001: #include<stdio.h>
002: #include<stdlib.h>
003: #include<string.h>
004: 
005: // struct per memorizzare coppie di parole
006: // di fatto si usera' un array di quese struct man mano allocato dinamicamente
007: // del tutto lecito sarebbe stato anche usare un semplice array di stringhe in cui all'indice pari trovavo una delle parole della coppia
008: // e al consecutivo indice dispari l'altra
009: struct coppia
010: {
011:   char *parola1;
012:   char *parola2;
013: };
014: 
015: // funzioni che uso come da testo, passo ogni volta una singola coppia
016: int check_palindromi(struct coppia);
017: int check_anagrammi(struct coppia);
018: 
019: int main(int argc, char **argv){
020: 
021:   FILE *fp = fopen("parole.txt", "r");
022:   if(!fp)
023:   {
024:     perror("");
025:     exit(EXIT_FAILURE);
026:   }
027: 
028:   char tmp1[1000], tmp2[1000]; // array temporanei per lettura coppia
029: 
030:   // inizializzo array vuoto di "coppie", non basta il puntatore mna occorre anche un int che mi tiene traccia del numero di coppie lette
031:   struct coppia *parole = NULL;
032:   int ncoppie = 0;
033: 
034:   // leggo una riga sfruttando i due temporeanei, termino quando non riesco piu' a leggere niente
035:   while(fscanf(fp, " %s %s", tmp1, tmp2) == 2)
036:   { 
037:     // incremento il numero di coppie
038:     ++ncoppie;
039:     // "allargo" l'array dui struct per ospitare la nuova coppia di parole
040:     parole = realloc(parole, sizeof(struct coppia)*ncoppie);
041:     // per il nuovo elemento dell'array, alloco spazio a sufficienza nei due elementi per poter ospitare le due parole lette
042:     parole[ncoppie - 1].parola1 = malloc(strlen(tmp1) + 1);
043:     parole[ncoppie - 1].parola2 = malloc(strlen(tmp2) + 1);
044:     // e ve le copio
045:     strcpy(parole[ncoppie - 1].parola1, tmp1);
046:     strcpy(parole[ncoppie - 1].parola2, tmp2);
047:   }
048:   fclose(fp);
049: 
050:   // scorro array di coppie
051:   for(int i = 0; i < ncoppie; ++i)
052:   {
053:     printf("La coppia '%s' '%s' ", parole[i].parola1, parole[i].parola2);
054:     // chiamo prima funzione e memorizzo valore restituito
055:     int pal = check_palindromi(parole[i]);
056:     // in base a valore stampo messaggio opportuno
057:     if(pal == 2 )
058:       printf("contiene 2 parole palindrome ");
059:     else if(pal == 1)
060:       printf("contiene 1 parola palindroma ");
061:     else
062:       printf("non contiene parole palindrome ");
063: 
064:     // come nel caso precedente per gli anagrammi
065:     if(check_anagrammi(parole[i]))
066:       printf("e sono anagrammi una dell'altra\n");
067:     else
068:       printf("\n");
069: 
070:   }
071: 
072: 
073: 
074:   return 0;
075: }
076: 
077: // funzione ricorsiva che controlla se una singola stringa e' palindroma
078: // passo indirizzo stringa e lunghezza del numero di caratteri da controllare
079: int palindroma(char *parola, int lungh)
080: {
081:   // se la stringa e' vuota o e' formata da un solo carattere la considero palindroma
082:   if(lungh == 1 || lungh == 0)
083:     return 1;
084: 
085:   // se il primo e l'ultimo carattere sono differenti non e' sicuramente palindroma
086:   if(parola[0] != parola[lungh-1])
087:     return 0;
088: 
089:   // richiamo funzione passando sottostringa che parte dal carattere successivo e un cui non considero anche l'ultimo carattere
090:   return palindroma(parola + 1, lungh - 2);
091: }
092: 
093: 
094: // controllo palindromi sfruttando la funzione precedente
095: int check_palindromi(struct coppia c)
096: {
097:   return palindroma(c.parola1, strlen(c.parola1)) + palindroma(c.parola2, strlen(c.parola2));
098: }
099: 
100: // classica funzione necessaria per la qsort() gia' vista a lezione
101: int confronta_caratteri(const void *a, const void *b)
102: {
103:   char ca = *((char *)a);
104:   char cb = *((char *)b);
105: 
106:   return ca - cb;
107: }
108: 
109: // se due parole sono anagrammi contengono le stesse identiche lettere solo distribuite
110: // diversamente
111: // questa funzione ordina i caratteri delle due stringhe in ordine alfabetico, se sono anagrammi una dell'altra
112: // otterro' due stringhe identiche
113: int check_anagrammi(struct coppia c)
114: {
115:   // uso qsort per ordinare due stringhe ovvero due array di char
116:   qsort(c.parola1, strlen(c.parola1), sizeof(char), confronta_caratteri);
117:   qsort(c.parola2, strlen(c.parola2), sizeof(char), confronta_caratteri);
118:   // controllo se dopol'ordinamento sono o meno identiche
119:   if(!strcmp(c.parola1, c.parola2))
120:     return 1;
121:   else // a rigore non necessario ma comunque piu' chiaro
122:     return 0;
123: }
124: