#include<stdio.h>
#include<conio.c>
#include<string.h>
#include<stdlib.h>

#define N 100       /* stała określająca maksymalną długość wyrazu w pliku */

/* Struktura opisująca element listy jednokierunkowej                      */
struct wyraz
{
  char *slowo;           /* wskaźnik na początek łańcucha znakowego        */
  struct wyraz *nast;    /* wskaźnik na kolejny element listy              */
};

/* Funkcja dodająca na początek listy jednokierunkowej nowy element        */
/* i umieszczająca w nim określony wyraz                                   */
/* parametry:                                                              */
/*    _pocz - wskaźnik na pierwszy element listy                           */
/*    _slowo - wskaźnik na łańcuch znakowy zawierajacy wyraz z pliku       */
/* Funkcja zwraca 1 gdy dodanie elementu się powiodło lub 0, gdy alokacja  */
/* pamięci była niemozliwa                                                 */
int dodaj( struct wyraz **_pocz, char *_slowo )
{
  struct wyraz *pom;
  if( (pom = (struct wyraz *)malloc( sizeof( struct wyraz ) ) ) != NULL )
    if( (pom->slowo = (char *)malloc( strlen( _slowo ) + 1 ) ) != NULL )
    {
      strcpy( pom->slowo, _slowo );
      pom->nast = *_pocz;
      *_pocz = pom;
      return 1;
    }
    else
      return 0;
  else return 0;
}

/* Rekurencyjna funkcja usuwająca z pamięci operacyjnej strukturę listową  */
/* parametry:                                                              */
/*    _pom - wskaźnik na element do usunięcia                              */
/* Funkcja nie zwraca żadnej wartości                                      */
void usun( struct wyraz *_pom )
{
  if( _pom->nast != NULL )
    usun( _pom->nast );
  free( _pom->slowo );
  free( _pom );
}

/* Funkcja odczytująca z pliku tekstowego łańcuchy znakowe i umieszczająca */
/* je na liście jednokierunkowej                                           */
/* parametry:                                                              */
/*    _pocz - wskaźnik na pierwszy element listy                           */
/*    _nazwaPliku - wskaźnik na łańcuch znakowy zawierajacy nazwe pliku    */
/* Funkcja zwraca ilość odczytanych słów z pliku                           */
int czytaj( struct wyraz **_pocz, char *_nazwaPliku )
{
  FILE *plik;
  int licznik = 0;
  char bufor[N];

  plik=fopen( _nazwaPliku, "rt" );
  if( plik != NULL )
  {
    while( ! feof( plik ) )
    {
      fscanf(plik,"%s", &bufor);
      if( dodaj( _pocz, bufor ) )
        licznik ++;
      else
      {
        printf("Przydzielenie pamieci na dane do posortowania - nie powiodlo sie");
        break;
      }
    }
    fclose( plik );
  }
  return licznik;
}
 

/* Funkcja zapisująca do pliku tekstowego posortowane wyrazy               */
/* parametry:                                                              */
/*    _pocz - wskaźnik na pierwszy element listy wyrazów                   */
/*    _nazwaPliku - wskaźnik na łańcuch znakowy zawierajacy nazwe pliku    */
/* Funkcja zwraca wartość 0 gdy nie udało się utworzyć pliku               */
/* lub wartość 1, gdy plik został zapisany na dysku.                       */
int zapisz( struct wyraz *_pocz, char *_nazwaPliku )
{
  FILE *plik;
  struct wyraz *pom = _pocz;

  plik=fopen( _nazwaPliku, "wt" );
  if( plik != NULL )
  {
    while( pom != NULL )
    {
      fprintf(plik,"%s\n", pom->slowo);
      pom = pom->nast;
    }
    fclose( plik );
  }
  else
    return 1;
  return 0;
}
 

/* Funkcja obliczająca ilość elementów na liscie jednokierunkowe           */
/* parametr:                                                               */
/*    _pocz - wskaźnik na pierwszy element listy                           */
/* Funkcja zwraca ilość elementów listy                                    */
int dlugoscListy( struct wyraz *_pocz )
{
  int licznik = 0;
  while( _pocz != NULL )
  {
    _pocz = _pocz->nast;
    licznik++;
  }
  return licznik;
}
 

