Lista parole in ordine alfabetico in C

di il
6 risposte

Lista parole in ordine alfabetico in C

Salve, avevo il compito di modificare il seguente programma:

#include <stdio.h>
#include <math.h>

#define MY_MAX 100

#define MY_SUCCESS 0
#define MY_RUIN -9

FILE *fInput;
char *fInputName = "leopardi.dat";

void myStart(void);
void openFile(void);

struct word{
  char *pointerToString;
  struct word *nextWordLeft;
  struct word *nextWordRight;
};
struct fromWord{
  int myEnd;
  char *scratchPointer;
};

struct fromWord readWord(void);
struct word *addToTree(struct word *, char *);
void printTreeInAlphabeticOrder(struct word *);

/*****************************************************************************/
int main(void)
{
  struct fromWord fW1;
  
/* creo la lista e visto che all'inizio e' vuota la inizializzo a NULL */
  struct word *treeRoot = NULL;

  myStart();
  openFile();
  
  fW1.myEnd = 0;
  while(fW1.myEnd != 1){
    fW1 = readWord();
    treeRoot = addToTree(treeRoot, fW1.scratchPointer); 
  } 
  fclose(fInput);
  printTreeInAlphabeticOrder(treeRoot); 
}

/*****************************************************************************/
void myStart(void)
{
  printf("# Costruiremo un albero binario\n");
}

/*****************************************************************************/
void openFile(void)
{
  fInput = fopen(fInputName,"r");
  if(fInput == NULL){
    printf("abort: impossibile aprire il file di input"
	   " in lettura: %s\n",
	   fInputName); 
    exit(MY_RUIN);
  }
  printf("# E' stato aperto il file di input: %s\n",
	 fInputName); 
}

/*****************************************************************************/
struct fromWord readWord(void)
{
  int j = 0;
  char myString[MY_MAX], myFlag = 1;
  char *thisPointer;
  struct fromWord fW1;

  while((j < MY_MAX) && (myFlag == 1)){ 
    myString[j] = fgetc(fInput);
    if(myString[j] == ' '){
      myString[j] = '\0';
      myFlag = 0;
    }
    else if(myString[j] == '\n'){
      j--;
    }
    else if(myString[j] == EOF){
      fW1.myEnd = 1; 
      myString[j] = '\0'; 
      myFlag = 0;
    }
    j++;
  }

  /* per sicurezza mi sto riservando un carattere in piu' oltre 
    al terminatore \0 */
  if(j >= MY_MAX - 1){
    printf("Interruzione del programma: la parola era troppo lunga.\n");
    printf("Ricompilare con un valore di MY_MAX piu grande, era %d.\n",
	   MY_MAX);
    exit(MY_RUIN);
  }
  thisPointer = (char *) malloc(strlen(myString) + 1);
  if(thisPointer == NULL){
    printf("Interruzione del programma: fallita malloc 1\n");
    exit(MY_RUIN);
  }
  strcpy(thisPointer, myString);
  fW1.scratchPointer = thisPointer;
  /* printf("Parola di lunghezza %d: %s\n",strlen(thisPointer),thisPointer); */

  return fW1;
}

/*****************************************************************************/
struct word* addToTree(struct word* inputWord, 
		       char *localPointer)
{
  int stringDifference;
  if(inputWord == NULL){
    inputWord = 
      (struct word *) malloc(sizeof(struct word));  
    if(inputWord == NULL){
      printf("Interruzione del programma: fallita malloc 1\n");
      exit(MY_RUIN);
    }
    inputWord->pointerToString = localPointer;
    inputWord->nextWordLeft = NULL;
    inputWord->nextWordRight = NULL;
  } else if((stringDifference = 
	     strcmp(inputWord->pointerToString,   
		    localPointer)) != 0){
    if(stringDifference > 0) {
      inputWord->nextWordLeft = 
	addToTree(inputWord->nextWordLeft,localPointer);
    } else {
      inputWord->nextWordRight =
	addToTree(inputWord->nextWordRight, localPointer);
    }
  } 
  return inputWord;
}

/*****************************************************************************/
void printTreeInAlphabeticOrder(struct word* inputWord)
{
  if(inputWord != NULL){
    printTreeInAlphabeticOrder(inputWord->nextWordLeft);
    printf("%s\n",inputWord->pointerToString);
    printTreeInAlphabeticOrder(inputWord->nextWordRight);
  }
}
Questo programma riceve parole in input da file e le ristampa in ordine alfabetico, tuttavia non tiene conto della differenza tra caratteri alfabetici e non, non riconosce maiuscole e minuscole e poi aveva problemi quado si va a capo.
Il mio compito è stato di modificarlo, e ho pensato di fare cosi:
#include <stdlib.h>
#include <string.h>
#include <stdio.h>

#define MY_MAX 100

#define MY_SUCCESS 0
#define MY_EXIT_FAILURE -9

FILE *fInput;
char *fInputName = "leopardi.dat";

void openFile(void);

struct word{
  char *pointerToString;
  struct word *nextWordLeft;
  struct word *nextWordRight;
};
struct fromWord{
  int myEnd;
  char *scratchPointer;
};

struct fromWord readWord(void);
struct word *addToTree(struct word *, char *);
void printTreeInAlphabeticOrder(struct word *);

/*****************************************************************************/
int main(void)
{
  struct fromWord fW1;

  struct word *treeRoot = NULL;

  openFile();
  
  fW1.myEnd = 0;
  while(fW1.myEnd != 1){
    fW1 = readWord();
    treeRoot = addToTree(treeRoot, fW1.scratchPointer); 
  } 
  fclose(fInput);
  printTreeInAlphabeticOrder(treeRoot); 
}

