|
|
|
![]() |
|
Strumenti |
![]() |
#1 |
Member
Iscritto dal: May 2010
Messaggi: 126
|
[C/C++]Costruire lista da file
Ciao ragazzi..scrivo perchè ho un problema sul leggere il contenuto di un file e metterlo su una lista concatenata semplice.
Il file di testo è strutturato così: Codice:
"luca","pippo","marco","etc...",... ... ... Codice:
#include <iostream> #include <fstream> #include <string.h> #include <malloc.h> using namespace std; struct nome { char *p; nome* succ; }; typedef nome Tnome; Tnome* CreaLista(); void Inizializza(char array[],int dim); void Inserisci(Tnome* &lista,char buffer[]); void StampaLista(Tnome* lista); void OrdinaLista(Tnome* &lista); void Scambia(char* str1[],char* str2[]); int main() { int prova=0; char buffer[100]; char c; int contavirgolette = 0; int k=0; Tnome *nomipropri; ifstream testo; testo.open("prova.txt",ios::in); nomipropri = CreaLista(); while(!testo.eof()) { while(contavirgolette<2) { c = testo.get(); if (c!='"') buffer[k++] = c; else contavirgolette++; } buffer[k]=0; k = 0; prova++; contavirgolette = 0; Inserisci(nomipropri,buffer); Inizializza(buffer,100); c = testo.get(); } testo.close(); StampaLista(nomipropri); } Tnome* CreaLista() { return NULL; } void Inserisci(Tnome* &lista,char buffer[]) { int i; Tnome *supporto; supporto = (Tnome*) calloc(1,sizeof(Tnome)); supporto->succ=lista; supporto->p = (char*)calloc(strlen(buffer)+1,sizeof(char)); for(i=0;buffer[i]!='\0';i++) supporto->p[i] = buffer[i]; supporto->p[i] = 0; lista=supporto; } void Inizializza(char array[],int dim) { int i; for(i=0;i<dim;i++) array[i]=0; } void StampaLista(Tnome* lista) { while(lista!=NULL) { cout << lista->p << endl; lista = lista->succ; } } ![]() Potreste aiutarmi? Vi allego anche il file .. testo.zip Grazie.
__________________
Il mio pc: Scheda madre:MSI Amethyst-m; Processore:amd sempron 3400+;2000Mhz Ram:ddr-sdram 1024Mb; Scheda grafica:Nvidia geforce 6200SE Turbocache; Scheda audio:AC'97 Audio controller Sistema Operativo:Windows 7 32bit Ultima modifica di Marco95 : 10-03-2013 alle 17:25. |
![]() |
![]() |
![]() |
#2 |
Bannato
Iscritto dal: Mar 2008
Città: Villabate(PA)
Messaggi: 2515
|
![]() ![]() ![]() Codice:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <malloc.h> #include <time.h> #include <stdint.h> typedef struct tagPersona { unsigned char *Nome; struct tagPersona *next; struct tagPersona *last; } Persona; void Print(Persona *first) { Persona *n = first; printf("\n"); while( n != NULL ) { printf("%s\n", n->Nome); n = n->next; } } void FreeList(Persona *first) { Persona *n1 = first, *n2; while ( n1 != NULL ) { n2 = n1->next; if ( n1->Nome ) free(n1->Nome); free(n1); n1 = n2; } } Persona* NewNode(Persona *Pers) { Persona *n; size_t len; len = strlen(Pers->Nome); n = (Persona *)malloc(sizeof(Persona)); if( n == NULL ) { printf("\nNewNode 1: Impossibile allocare la memoria. LOL!!!\n"); return NULL; } n->Nome = (unsigned char*)malloc(sizeof(unsigned char) * len + 1); if ( !n->Nome ) { printf("\nNewNode 2: Impossibile allocare la memoria. LOL!!!\n"); free(n); n = NULL; return NULL; } strcpy(n->Nome, Pers->Nome); n->next = NULL; return n; } Persona* Append(Persona *Pers, Persona *first) { Persona *n = first, *nuovo; if ( first == NULL ) { nuovo = NewNode(Pers); if ( !nuovo ) return first; nuovo->last = nuovo; return nuovo; } nuovo = NewNode(Pers); if ( !nuovo ) return first; n = first->last; n->next = nuovo; first->last = n->next; return first; } uint64_t MakeBuffer(const char *szFileName, unsigned char **buffer) { long x; uint64_t retSizeData = 0; long numread; FILE *fp; fp = fopen(szFileName, "rb"); if ( fp == NULL ) { printf("\nLOL!!!\nErrore nell'apertura del file \"%s\". Addio!\n", szFileName); return 0; } #if __linux__ || __APPLE__ fseeko(fp, 0, SEEK_END); retSizeData = ftello(fp); fseeko(fp, 0, SEEK_SET); #else _fseeki64(fp, 0, SEEK_END); retSizeData = _ftelli64(fp); _fseeki64(fp, 0, SEEK_SET); #endif *buffer = (unsigned char *)malloc(sizeof(unsigned char) * retSizeData); if ( !*buffer ) { printf("\nLOL!!!\nMemoria insufficiente. Addio!\n"); fclose(fp); return 0; } numread = fread(*buffer, 1, retSizeData, fp); if ( numread < retSizeData ) { fclose(fp); free(*buffer); *buffer = NULL; printf("\nLOL!!!\nErrore nella lettura del file %s\n", szFileName); return 0; } fclose(fp); return retSizeData; } int DFA(unsigned char *buffer, uint64_t SizeData, Persona **pPers) { char c; long k; long x; Persona Pers; Pers.Nome = (unsigned char*)malloc(sizeof(unsigned char) * 1024); if ( !(Pers.Nome) ) { printf("Impossibile allocare la memoria. LOL!!!\n"); return 0; } x = 0; k = 0; while ( k < SizeData ) { c = *(buffer + k++); while ( c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == ',' ) { c = *(buffer + k++); if ( k >= SizeData ) { free(Pers.Nome); return k; } } switch( c ) { case '"': c = *(buffer + k++); while ( c != '"' ) { if ( k >= SizeData ) { printf("\nErroooooooreeee! File malformato! LOOOOOOOOLLL!!!\n"); free(Pers.Nome); return 0; } Pers.Nome[x++] = c; if ( x >= 1024 ) { printf("\nLOOOOOOLLL!!! Ho trovato un nome piu' lungo di 1024 caratteri. LOOOOOOLLL!!! Addio!\n"); free(Pers.Nome); return 0; } c = *(buffer + k++); } Pers.Nome[x] = '\0'; x = 0; *pPers = Append(&Pers, *pPers); break; default: break; } } if ( Pers.Nome ) free(Pers.Nome); return k; } int main(int argc, char* argv[]) { Persona *pPers = NULL; unsigned char *buffer = NULL; uint64_t sizeData = 0; int ret; if ( argc != 2 ) { printf("\nDevi specificare il nome di un file!\n"); printf("\nUso: %s nomefile\n\n", argv[0]); return -1; } sizeData = MakeBuffer(argv[1], &buffer); if ( !sizeData ) { printf("\nImpossibile allocare il buffer. Addio!\n"); return -1; } ret = DFA(buffer, sizeData, &pPers); printf("\n"); if ( ret && pPers ) Print(pPers); printf("\n"); if ( pPers) FreeList(pPers); if ( buffer ) free(buffer); return 0; } Ultima modifica di Vincenzo1968 : 11-03-2013 alle 11:20. |
![]() |
![]() |
![]() |
#3 | |
Senior Member
Iscritto dal: Nov 2005
Città: Texas
Messaggi: 1722
|
Quote:
Anzi, di piu': nel file ci sono 5162 nomi ma quando si va a stampare ne vengono stampati 5163. Infatti c'e' anche il nome vuoto dovuto al newline, del quale non hai tenuto conto nella scrittura dell'applicazione. Perche' il mio output e' diverso dal tuo? Ci possono essere diversi fattori. In primis, il tuo programma sembra corretto, ma debole. Per debole intendo che un piccolo problema di qualsiasi genere potrebbe farlo sbagliare, spesso rendendo difficile l'identificazione del problema. E' molto sensibile all'input e all'ambiente di esecuzione. Per renderlo piu' robusto, e magari trovare il motivo della differenza di esecuzione: - quando apri un file NON DARE PER SCONTATO che l'operazione riesca, ma controlla che sia effettivamente riuscita; - anche l'allocazione della memoria potrebbe non riuscire; pertanto controlla che sia riuscita e stampa un messaggio di errore/termina/fa qualcosa nel caso non riesca; - il ciclo "leggi virgolette" e' molto dipendente dal file esterno. Un errore nel file ti manda in crash. Ovviamente in caso di errore puoi fare ben poco, ma cerca di evitare eventuali crash.
__________________
In God we trust; all others bring data |
|
![]() |
![]() |
![]() |
#4 |
Bannato
Iscritto dal: Mar 2008
Città: Villabate(PA)
Messaggi: 2515
|
Improved version con automa a stati:
Codice:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <malloc.h> #include <time.h> #include <stdint.h> typedef enum tagStates { S0, S1, S2, S3 } States; typedef struct tagPersona { unsigned char *Nome; struct tagPersona *next; struct tagPersona *last; } Persona; void Print(Persona *first) { Persona *n = first; printf("\n"); while( n != NULL ) { printf("%s\n", n->Nome); n = n->next; } } void FreeList(Persona *first) { Persona *n1 = first, *n2; while ( n1 != NULL ) { n2 = n1->next; if ( n1->Nome ) free(n1->Nome); free(n1); n1 = n2; } } Persona* NewNode(Persona *Pers) { Persona *n; size_t len; len = strlen(Pers->Nome); n = (Persona *)malloc(sizeof(Persona)); if( n == NULL ) { printf("\nNewNode 1: Impossibile allocare la memoria. LOL!!!\n"); return NULL; } n->Nome = (unsigned char*)malloc(sizeof(unsigned char) * len + 1); if ( !n->Nome ) { printf("\nNewNode 2: Impossibile allocare la memoria. LOL!!!\n"); free(n); n = NULL; return NULL; } strcpy(n->Nome, Pers->Nome); n->next = NULL; return n; } Persona* Append(Persona *Pers, Persona *first) { Persona *n = first, *nuovo; if ( first == NULL ) { nuovo = NewNode(Pers); if ( !nuovo ) return first; nuovo->last = nuovo; return nuovo; } nuovo = NewNode(Pers); if ( !nuovo ) return first; n = first->last; n->next = nuovo; first->last = n->next; return first; } uint64_t MakeBuffer(const char *szFileName, unsigned char **buffer) { long x; uint64_t retSizeData = 0; long numread; FILE *fp; fp = fopen(szFileName, "rb"); if ( fp == NULL ) { printf("\nLOL!!!\nErrore nell'apertura del file \"%s\". Addio!\n", szFileName); return 0; } #if __linux__ || __APPLE__ fseeko(fp, 0, SEEK_END); retSizeData = ftello(fp); fseeko(fp, 0, SEEK_SET); #else _fseeki64(fp, 0, SEEK_END); retSizeData = _ftelli64(fp); _fseeki64(fp, 0, SEEK_SET); #endif *buffer = (unsigned char *)malloc(sizeof(unsigned char) * retSizeData); if ( !*buffer ) { printf("\nLOL!!!\nMemoria insufficiente. Addio!\n"); fclose(fp); return 0; } numread = fread(*buffer, 1, retSizeData, fp); if ( numread < retSizeData ) { fclose(fp); free(*buffer); *buffer = NULL; printf("\nLOL!!!\nErrore nella lettura del file %s\n", szFileName); return 0; } fclose(fp); return retSizeData; } int DFA(unsigned char *buffer, uint64_t SizeData, Persona **pPers) { States state = S0; char c; long k; long x; Persona Pers; Pers.Nome = (unsigned char*)malloc(sizeof(unsigned char) * 1024); if ( !(Pers.Nome) ) { printf("Impossibile allocare la memoria. LOL!!!\n"); return 0; } x = 0; k = 0; while ( k < SizeData ) { c = *(buffer + k++); while ( c == ' ' || c == '\t' || c == '\n' || c == '\r' ) { c = *(buffer + k++); if ( k >= SizeData ) { free(Pers.Nome); return k; } } switch( state ) { case S0: x = 0; if ( c == '"' ) { state = S1; } else { printf("\nS0 Errore: %c input malformato. Addio!\n", c); free(Pers.Nome); return 0; } break; case S1: if ( (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= 128 && c <= 154) || (c >= 224 && c <= 237) ) { Pers.Nome[x++] = c; if ( x >= 1024 ) { printf("\nS1 LOOOOOOLLL!!! Ho trovato un nome piu' lungo di 1024 caratteri. LOOOOOOLLL!!! Addio!\n"); free(Pers.Nome); return 0; } } else { k--; state = S2; } break; case S2: if ( c == '"' ) { Pers.Nome[x] = '\0'; x = 0; *pPers = Append(&Pers, *pPers); state = S3; } else { printf("\nS2 Errore: %c input malformato. Addio!\n", c); free(Pers.Nome); return 0; } break; case S3: if ( c == ',' ) { state = S0; } else { printf("\nS3 Errore: %c input malformato. Addio!\n", c); free(Pers.Nome); return 0; } break; default: printf("\nLOL! Errore: %c input malformato. Addio!\n", c); free(Pers.Nome); return 0; } } if ( Pers.Nome ) free(Pers.Nome); return k; } int main(int argc, char* argv[]) { Persona *pPers = NULL; unsigned char *buffer = NULL; uint64_t sizeData = 0; int ret; if ( argc != 2 ) { printf("\nDevi specificare il nome di un file!\n"); printf("\nUso: %s nomefile\n\n", argv[0]); return -1; } sizeData = MakeBuffer(argv[1], &buffer); if ( !sizeData ) { printf("\nImpossibile allocare il buffer. Addio!\n"); return -1; } ret = DFA(buffer, sizeData, &pPers); printf("\n"); if ( ret && pPers ) Print(pPers); printf("\n"); if ( pPers) FreeList(pPers); if ( buffer ) free(buffer); return 0; } ![]() ![]() ![]() Ultima modifica di Vincenzo1968 : 11-03-2013 alle 13:03. |
![]() |
![]() |
![]() |
#5 |
Senior Member
Iscritto dal: Nov 2005
Città: Texas
Messaggi: 1722
|
toglimi una curiosita': perche' scrivi sempre
Codice:
c = *(buffer + k++); Non e' piu' bello, a vedersi: Codice:
c = buffer[k++]; ![]()
__________________
In God we trust; all others bring data |
![]() |
![]() |
![]() |
#6 |
Bannato
Iscritto dal: Mar 2008
Città: Villabate(PA)
Messaggi: 2515
|
Perché è più lolloso
![]() No scherzo, è che sono rimasto al Dragon Book che, nell'esempio del dfa, usa quella notazione. Ma hai ragione, con le quadre è più chiaro, più leggibile. |
![]() |
![]() |
![]() |
#7 | ||
Member
Iscritto dal: May 2010
Messaggi: 126
|
Quote:
Quote:
P.s.Ho cancellato le linee Codice:
#if __linux__ || __APPLE__ fseeko(fp, 0, SEEK_END); retSizeData = ftello(fp); fseeko(fp, 0, SEEK_SET); #else _fseeki64(fp, 0, SEEK_END); retSizeData = _ftelli64(fp); _fseeki64(fp, 0, SEEK_SET); #endif
__________________
Il mio pc: Scheda madre:MSI Amethyst-m; Processore:amd sempron 3400+;2000Mhz Ram:ddr-sdram 1024Mb; Scheda grafica:Nvidia geforce 6200SE Turbocache; Scheda audio:AC'97 Audio controller Sistema Operativo:Windows 7 32bit Ultima modifica di Marco95 : 11-03-2013 alle 13:32. |
||
![]() |
![]() |
![]() |
#8 |
Bannato
Iscritto dal: Mar 2008
Città: Villabate(PA)
Messaggi: 2515
|
Codice:
valgrind --leak-check=full --show-reachable=yes --track-origins=yes --log-file=outValgrind.txt ./listadbg listafileinput.txt ==21205== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al. ==21205== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info ==21205== Command: ./listadbg listafileinput.txt ==21205== Parent PID: 21066 ==21205== ==21205== ==21205== HEAP SUMMARY: ==21205== in use at exit: 0 bytes in 0 blocks ==21205== total heap usage: 10,329 allocs, 10,329 frees, 208,078 bytes allocated ==21205== ==21205== All heap blocks were freed -- no leaks are possible ==21205== ==21205== For counts of detected and suppressed errors, rerun with: -v ==21205== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0) ![]() |
![]() |
![]() |
![]() |
#9 | |
Bannato
Iscritto dal: Mar 2008
Città: Villabate(PA)
Messaggi: 2515
|
Quote:
![]() ![]() Che compilatore usi? Io l'ho compilato con GCC 4.7.2 su Linux e Visual Studio 2012 su Windows. |
|
![]() |
![]() |
![]() |
#10 | |
Senior Member
Iscritto dal: Nov 2005
Città: Texas
Messaggi: 1722
|
Quote:
Per cambiarlo sotto Windows, clicca col bottone destro sul titolo, poi scegli Properties e seleziona il "Layout" tab. A quel punto puoi selezionare la dimensione che ti serve
__________________
In God we trust; all others bring data |
|
![]() |
![]() |
![]() |
#11 |
Bannato
Iscritto dal: Mar 2008
Città: Villabate(PA)
Messaggi: 2515
|
![]() Codice:
void Print(Persona *first) { uint32_t count = 1; Persona *n = first; printf("\n"); while( n != NULL ) { printf("%5d -> %s\n", count++, n->Nome); n = n->next; } } Codice:
./listafile2 listafileinput.txt > out.txt ![]() Ultima modifica di Vincenzo1968 : 11-03-2013 alle 14:03. |
![]() |
![]() |
![]() |
#12 | |
Member
Iscritto dal: May 2010
Messaggi: 126
|
Copiando esattamente il tuo codice ottengo i seguenti errori:
-invalid conversion from unsigned char* to const char* in function uint64... _fseeki64 was no delclaered in this scope _ftelli64 was not declared in this scope Io utilizzo codeblocks su windows versione 10.05... Poi potrsti spiegarmi che cosa sono _fseeki64 e _ftelli64? ![]() Quote:
EDIT:Il problema sembrava risiedere proprio là...che INGENUITà
__________________
Il mio pc: Scheda madre:MSI Amethyst-m; Processore:amd sempron 3400+;2000Mhz Ram:ddr-sdram 1024Mb; Scheda grafica:Nvidia geforce 6200SE Turbocache; Scheda audio:AC'97 Audio controller Sistema Operativo:Windows 7 32bit Ultima modifica di Marco95 : 11-03-2013 alle 14:08. |
|
![]() |
![]() |
![]() |
#13 | |
Bannato
Iscritto dal: Mar 2008
Città: Villabate(PA)
Messaggi: 2515
|
Quote:
http://msdn.microsoft.com/en-US/libr...=vs.80%29.aspx Eppure è C standard. Non è che con CodeBlocks usi qualche compilatore stravagante tipo DEV-C++? Non è meglio usare Geany con GCC per Windows? http://www.geany.org/Support/RunningOnWindows http://code.google.com/p/mingw-builds/ Ultima modifica di Vincenzo1968 : 11-03-2013 alle 14:14. |
|
![]() |
![]() |
![]() |
#14 | |
Member
Iscritto dal: May 2010
Messaggi: 126
|
Come compilatore uso Mingw...non so se può essere considerato stravagante :/
Quote:
__________________
Il mio pc: Scheda madre:MSI Amethyst-m; Processore:amd sempron 3400+;2000Mhz Ram:ddr-sdram 1024Mb; Scheda grafica:Nvidia geforce 6200SE Turbocache; Scheda audio:AC'97 Audio controller Sistema Operativo:Windows 7 32bit Ultima modifica di Marco95 : 11-03-2013 alle 14:13. |
|
![]() |
![]() |
![]() |
#15 |
Bannato
Iscritto dal: Mar 2008
Città: Villabate(PA)
Messaggi: 2515
|
Al limite c'è anche la versione gratuita di Visual Studio 2012:
http://www.microsoft.com/visualstudi...press-products http://www.microsoft.com/visualstudi...indows-desktop http://www.microsoft.com/visualstudi...indows-desktop Ultima modifica di Vincenzo1968 : 11-03-2013 alle 14:23. |
![]() |
![]() |
![]() |
#16 | |
Member
Iscritto dal: May 2010
Messaggi: 126
|
Quote:
__________________
Il mio pc: Scheda madre:MSI Amethyst-m; Processore:amd sempron 3400+;2000Mhz Ram:ddr-sdram 1024Mb; Scheda grafica:Nvidia geforce 6200SE Turbocache; Scheda audio:AC'97 Audio controller Sistema Operativo:Windows 7 32bit |
|
![]() |
![]() |
![]() |
#17 |
Bannato
Iscritto dal: Mar 2008
Città: Villabate(PA)
Messaggi: 2515
|
![]() ![]() ![]() |
![]() |
![]() |
![]() |
#18 |
Bannato
Iscritto dal: Mar 2008
Città: Villabate(PA)
Messaggi: 2515
|
![]() ![]() |
![]() |
![]() |
![]() |
Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 14:39.