PDA

Visualizza la versione completa : Lettura migliaia numeri da file in C


spaghetto
03-04-2008, 21:13
Salve ragazzi, vi scrivo perchè non riesco a risolvere un problema con un programma.
L' esercizio consiste nel restituire una stringa nella quale vengono salvati dei numeri letti in un file passato come parametro ad una funzione...
Il problema principale è che il file è composto da circa 50000 numeri, e il programma che io ho fatto si blocca dopo pochi numeri....ecco qui il mio TENTATIVO FALLITO:


char * funzione(FILE * f) {

int c,i=0,var,clas,neg; // Dichiaro le variabili che mi serviranno man mano

char c1,c2,s[10];

long int cont=0,x;

fscanf(f,"%c",&c1); // Prelevo le prime due righe del file
fscanf(f,"%c",&c1); // In questo fscanf prelevo il '\n' della prima riga
fscanf(f,"%c %s %d %d",&c2,s,&var,&clas);

char * str; // Dichiaro la stringa

FILE * p=f; // Dichiaro questo puntatore che mi serve per salvare la posizione di "f"

while(!feof(f)) {

fscanf(f,"%d",&x); cont++; // Conto i numeri presenti nel file (numero non preciso)

}

str=calloc(cont,sizeof(char)); // Alloco la memoria necessaria per contenere tutti questi numeri

f=p; // Riparto dal punto salvato da 'p' nel file

while(!feof(f)) { // Scorro il file per salvare nella stringa i numeri che trovo

fscanf(f,"%d",&x);

str[i]=x;

i++; }

}

return str; // ritorno la stringa

}


Il file è così composto:



c
p cnf 450 19084
1 22 3 4 54 6 7 8 9 10 11 62 13 14 15 0
16 17 8 19 2 21 62 213 24 25 26 27 28 29 30 0
31 42 33 34 230 36 37 358 39 40 423 42 43 44 45 0
etc etc etc!!!

Quando ritorno la stringa purtroppo di tutti numeri me li salva soltanto 15! E quindi non so più come fare...Vi ringrazio in anticipo per il vostro aiuto!
Un saluto a tutti!

MacApp
03-04-2008, 21:43
Anziché:


f=p; // Riparto dal punto salvato da 'p' nel file

prova con:


rewind (f);

spaghetto
03-04-2008, 22:45
Purtroppo non posso far ripartire da zero f in quanto sennò dovrei rifare l' fscanf per le prima due righe...l' altra alternativa che mi è venuta in mente è fare gli fscanf per le prime due righe nel MAIN e poi richiamare la funzione...solo che anche adesso mi da dei problemi, nel senso che mi va in segmentation fault subito dopo i due fscanf...vi lascio questo mio secondo tentativo...



char * read_file(FILE * f);

int main() {

FILE * f;

char * str;
char c1,c2,s[10];
int x,var,clas;

f=fopen("xxx.dat","r");

fscanf(f,"%c %c",&c1); // Prelevo le prime due righe del file
fscanf(f,"%c %s %d %d",&c2,s,&var,&clas);
printf("%c %c %s %d %d\n",c1,c2,s,var,clas);

str=read_file(f);

}

char * read_file(FILE * f) {

int c,i=0,neg,x;

long int cont=0;

while(!feof(f)) {

fscanf(f,"%d",&x); cont++; // Conto i numeri presenti nel file

}

rewind(f);


char * str; // Dichiaro la stringa

str=calloc(cont,sizeof(char)); // Alloco la memoria necessaria per contenere tutti questi numeri

while(!feof(f)) { // Scorro il file per salvare nella stringa i numeri che trovo

fscanf(f,"%d",&x);

str[i]=x;

i++; }

return str; // ritorno la stringa

}

Non so più come fare...!!! Aiuto vi prego! :bhò:

shodan
03-04-2008, 23:28
Commetti il classico errore concettuale nel confondere C string con array di char.
Una C string è un array di char null terminated, quindi se passi str ad una funzione (es. strlen) ti verranno conteggiati tutti i caratteri fino al primo zero che viene incontrato.