/* Funkcja sortująca wyrazy zgodnie z wybraną metodą                       */
/* parametry:                                                              */
/*    _pocz - wskaźnik na pierwszy element listy wyrazów                   */
/*    _method - numer metody sortowania                                    */
/* Funkcja nie zwraca żadnej wartości                                      */
void sortuj( struct wyraz *_pocz, int _method )
{

  struct wyraz *pom;
  char *tmp;
  int i, iloscWyrazow = dlugoscListy( _pocz );

  for( i=0; i<iloscWyrazow ;i++ )
  {
    pom = _pocz;
    while( pom != NULL && pom->nast != NULL )
    {
      switch( _method )
      {
        case 1: if( strcmp( pom->slowo, pom->nast->slowo ) > 0 )
                {
                  tmp = pom->nast->slowo;
                  pom->nast->slowo = pom->slowo;
                  pom->slowo = tmp;
                }
                break;
        case 2: if( strcmp( pom->slowo, pom->nast->slowo ) < 0 )
                {
                  tmp = pom->nast->slowo;
                  pom->nast->slowo = pom->slowo;
                  pom->slowo = tmp;
                }
                break;
        case 3: if( strlen( pom->slowo ) > strlen( pom->nast->slowo ) )
                {
                  tmp = pom->nast->slowo;
                  pom->nast->slowo = pom->slowo;
                  pom->slowo = tmp;
                }
                break;
        case 4: if( strlen( pom->slowo ) < strlen( pom->nast->slowo ) )
                {
                  tmp = pom->nast->slowo;
                  pom->nast->slowo = pom->slowo;
                  pom->slowo = tmp;
                }
                break;
      }
      pom = pom->nast;
    }
  }
}
 

/* Funkcja odczytująca z pliku tekstowego łańcuchy znakowe i umieszczająca */
/* je na liście jednokierunkowej                                           */
/* parametry:                                                              */
/*    brak                                                                 */
/* Funkcja zwraca ilość odczytanych słów z pliku                           */
int menu(void)
{
  int klawisz=0;

  clrscr();
  printf("1 - leksykograficznie, narastajaco\n");
  printf("2 - leksykograficznie, malejaco\n");
  printf("3 - wg dlugosci, narastajaco\n");
  printf("4 - wg dlugosci, malejaco\n");
  printf("");
  gotoxy( 20, 24 );
  printf("nacisnij klawisz 1, 2, 3 lub 4: ");

  do
    klawisz = getch();
  while( klawisz < 49 || klawisz > 52 );

  return klawisz-48;
}
 

/* Główna funkcja programu                                                 */
/* parametry:                                                              */
/*    ilePar - ilość łańcuchów znakowych w linii poleceń                   */
/*    tabPar - tablica wskaźników na łańcuchy znakowe z linii wywołania    */
/*             programu                                                    */
/* Funkcja zwraca:                                                         */
/* 0 - gdy program zakończył się prawidłowo,                               */
/* 1 - gdy podano niewłaściwą liczbę parametrów wywołania programu,        */
/* 2 - gdy nie znaleziono pliku z danymi wejściowymi                       */
/* 3 - gdy nie można było zapisać na dysku pliku wynikowego                */
main(int ilePar, char *tabPar[])
{
  struct wyraz *pocz = NULL;

  if( ilePar < 2 || ilePar > 3)
  {
    printf("Prawidlowe uruchomienie programu:\n");
    printf("Sort <nazwa_pliku_wejsciowego> [nazwa_pliku_wyjsciowego]\n");
    printf("gdzie:\n");
    printf("nazwa_pliku_wejściowego - nazwa pliku z wyrazami do posortowania\n");
    printf("nazwa_pliku_wyjściowego - nazwa pliku z posortowanymi wyrazami\n\n");
    return 1;
  }
  else
  {
    if( czytaj( &pocz, tabPar[1] ) )
    {
      sortuj( pocz, menu() );
      if( !zapisz( pocz, (ilePar==3)?tabPar[2]:"wynik.txt" ) )
      {
        printf("Zapis do pliku %s nie powiodl sie",
                  (ilePar==3)?tabPar[2]:"wynik.txt");
        return 3;
      }
      else
      {
        printf("Posortowane wyrazy zapisano w pliku %s ",
                  (ilePar==3)?tabPar[2]:"wynik.txt");
        return 0;
      }
    }
    else
    {
      printf("Nie znaleziono pliku z danymi: %s", tabPar[1]);
      getch();
      return 2;
    }
  }
}