PDA

View Full Version : [C] ordinamento lista e stampa su file


tenbota87
10-02-2011, 16:35
Salve a tutti!
Ho un problema..
In questo codice io devo leggere un file contenente parole delimitate da un numero variabile di spazi e devo creare un file contenente le parole e la loro relativa frequenza, in modo decrescente. La lettura da file dovrebbe avvenire in modo corretto, il problema sorge nell'ordinamento della lista e nella conseguente stampa su file.
Spero che ci sia qualche buon anima che mi possa rispondere e aiutare!
Grazie in anticipo..



#include <stdio.h> //Direttive al pre processore che ci permettono di includere
#include <string.h> //gli haeder file,relativi a librerie standar.
#include <stdlib.h>
#include <limits.h>
#include <assert.h>


// definizione della funzione ASSERT() con stampa di un messaggio di errore
#define ASSERT( condizionedaverificare, cosafare ) { if ( !(condizionedaverificare) ) { printf cosafare; printf("\n"); assert( condizionedaverificare ); } }



struct lista{ //Dichiarazione della lista usata dalla funzione aggiuntiva
char parola[257]; //Dichiarazione di un array di lunghezza massima 1024 adibito a contenere la parola
int frequenza; //Dichiarazione di una varibile adibita a contenere la frequenza della parola
struct lista *next; //Dichiarazione di un puntatore per lo spostamento all'interno della lista
};



int main(int argc, char *argv[])
{
char *nomeDelFile=NULL; //puntatore al nome del file da comprimere o decomprimere
char *centoParole=NULL;

char *pra=NULL;
FILE *fileTesto=NULL;
FILE *fpw=NULL ;
int contaLettere=0;
int numero_parole=0;
int massimo=0;
char bufferLettura[256];
struct lista *nuovo=NULL;
struct lista *testa=NULL;
struct lista *temp=NULL;
struct lista *prev=NULL;
struct lista *canc=NULL;



if(argc!=2) //controllo sul numero di parametri per far partire il programma che devono essere: <nome programma> <nome file>
{
printf("\nErrore!Indicare il nome del file da comprimere o da decomprimere\n");
exit(1);
}

nomeDelFile=argv[1]; //copio il contenuto di argv[1] che contiene il nome del file da comprimere/decomprimere


centoParole = (char*)malloc(sizeof(char)*(strlen(nomeDelFile)+7));
strncpy(centoParole,nomeDelFile,strlen(nomeDelFile));
strncat(centoParole,".world\0",7);




fileTesto=fopen(nomeDelFile,"r"); //apertura del file di testo in modalità lettura

fpw=fopen(centoParole,"w"); //apertura del file di testa in cui devo andare a scrivere
assert(fpw != NULL);


while(!feof(fileTesto))
{
//trovato=0;
contaLettere=0; //Indicizzazione a 0 della variabile i


pra = (char*)malloc( 256 * sizeof(char));
memset(pra,0,256 * sizeof(char));

fscanf(fileTesto,"%s", pra);
strcpy(bufferLettura,pra);
//printf("\n Parola: %s",bufferLettura);
contaLettere=strlen(bufferLettura);
free(pra);
if(contaLettere<256)
{
bufferLettura[contaLettere]='\0';
}
else
{
bufferLettura[0]='\0';
}



if(bufferLettura[0]!='\0') //guardare soluzioni alternative per parole maggiori di 256 caratteri
{ //printf("\n 10 \n");

prev = NULL;
temp=testa;
while((temp != NULL) && (strcmp(bufferLettura,temp->parola) != 0)){

prev = temp;
temp = temp->next; //Incremento il puntatore per avanzare nella scansione della lista

}


if (temp == NULL)
{
// printf("\n 17 dentro\n");
nuovo=(struct lista*)malloc(sizeof(struct lista)); //Allocazione dinamica della memoria di una nuova cella della lista tramite la funzione malloc
strncpy(nuovo->parola,bufferLettura,contaLettere);
// printf("\n 18 dentro\n");
nuovo->frequenza=1; //Impostazione della frequenza della parola a 1
nuovo->next = NULL;
if (testa != NULL)
prev->next = nuovo;
else testa = nuovo;
// printf("\n 18 dentro\n");
// printf("\nPrima Parola in lista:%s \n",nuovo->parola);
// printf("\n 18 dentro\n");
// printf("\nFrequenza in lista:%d \n",nuovo->frequenza);
}
else temp->frequenza++;
}
}


temp=testa;

if(testa==NULL)
{
fclose(fpw);
exit(0);
}
else
{
while(temp != NULL && numero_parole <= 100 )
{
massimo=0;
while(temp != NULL) //ciclo per trovare il massimo
{
if(temp->frequenza > massimo)
{
massimo=temp->frequenza;
}
temp=temp->next;
}

temp=testa;

while(temp != NULL)
{
if(temp->frequenza == massimo)
{
fprintf(fpw,"%d %s \r\n",temp->frequenza,temp->parola);
numero_parole++;
prev->next=temp->next;
canc=temp;
temp=temp->next;
free(canc);

}
else
{
prev=temp;
temp=temp->next;
}



}

}
}

fclose(fileTesto);
fclose(fpw);

return 0;
}

