Ho modificato il codice:
siccome devo stampare le parole in ordine di occorrenza crescente
(prima quelle che compaiono di meno, poi via via quelle più frequenti), ho introdotto l'algoritmo di ordinamento radix-sort che permette di ordinare la lista in ordine crescente, in modo da stampare la lista delle parole con l'ordine giusto.
Nonostante questo ho un problema di compilazione e non riesco a trovare l'errore. L'algoritmo sembra corretto e non riesco a capire cosa abbia sbagliato. Se qualcuno può darmi una mano lo ringrazio davvero tantissimo.
codice:#include <stdlib.h> #include <stdio.h> #include <string.h> #include <ctype.h> //Queste due costanti servono per l'ordinamento radix sort: #define RADICE_SIZE 10 //numero di cifre del sist. decimale #define MAX_CIFRE 3 //numero di cifre da 0 a 999 //Mantiene le frequenze delle lettere int freqLettere['z' - 'a' + 1]; //Array di dimensione 26 (numero di lettere dell'alfabeto) //Mantiene le frequenze dei numeri int freqNumeri[10]; //Dimensione 10 per prendere in considerazione i numeri del sistema decimale //Mantiene il numero totale di caratteri trovati nel testo (lettere e numeri) int totaleCaratteri = 0; //Mantiene il numero totale di parole trovate nel testo int totaleParole = 0; //Definizione dell'elemento di una lista typedef struct list *lista; typedef struct list{ char *parola; int frequenza[MAX_CIFRE]; list *next; }list; //Variabile che mantiene le lista di parole lista parole = NULL; //Inizializza a zero i vettori delle frequenze (lettere e numeri) void inizializza(){ int i; for(i = 0; i < 10; i++) freqNumeri[i] = 0; for(i = 0; i < ('z' - 'a' + 1); i++) freqLettere[i] = 0; } //Aggiorna le frequenze di lettere e numeri void aggiornaFrequenze(char *parola) { int i; char c; int len = strlen(parola); //Memorizza la dimensione di char della parola corrente for(i = 0; i < len; i++) { c = parola[i]; //Memorizza in c la parola corrente //isalpha restituisce un valore diverso da zero se e è una lettera (maiuscola o minuscola) if(isalpha(c)) { //la funzione tolower rende tutte le lettere minuscole c = tolower(c); //incrementiamo la posizione corrispondente di freqLettere freqLettere[c - 'a']++; } //isdigit controlla se il carattere corrente è un numero (in tal caso restituisce un valore diverso da 0) if(isdigit(c)) { //incrementiamo la posizione corrispondente di freqLettere freqNumeri[c - '0']++; } } //Incremento il numero di parole totali totaleParole++; //Incremento il numero di caratteri totali totaleCaratteri = totaleCaratteri + len; } //Restituisce la prossima parola che si trova in testo a partire //dalla posizione posizioneCorrente. Una parola è definita come //una sequenza di lettere e/o numeri senza altri caratteri. //Restituisce NULL se non c'è una prossima parola char *prossimaParola(char *testo) { static int posizioneCorrente = 0; int i; int len = strlen(testo); //len rappresenta il numero dei caratteri presenti nel testo //mi sposto avanti finche non trovo una lettera o un numero while(! isalnum(testo[posizioneCorrente])) { //isalnum restituisce un valore diverso da zero se ciò che analizziamo è un carattere alfanumerico posizioneCorrente++; //se sono alla fine senza aver trovato lettere o numeri ritorno null if(posizioneCorrente >= len) return NULL; } //incremento i finchè trovo numeri e lettere; alla fine del cilco //i punta alla fine della parola corrente i = posizioneCorrente; //in i si registra l'indice dell'array in cui inizia la prima frase del testo while(isalnum(testo[i]) && (i < len)) i++; //i adesso assume il valore dell'indice dell'array che rappresenta la fine della parola int lunghezza = i - posizioneCorrente; //lunghezza è la lunghezza di caratteri della parola considerata char *parola = (char *)malloc((lunghezza + 1)); for(i = 0; i <= lunghezza; i++) parola[i] = testo[posizioneCorrente + i]; //su parola viene memorizzata la parola corrente //Inserisco il carattere di fine stringa alla fine della parola parola[lunghezza] = '\0'; posizioneCorrente = posizioneCorrente + i; //riprende dalla fine della parola return parola; } void stampaNumeri(){ printf("\n\n"); int i; for(i = 0; i < 10; i++) printf("\nfrequenza di %d: %d", i, freqNumeri[i]); } void stampaLettere(){ printf("\n\n"); int i; for(i = 0; i < ('z' - 'a' + 1); i++) printf("\nfrequenza di %c: %d", 'a' + i, freqLettere[i]); } void stampaParole(){ printf("\n\n"); lista temp = parole; while(temp){ printf("\nfrequenza di %s: %d", temp->parola, temp->frequenza[0]); temp = temp -> next; } } //Inserisce la parola nella lista parole, se non è gia presente, //altrimenti incrementa la sua frequenza void inserisciParola(char *parola){ lista temp = parole; //Scorriamo la lista per vedere se la parola è ia stata inserita while(temp){ //Se la parola già c'è ci limitiamo a incrementare //la frequenza if(strcmp(temp -> parola, parola) == 0) //se strcmp restituisce 0 le stringhe sono uguali { temp->frequenza[2] = temp->frequenza[2]%RADICE_SIZE; temp->frequenza[1]=(temp->frequenza[1] % (RADICE_SIZE*RADICE_SIZE))/RADICE_SIZE; temp->frequenza[0]=(temp->frequenza[0] % (RADICE_SIZE*RADICE_SIZE*RADICE_SIZE))/(RADICE_SIZE*RADICE_SIZE); return; } temp = temp -> next; } //Se la parola non è stata trovata, creiamo un nuovo elemento //che sarà inserito in testa alla lista. temp = (lista )malloc(sizeof(lista)); temp -> parola = parola; temp -> frequenza[0] = 1; temp -> next = parole; //Facciamo puntare la lista 'parole' all'elemento di testa //appena isnerito parole = temp; } /*questa funzione crea dei "recipienti" per rappresentare il valore delle chiavi (sono 10 recipienti, da 0 a 9). Visto che un numero intero è costituito da più cifre ordinate dalla meno significativa, in ultima posizione, alla più significativa, in prima posizione (000, 001, 002,..., 010,...,100,..., 999) e ogni cifra K si trova nell'intervallo 0 <= k <= 9 ,in questo tipo di ordinamento la chiave di ordinamento viene scomposta in cifre utilizzando una radice RADICE_SIZE*/ lista radice_sort(lista ptr) { lista davanti[RADICE_SIZE], dietro[RADICE_SIZE]; int i, j, cifra; for(i=MAX_CIFRE-1;i>=0;i--) { for(j=0;j<RADICE_SIZE;j++) davanti[j] = dietro[j] = NULL; //i recipienti sono //implementati come code di dati: davanti[i] punta al primo //record nel recipiente i, mentre dietro[i] punta all'ultimo //record nel recipiente i. while(ptr) { cifra = ptr->frequenza[i]; if(!davanti[cifra]) davanti[cifra] = ptr; else dietro[cifra]->next = ptr; dietro[cifra] = ptr; ptr = ptr->next; } ptr = NULL; for(j=RADICE_SIZE-1;j>=0;j--) { if(davanti[j]) { dietro[j]->next = ptr; ptr = davanti[j]; } } } return ptr; } int main(){ char * p; char *testo = "ciao\tt\n1r&7 (re)re t zz"; while((p = prossimaParola(testo))){ aggiornaFrequenze(p); inserisciParola(p); } stampaNumeri(); stampaLettere(); parole = radice_sort(parole); stampaParole(); printf("\n\nTotale parole: %d", totaleParole); printf("\n\nTotale caratteri: %d", totaleCaratteri); fflush(stdin); getchar(); }

Rispondi quotando