[C] Scrittura lettura file binari
Non capisco perchè la lettura non funziona:
=== Scrittura ===
===Lettura===
Mi stampa Name:Name%s.
Potete darci un'occhiatina gentilmente?
Grazie e buona giornata.
=== Scrittura ===
typedef struct{ char *name; char *surname; int age; }Person; int main() { FILE * f = fopen("file","wb"); if(f == NULL ) return -1; Person *io = malloc(sizeof(Person)); if ( io == NULL ) return -1; io->name = "Andrea"; io->surname = "Rossi"; io->age=23; fwrite( io, sizeof(Person), 1, f ); fclose(f); return 0; }
===Lettura===
typedef struct{ char *name; char *surname; int age; }Person; int main() { Person *io = malloc(sizeof(Person)); FILE *f = fopen("file","rb"); if( f == NULL ) return -1; rewind(f); fread(io, sizeof(Person), 1, f); printf("Name:%s", io->name); fclose(f); return 0; }
Mi stampa Name:Name%s.
Potete darci un'occhiatina gentilmente?
Grazie e buona giornata.

Risposte
fwrite scrive i valori dei puntatori contenuti nella tua struttura e non i valori a cui questi puntatori fanno riferimento. Per scrivere la tua struttura è quindi necessario usare un codice più complicato o usare delle stringhe di lunghezza fissa nella tua struttura (quindi qualcosa tipo char name[20] al posto di char *name).
Però non mi ritorna una cosa:
===Scrittura===
===Lettura===
Il puntatore io->name è uguale sia nella scrittura che nella lettura. Però nella scrittura mi printa:
mentre nella lettura:
Qual'è la spiegazione a tutto questo??
Grazie e buona serata
===Scrittura===
int main() { FILE * f = fopen("file","wb"); if(f == NULL ) return -1; Person *io = malloc(sizeof(Person)); if ( io == NULL ) return -1; io->name = (char *)malloc(sizeof(char)*64); io->name = "Andrea"; io->surname = (char *)malloc(sizeof(char)*64); io->surname = "Rossi"; io->age=23; printf("Name:%p %s", io->name, io->name); fwrite( io, sizeof(Person), 1, f ); fclose(f); return 0; }
===Lettura===
int main() { Person *io = malloc(sizeof(Person)); FILE *f = fopen("file","rb"); if( f == NULL ) return -1; fread(io, sizeof(Person), 1, f); printf("Name:%p %s", io->name, io->name); fclose(f); return 0; }
Il puntatore io->name è uguale sia nella scrittura che nella lettura. Però nella scrittura mi printa:
Name:0040A06C Andrea
mentre nella lettura:
Name:0040A06C Name:%p %s
Qual'è la spiegazione a tutto questo??
Grazie e buona serata

I puntatori non vengono preservati tra programmi diversi e, in generale, neanche tra esecuzioni diverse dello stesso programma. Nel tuo caso hai che entrambi i programmi vengono caricati nella stessa locazione di memoria e che nella stessa posizione dell'eseguibile in cui c'è Andrea nel primo programma, c'è l'altra stringa nel secondo programma. E' strano ma suppongo tu stia lavorando in debug o qualcosa del genere. In altre situazioni ti saresti trovato una stringa senza senso o un crash del programma. In generale i puntatori non possono essere scritti su file in questo modo.
Capito grazie.
Quindi per risolverlo, dovrei utilizzare per forza una struct senza puntatori quindi che memorizza nella struct direttamente le stringhe.
Altre soluzioni??
Quindi per risolverlo, dovrei utilizzare per forza una struct senza puntatori quindi che memorizza nella struct direttamente le stringhe.
Altre soluzioni??
I puntatori sono il principale ostacolo a scrivere e leggere valori in questo modo. Ci sono anche altri potenziali problemi:
1. I puntatori hanno dimensioni diversi in piattaforme diverse.
2. I numeri interi possono avere dimensioni diverse in piattaforme diverse.
3. I compilatori possono introdurre diversi tipi di allineamento dei membri di una struttura (non è più di tanto questo il caso).
4. Gli interi e i puntatori possono essere rappresentati diversamente a seconda della piattaforma.
Ignorando questi problemi rimane quello dei puntatori che non vengono preservati una volta scritti e letti da file. La soluzione (se si può chiamare tale) potrebbe essere qualcosa come segue (non testato):
1. I puntatori hanno dimensioni diversi in piattaforme diverse.
2. I numeri interi possono avere dimensioni diverse in piattaforme diverse.
3. I compilatori possono introdurre diversi tipi di allineamento dei membri di una struttura (non è più di tanto questo il caso).
4. Gli interi e i puntatori possono essere rappresentati diversamente a seconda della piattaforma.
Ignorando questi problemi rimane quello dei puntatori che non vengono preservati una volta scritti e letti da file. La soluzione (se si può chiamare tale) potrebbe essere qualcosa come segue (non testato):
void writePerson(FILE *file, Person *p) { Person copy = *p; long pos = ftell(file); long name = 0L, surname = 0L; fseek(file, sizeof(Person), SEEK_CUR); name = ftell(file); fwrite(p->name, 1, strlen(p->name)+1, file); surname = ftell(file); fwrite(p->surname, 1, strlen(p->surname)+1, file); copy.name = (char*)NULL + name; copy.surname = (char*)NULL + surname; fseek(file, pos, SEEK_SET); fwrite(©, sizeof(Person), 1, file); } /* Da per scontato sia l'unica cosa scritta nel file.. */ Person *readPerson(FILE *file) { long size = 0; Person *p = NULL; fseek(file, 0, SEEK_END); size = ftell(file); p = malloc(size); fseek(file, 0, SEEK_SET); fread(p, 1, size, file); p->name += (char*)p; p->surname += (char*)p; return p; }
"Paolovox":
Capito grazie.
Quindi per risolverlo, dovrei utilizzare per forza una struct senza puntatori quindi che memorizza nella struct direttamente le stringhe.
Altre soluzioni??
L'unico vantaggio dell'uso dei puntatori invece di scrivere direttamente un array statico è quello che li puoi ridimensionare a seconda di quanto ti serve. Ma tu non stai usando questa caratteristica. Inoltre mi sembra assurdo generare dinamicamente la struttura.
Detto questo il problema non sono i puntatori della struttura ma il fatto che tu scriva il valore dei puntatori su file. È un valore che non ha alcun significato, se vuoi salvare il nome della persona dovrai necessariamente salvare la stringa che contiene quel nome (che essa sia statica o dinamica).