IceCoder
11-02-2011, 09:03
Stando a quello che ho capito tu non usi un debugger o non sai proprio cosa sia.. quale IDE usi? (IDE = (in maniera molto rozza) programma in cui scrivi il codice)

tenbota87
11-02-2011, 09:38
Il programma che uso per scrivere il codice è il Notepad++,un software che è utile per scrivere in tutti i linguaggi,visto che evidenzia tutte le parole chiave utilizzate a seconda del linguaggio che scegli, e lo vado a compilare ed eseguire con il cygwin.come debug uso il gdb ma non è facile per niente,poco intuitivo e,magari è una motivazione banale,esteticamente orrendo quindi mi aiuto utilizzando i printf per visualizzare a video dove il programma si blocca.

sei comunque in grado di aiutarmi? :confused:

IceCoder
11-02-2011, 10:59
Ci sono molte imprecisioni, a partire dall'uso di strncpy() fino all'uso dei puntatori che fa andare il programma in un loop infinito (a quanto sembra fin ora)..

Io ti consiglierei di iniziare con Visual C++ Express che è gratuito e ti fornisce un ottimo debugger semplicissimo da usare (clicchi all'inizio della linea ed il programma si bloccherà li fornendoti tutti i dati necessari) per poi passare a qualcosa di meglio..

Una nota finale da fare è sul'impostazione del codice un po' troppo disordinata.. Ad una funzione deve corrispondere un solo scopo, cosi ti faciliti il lavoro di almeno 100 volte (in progetti piu complessi).

Vedo un po' di risolvere, dammi qualche minuto, sto facendo anche altre cose e sono un po' impegnato :)

IceCoder
11-02-2011, 11:26
#include <stdio.h> //Direttive al pre processore che ci permettono di includere
#include <string.h> //gli haeder file,relativi a librerie standar.
#include <stdlib.h>
#include <limits.h>
#include <assert.h>


// definizione della funzione ASSERT() con stampa di un messaggio di errore
#define ASSERT( condizionedaverificare, cosafare ) { if ( !(condizionedaverificare) ) { printf cosafare; printf("\n"); assert( condizionedaverificare ); } }



struct lista{ //Dichiarazione della lista usata dalla funzione aggiuntiva
char parola[257]; //Dichiarazione di un array di lunghezza massima 1024 adibito a contenere la parola
int frequenza; //Dichiarazione di una varibile adibita a contenere la frequenza della parola
struct lista *next; //Dichiarazione di un puntatore per lo spostamento all'interno della lista
};



