PDA

Visualizza la versione completa : [C] Lettura struct con dati di persone da file


felx
22-07-2018, 14:25
Creare i file persona.h e persona.c che consentano di utilizzare la seguente struttura:
struct persona { int anni; char nome[50]; };
e la seguente funzione:
extern struct persona *leggi_persone(const char *filename, size_t *size);
La funzione riceve in input un nome di file filename che deve aprire in modalità lettura tradotta (testo). Se il file esiste, legge dal file sequenze di caratteri che descrivono delle persone e la loro età.
Nel file è indicato, come primo valore, un numero intero che rappresenta il numero totale di persone elencate nel file seguito da un a capo. Successivamente, su ogni riga sono presenti i dati delle persone nel seguente formato:
 Zero o più spazi o tab.
 Un numero intero che indica l’età della persona.
 Zero o più spazi o tab.
 Il carattere virgola
 Zero o più spazi o tab.
 Una stringa che può contenere spazi e tab che rappresenta il nome della persona.
 Un a capo.
Quello che segue è un esempio corretto di file:
3↵ 18 , Marco Rossi↵ 22 , Luca Verdi↵ 25, Marcello Bianchi↵
La funzione deve allocare dinamicamente sull’heap spazio sufficiente a contenere tutte le persone leggibili correttamente dal file, riempirlo con i valori opportuni, impostare la variabile puntata da size a questo numero e infine ritornare un puntatore all’area così allocata.
Se è impossibile aprire il file, questo non contiene nulla o si verifica un errore durante la lettura, ad esempio nel file ci sono meno persone di quelle indicate dal primo numero intero, la funzione ritorna NULL e imposta la variabile puntata da size a 0.





Il codice che ho creato fuzniona quasi perfettamente eccetto che per i controlli non sono in grado di arrestare nel caso il file è vuoto non esiste eccetera sapreste aiutarmi?
posto il codice

#include"persona.h"
#include<string.h>
extern struct persona *leggi_persone(const char *filename, size_t *size) {
FILE *f = fopen(filename, "rt");
if (f == NULL)
{
*size = 0;
return NULL;
fclose(f);

}
char p[50];
size_t nrighe;
struct persona *ret;

fscanf(f, "%i", &nrighe);
if (nrighe == 0)
{
*size = 0;
return NULL;

}
ret = malloc(sizeof(struct persona)*nrighe);
for (size_t i = 0; i < nrighe; i++) {
if (!feof(f)) {
fscanf(f, "%i ,", &ret[i].anni);
fgets(p, 50, f);
strcpy(ret[i].nome, p);
}
else return NULL;



}

fclose(f);
*size = nrighe;
return ret;



}

oregon
22-07-2018, 15:30
No ... non si capisce il tuo problema, spiegati meglio.

felx
22-07-2018, 16:01
No ... non si capisce il tuo problema, spiegati meglio.
L'ultima parte dell'esercizio mi dice che se c'è un problema nell'apertura del file oppure nella lettuRA C'è UN ERRORE DEVO IMPOSTARE LA VARIABILE SIZE A 0 E RITORNARE NULL.Il problema è che non so come corregere il mio codice in modo da fare quersto

oregon
22-07-2018, 16:09
Per i problemi nell'apertura lo fai qui

if (f == NULL)
{
*size = 0;
return NULL;
fclose(f);
}

anche se la fclose non ha senso inserirla (dopo la if non va nulla e dato che il file non è aperto non va chiuso).

L'hai scritto tu questa if?

felx
22-07-2018, 16:45
Per i problemi nell'apertura lo fai qui

if (f == NULL)
{
*size = 0;
return NULL;
fclose(f);
}

anche se la fclose non ha senso inserirla (dopo la if non va nulla e dato che il file non è aperto non va chiuso).

L'hai scritto tu questa if?
si l'ho scritta io, e come controllo se durante la lettura ho per esempio un file strutturato così:
56
8 Luca
12 Marco
Il primo numero dovrebbe essere il numero di persone presenti nel file... essendo più grande farei un for inutile 56 volte come farei a controllare se quel numero corrispoinde effettivamente al numero di righe presenti nel file???
Ne ho bisoghno perché se il numero è maggiore devo ritornare null.
Inoltre se il file è vuoto come lo controllo?

oregon
22-07-2018, 19:11
Devi controllare il risultato restituito da ogni fscanf. Ad esempio, per la prima
r = fscanf(f, "%i", &nrighe);

in cui r è un int che devi controllare. Il suo valore ha un significato che trovi nella sezione Return Valuedel documento in

http://www.cplusplus.com/reference/cstdio/fscanf/

felx
22-07-2018, 19:30
Devi controllare il risultato restituito da ogni fscanf. Ad esempio, per la prima
r = fscanf(f, "%i", &nrighe);

in cui r è un int che devi controllare. Il suo valore ha un significato che trovi nella sezione Return Value

del documento in

http://www.cplusplus.com/reference/cstdio/fscanf/
e se facessi if(fscanf(A,B,C)<0)
SIZE=0;
return NULL sarebbe lo stesso?

oregon
22-07-2018, 19:35
Non <0 ma < del numero di item che devi leggere

felx
22-07-2018, 19:42
Risolto grazie mille posto il codice corretto:
p.s. non significa che non possa essere migliorato


#include"persona.h"
#include<string.h>
extern struct persona *leggi_persone(const char *filename, size_t *size) {
FILE *f = fopen(filename, "rt");
if (f == NULL)
{
*size = 0;
return NULL;
fclose(f);

}
char p[50];
size_t nrighe;
struct persona *ret;

if(fscanf(f, "%i", &nrighe)<=0)

{
fclose(f);
*size = 0;
return NULL;

}
ret = malloc(sizeof(struct persona)*nrighe);
for (size_t i = 0; i < nrighe; i++) {
if (fscanf(f, "%i ,", &ret[i].anni) <= 0) {
*size = 0;
free(ret);
fclose(f);
return NULL;

}
if (fgets(p, 50, f) == NULL)
{*size = 0;
free(ret);
fclose(f);
return NULL;
}
strcpy(ret[i].nome, p);





}

fclose(f);
*size = nrighe;
return ret;
free(ret);



}

oregon
22-07-2018, 19:46
Ti ho detto di eliminare la fclose dopo il return ... te lo ripeto ...

La free va messa prima del return ...

DOPO il return non va nulla.

Loading