/*****************************************************************************/

void openFile(void)
{
  fInput = fopen(fInputName,"r");
  if(fInput == NULL){
    printf("Impossiible aprire il file\n");
    exit(MY_EXIT_FAILURE);
  }
  printf("# E' stato aperto il file di input: %s\n",fInputName); 
}

/*****************************************************************************/
struct fromWord readWord(void)
{
  int j = 0, alphabetic = 0;
  char myString[MY_MAX], myFlag = 1;
  char *thisPointer;
  struct fromWord fW1;

  while((j < MY_MAX) && (myFlag == 1)){ 
    myString[j] = fgetc(fInput);
    if( (myString[j] >= 'a' && myString[j] <= 'z') || (myString[j] >= 'A' && myString[j] <= 'Z') ) {
      alphabetic = 1;
    }

    if ((myString[j] >= 'A' && myString[j] <= 'Z')) {
      myString[j] += 32;
    }

    else if (alphabetic != 1) {
      if(myString[j] == EOF){
        fW1.myEnd = 1; 
        myString[j] = '\0'; 
        myFlag = 0;
      }

      else if (myString[j] == 133 || myString[j] == 160 || myString[j] == 181 || myString[j] == 183) {
        myString[j] = 97;
      }
      else if (myString[j] == 130 || myString[j] == 138 || myString[j] == 212) {
        myString[j] = 101;
      }
      else if (myString[j] == 141 || myString[j] == 161) {
        myString[j] = 105;
      }
      else if (myString[j] == 149 || myString[j] == 162) {
        myString[j] = 111;
      }
      else if (myString[j] == 151 || myString[j] == 163) {
        myString[j] = 117;
      }
      
      else {
        myString[j] = '\0';
        myFlag = 0;
      }
    }
    j++;
    alphabetic = 0;
  }

  if(j >= MY_MAX - 1){
    printf("Interruzione del programma: la parola era troppo lunga, ti sei addormentato sulla tastiera scrivendo il file?\n");
    exit(MY_EXIT_FAILURE);
  }
  thisPointer = (char *) malloc(strlen(myString) + 1);
  if(thisPointer == NULL){
    printf("Interruzione del programma: fallita malloc di thisPointer\n");
    exit(MY_EXIT_FAILURE);
  }
  strcpy(thisPointer, myString);
  fW1.scratchPointer = thisPointer;

  return fW1;
}

/*****************************************************************************/
struct word* addToTree(struct word* inputWord, char *localPointer)
{
  int stringDifference;
  if(inputWord == NULL){
    inputWord = 
      (struct word *) malloc(sizeof(struct word));  
    if(inputWord == NULL){
      printf("Interruzione del programma: fallita malloc di inputWord\n");
      exit(MY_EXIT_FAILURE);
    }
    inputWord->pointerToString = localPointer;
    inputWord->nextWordLeft = NULL;
    inputWord->nextWordRight = NULL;
  } 
  else if((stringDifference = strcmp(inputWord->pointerToString, localPointer)) != 0){
    if(stringDifference > 0) {
      inputWord->nextWordLeft = addToTree(inputWord->nextWordLeft,localPointer);
    } 
    else {
      inputWord->nextWordRight = addToTree(inputWord->nextWordRight, localPointer);
    }
  } 
  return inputWord;
}

/*****************************************************************************/
void printTreeInAlphabeticOrder(struct word* inputWord)
{
  if(inputWord != NULL){
    printTreeInAlphabeticOrder(inputWord->nextWordLeft);
    printf("%s\n",inputWord->pointerToString);
    printTreeInAlphabeticOrder(inputWord->nextWordRight);
  }
}
In pratica la modifica è stata solo su readword() e ho inserito alcune istruzioni al preprocessore che non so perchè non fossero inserisce. L'unico problema rimane con le lettere accentate, anzichè sostituirle con il carattere non accentato mi inserire il terminatore di stringa, come posso risolvere?

6 Risposte

  • Re: Lista parole in ordine alfabetico in C

    Per le lettere accentate usa la libreria #include <locale.h>

    e all'inizio del main

    setlocale(LC_ALL, "");
  • Re: Lista parole in ordine alfabetico in C

    Ho provato ad esempio facendo setlocale(LC_ALL, "ì"); ma non va, continua a stamparmi il terminatore nullo
  • Re: Lista parole in ordine alfabetico in C

    Prova a risolvere l'esercizio per i soli caratteri ASCII. Le lettere accentate tirano in ballo le codifiche. Non penso che siano lo scopo dell'esercizio, e poi il C non è il linguaggio adatto per queste cose
  • Re: Lista parole in ordine alfabetico in C

    Gli altri problemi mi sembrano risolti. Quindi cosa dovrei fare con le parole accentate, metto '\0' al posto di esse?
  • Re: Lista parole in ordine alfabetico in C

    Usa un testo di esempio in inglese, non Leopardi. Oppure metti 'e' seguito da ''', ad esempio, con tutta la gestione del caso.
    La soluzione con le lettere accentate completa richiede una revisione del tuo codice in base a una serie di considerazioni che non hai fatto: 133 è 'à' in extended ASCII, e se il tuo file fosse in UTF-8? Il tuo terminale come è impostato invece?
  • Re: Lista parole in ordine alfabetico in C

    Il file è UTF-8 e il terminale dovrebbe essere impostato con encoding UTF-8
Devi accedere o registrarti per scrivere nel forum
6 risposte