while(!feof(f)) { // Scorro il file per salvare nella stringa i numeri che trovo

fscanf(f,"%d",&x);

str[i]=x; // se x vale zero, le funzioni string del C lo considerano terminatore di stringa.

i++; }


Ma tu in realtà allochi un numero maggiore di memoria, (es. 256 byte), per cui in realtà, i numeri successivi vengono messi dopo quel terminatore.
Di conseguenza, devi restituire il numero di caratteri allocati (il cont per intenderci) in qualche modo e usare quello per lavorarci.

es.
for (i=0; i<cont; i++) etc.

Infine non liberi la memoria allocata da calloc.

spaghetto
03-04-2008, 23:39
Oddio perdonami ma continuo a non capire!!
Cioè, la porzione del programma che tu mi hai riscritto serve per salvare i numeri che trovo nella stringa...mi stai dicendo che se avanzo nella lettura del file e mi trova uno 0 (che si trova alla fine di ogni riga) lo fscanf si blocca? E quindi come posso scavalcare il problema?
Ti ringrazio per la tua risposta!

shodan
04-04-2008, 00:18
Mi riferisco al primo listato che hai postato.
Non si blocca la fscanf; si blocca una eventuale lettura fatta da una funzione C string.
Considera questo.



1 22 3 4 54 6 7 8 9 10 11 62 13 14 15 0 16 17 8 19 2 21 62 213 24 25 26 27 28 29 30 0


Qui hai 32 numeri. Se passi un array composto in questo modo, una strlen si blocca qui:



1 22 3 4 54 6 7 8 9 10 11 62 13 14 15 0


perché lo zero finale lo considera terminatore di stringa (come quasi tutte le funzioni string del C).

Tu invece hai bisogno di avere tutti e 32 i caratteri, quindi devi usare il contatore con un ciclo per sapere quando hai finito di scansionare l'array.
Se tu avessi usato un array di int, saresti stato costretto a recuperare in qualche modo la dimensione dello stesso, per scansionarlo tutto.

Per quanto riguarda il secondo listato.
Credo che l'errore sia qui. (In genere uso C++ quindi queste funzioni non le uso mai)


fscanf(f,"%c %c",&c1); // Prelevo le prime due righe del file

Richiedi due char, ma passi solo una variabile.

MacApp
04-04-2008, 00:19
controlla bene gli argomenti della scanf


fscanf(f,"%c %c",&c1); // Prelevo le prime due righe del file


gli chiedi due caratteri e ne prendi solo uno...

shodan
04-04-2008, 00:27
Ricordavo bene allora :D

spaghetto
04-04-2008, 00:27
Guarda, quel fscanf dove metto due %c serve soltanto per leggere due caratteri, una lettera e '\n'...ti assicuro facendo varie prove che il problema non è lì...si può sostituire con due fscanf tranquillamente...

Ho provato pure così, con questo ciclo...

while((x=fgetc(f))!= EOF) {

if(x>= var * -1 && x<= var) {

str[i]=x;

i++;

}

}

Purtroppo non mi salva i numeri precisi...ora il problema che rimane è riuscire a salvare questi interi....uffi!
Grazie Nuovamente!!!

shodan
04-04-2008, 00:40
D'accordo sulla prima fscanf, ma se chiedi due char e passi solo una variabile, ha ragione a protestare.

Per il problema principale, devi fare una cosa simile.


char * read_file(FILE * f, int *cont ) {

int c,i=0,neg,x;

*cont=0;

while(!feof(f)) {

fscanf(f,"%d",&x); (*cont)++; // Conto i numeri presenti nel file

}

rewind(f);


char * str; // Dichiaro la stringa

str=calloc(*cont,sizeof(char)); // Alloco la memoria necessaria per contenere tutti questi numeri

while(!feof(f)) { // Scorro il file per salvare nella stringa i numeri che trovo

fscanf(f,"%d",&x);

str[i]=x;

i++; }

return str; // ritorno la stringa

}

....
int counter=0;
char *stringa = read_file(f, &counter );
for (i=0; i<counter; i++) {
printf("%c\n",stringa[i]);
}
free(stringa);

Loading