int main(int argc, char *argv[])
{
char *nomeDelFile=NULL; //puntatore al nome del file da comprimere o decomprimere
char *centoParole=NULL;

char *pra=NULL;
FILE *fileTesto=NULL;
FILE *fpw=NULL ;
int contaLettere=0;
int numero_parole=0;
int massimo=0;
char bufferLettura[256];
struct lista *nuovo=NULL;
struct lista *testa=NULL;
struct lista *temp=NULL;
struct lista *prev=NULL;
struct lista *canc=NULL;



if(argc!=2) //controllo sul numero di parametri per far partire il programma che devono essere: <nome programma> <nome file>
{
printf("\nErrore!Indicare il nome del file da comprimere o da decomprimere\n");
exit(1);
}

nomeDelFile=argv[1]; //copio il contenuto di argv[1] che contiene il nome del file da comprimere/decomprimere


centoParole = (char*)malloc(sizeof(char)*(strlen(nomeDelFile)+7));
strncpy(centoParole,nomeDelFile,sizeof(char)*(strlen(nomeDelFile)+7)); //ICE: Impostata formula corretta per il terzo parametro
strncat(centoParole,".world",6); //ICE: Eliminato il carattere '\0' alla fine, viene aggiunto in automatico durante la compilazione




fileTesto=fopen(nomeDelFile,"r"); //apertura del file di testo in modalità lettura

fpw=fopen(centoParole,"w"); //apertura del file di testa in cui devo andare a scrivere
assert(fpw != NULL);


while(!feof(fileTesto))
{
//trovato=0;
contaLettere=0; //Indicizzazione a 0 della variabile i


pra = (char*)malloc( 256 * sizeof(char));
memset(pra,0,256 * sizeof(char));

fscanf(fileTesto,"%s", pra);

//ICE: Inizio codice aggiunto
if(pra[0] == 0) //Non è stato letto alcun carattere, il file è finito.
{
free(pra);
break;
}

//ICE: Fine codice aggiunto

strcpy(bufferLettura,pra);
//printf("\n Parola: %s",bufferLettura);
contaLettere=strlen(bufferLettura);
free(pra);
if(contaLettere<256)
{
bufferLettura[contaLettere]='\0';
}
else
{
bufferLettura[0]='\0';
}



if(bufferLettura[0]!='\0') //guardare soluzioni alternative per parole maggiori di 256 caratteri
{ //printf("\n 10 \n");

prev = NULL;
temp=testa;
while((temp != NULL) && (strcmp(bufferLettura,temp->parola) != 0)){

prev = temp;
temp = temp->next; //Incremento il puntatore per avanzare nella scansione della lista

}


if (temp == NULL)
{
// printf("\n 17 dentro\n");
nuovo=(struct lista*)malloc(sizeof(struct lista)); //Allocazione dinamica della memoria di una nuova cella della lista tramite la funzione malloc
strncpy(nuovo->parola,bufferLettura,257); //ICE: il terzo argomento di strncpy() deve essere la lunghezza TOTALE della stringa IN CUI vuoi copiare il contenuto della seconda stringa
// printf("\n 18 dentro\n");
nuovo->frequenza=1; //Impostazione della frequenza della parola a 1
nuovo->next = NULL;
if (testa != NULL)
prev->next = nuovo;
else testa = nuovo;
// printf("\n 18 dentro\n");
// printf("\nPrima Parola in lista:%s \n",nuovo->parola);
// printf("\n 18 dentro\n");
// printf("\nFrequenza in lista:%d \n",nuovo->frequenza);
}
else temp->frequenza++;
}
}


temp=testa;

if(testa==NULL)
{
fclose(fpw);
exit(0);
}
else
{
while(temp != NULL && numero_parole <= 100 )
{
massimo=0;
while(temp != NULL) //ciclo per trovare il massimo
{
if(temp->frequenza > massimo)
{
massimo=temp->frequenza;
}
temp=temp->next;
}

temp=testa;

while(temp != NULL)
{
if(temp->frequenza == massimo)
{
fprintf(fpw,"%d %s \r\n",temp->frequenza,temp->parola);
numero_parole++;
//prev->next=temp->next; //ICE: Commentata questa linea che causava un loop infinito (prev puntava al penultimo elemento della lista che veniva così una lista ciclicamente collegata)
canc=temp;
temp=temp->next;
free(canc);

}
else
{
prev=temp;
temp=temp->next;
}



}

}
}

fclose(fileTesto);
fclose(fpw);

return 0;
}



Ecco fatto, se hai altre domande chiedi pure ;)

tenbota87
11-02-2011, 13:57
Un problema grosso me l'hai risolto,grazie mille,però quello di cui ho bisogno,e non riesco proprio a fare,è la stampa delle 100 parole più frequenti,non solo la più frequente..e nel caso la 101esima parola e successive abbiano frequenza uguale alla 100esima devono essere stampate tutte,per questo facevo il ciclo:

while(temp != NULL && numero_parole <= 100 )


grazie ancora per il tuo prezioso aiuto!!! :D

tenbota87
15-02-2011, 10:52
non c'è proprio nessuno che è in grado di aiutarmi per favore?!
:help: :(