[C] Scrittura lettura file binari

Messaggioda Paolovox » 20/07/2016, 17:48

Non capisco perchè la lettura non funziona:

=== Scrittura ===
Codice:
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===
Codice:
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. :-D
« Una volta eliminato l'impossibile, ciò che resta, per quanto improbabile, deve essere la verità. »
(Sherlock Holmes)
Avatar utente
Paolovox
Average Member
Average Member
 
Messaggio: 289 di 620
Iscritto il: 13/06/2014, 19:44

Re: [C] Scrittura lettura file binari

Messaggioda apatriarca » 22/07/2016, 16:28

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).
apatriarca
Moderatore
Moderatore
 
Messaggio: 4331 di 10435
Iscritto il: 08/12/2008, 20:37
Località: Madrid

Re: [C] Scrittura lettura file binari

Messaggioda Paolovox » 24/07/2016, 19:30

Però non mi ritorna una cosa:
===Scrittura===
Codice:
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===
Codice:
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:
Codice:
Name:0040A06C Andrea

mentre nella lettura:
Codice:
Name:0040A06C Name:%p %s


Qual'è la spiegazione a tutto questo??
Grazie e buona serata :-D
« Una volta eliminato l'impossibile, ciò che resta, per quanto improbabile, deve essere la verità. »
(Sherlock Holmes)
Avatar utente
Paolovox
Average Member
Average Member
 
Messaggio: 290 di 620
Iscritto il: 13/06/2014, 19:44

Re: [C] Scrittura lettura file binari

Messaggioda apatriarca » 25/07/2016, 09:36

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.
apatriarca
Moderatore
Moderatore
 
Messaggio: 4332 di 10435
Iscritto il: 08/12/2008, 20:37
Località: Madrid

Re: [C] Scrittura lettura file binari

Messaggioda Paolovox » 25/07/2016, 11:19

Capito grazie.
Quindi per risolverlo, dovrei utilizzare per forza una struct senza puntatori quindi che memorizza nella struct direttamente le stringhe.
Altre soluzioni??
« Una volta eliminato l'impossibile, ciò che resta, per quanto improbabile, deve essere la verità. »
(Sherlock Holmes)
Avatar utente
Paolovox
Average Member
Average Member
 
Messaggio: 291 di 620
Iscritto il: 13/06/2014, 19:44

Re: [C] Scrittura lettura file binari

Messaggioda apatriarca » 25/07/2016, 11:46

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):
Codice:
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(&copy, 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;
}
apatriarca
Moderatore
Moderatore
 
Messaggio: 4333 di 10435
Iscritto il: 08/12/2008, 20:37
Località: Madrid

Re: [C] Scrittura lettura file binari

Messaggioda vict85 » 25/07/2016, 18:52

Paolovox ha scritto: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).
vict85
Moderatore
Moderatore
 
Messaggio: 8824 di 19253
Iscritto il: 16/01/2008, 00:13
Località: Berlin


Torna a Informatica

Chi c’è in linea

Visitano il forum: Nessuno e 1 ospite