Newsgroup: it.comp.lang.c
Titolo: Domanda da inesperto

Dopo diversi tentativi di risolvere il problema da me, ho deciso di
approfittare del vostro tempo e porvi il seguente quesito:
come posso salvare su un file una variabile 'a' di questo tipo:
 struct {
    char *nome;
    char *cogn;
    int  eta;
    } cartella;
    cartella a;
    FILE *infile;
Uso il compilatore DJGPP gcc 2.8.1 con RHIDE versione 1.4, Win95, su un
P133.
Ho provato a consultare il testo di Kelley, Pohl della Addison-Wesley "C
- Didattica e Programmazione", ma non sono ugualmente riuscito a
risolvere il mio problema. Spero che per voi sia una banalita'
facilmente risolvibile e vi sarei veramente grato se mi faceste
partecipe della vostra conoscenza. Ciao.
--
*******************************************************
  "C'e' un vecchio detto a riguardo delle reti che
  recita: i problemi di banda possono essere risolti
  con il denaro. I problemi di latenza sono piu' dif-
  ficili poiche' la velocita' della luce e' una cos-
  tante e non e' possibile corrompere Dio."
                                     David Clark, MIT
  Reply to 
bia...@maganet.net
  ICQ : 25991146
*******************************************************

    FILE *infile;
In vari modi, ad esempio usando un carattere che sicuramente
non appare ne' nome ne' in cogn come "separatore dei campi";
supponiamo, ad esempio, una barra verticale, e vediamo che
"salvare" e` davvero FACILISSIMO...:
    void scrivi(FILE* outfile, cartella* pa) {
        fprintf(outfile, "%s|%s|%d\n",
            pa->nome, pa->cognome, pa->eta);
    }
Il problema, naturalmente, viene quando quello che hai
salvato vuoi poi ripristinarlo...!-)
Per rileggere, dovrai presumibilmente leggere in aree di lavoro
temporaneo e riallocare una nuova stringa con malloc (quindi,
naturalmente, liberarla con free piu' avanti).  Ad esempio:
    cartella* leggi(FILE* inpfile) {
        cartella* presult;
        char buff[1024];
        fscanf(inpfile, "%[^|]|", buff);
        presult = malloc(sizeof(cartella));
        presult->nome =
            malloc(1+strlen(buff));
        strcpy(presult->nome, buff);
        fscanf(inpfile, "%[^|]|", buff);
        presult->cogn =
            malloc(1+strlen(buff));
        strcpy(presult->cogn, buff);
        fscanf(inpfile, "%d\n", &presult->eta);
        return presult;
    }
La rilettura, naturalmente, a seconda dei problemi
di gestione della memoria, puo` essere ancora
piu` complessa (per fare una malloc sola, invece
di tre, con evidente vantaggio di prestazioni) ovvero,
se sei fortunato, piu` semplice (ad esempio se puoi
giocare interamente su aree di memoria statiche
invece di dovertele allocare dinamicamente).
La gestione esplicita della memoria in termini di
malloc e free tende ad essere la parte piu` sottile
e complessa di quei programmi C che gestiscono
strutture dati non interamente banali, e uno degli
elementi principali che rendono il C un linguaggio
NON facile da usare, nonostante la spartana
semplicita` del linguaggio stesso.
Alex


Il problema della tua struttura dati consiste nel fatto che le stringhe
non hanno, nella convenzione C, una informazione esplicita della
lunghezza, che viene desunta all'occorrenza dal carattere '\0' alla
fine della stringa stessa.
Nell'esempio che segue ho creato una versione "persistibile" della
tua struttura, esplicitando le lunghezze.
Ho popolato la struttura con i dati presi dalla tua, allocando memoria
(e rilasciandola) in modo da non avere problemi di variabili che escono
di visibilita' (problema comunque che dipende da cosa stai facendo ...).
Successivamente ho aperto un file ed ho scritto prima le lunghezze
delle stringhe, e poi le stringhe stesse.
In questo modo in fase di recupero dei dati basta leggere la lunghezza,
allocare memoria, leggere la stringa, e come per magia il puntatore
a file (espressione molto brutta per dire puntatore al carattere corrente
nel file) si posiziona all'inizio della prossima stringa da leggere.
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <io.h>
#include <fcntl.h>
#pragma pack(1)
typedef struct {
    char *nome;
    char *cogn;
    int  eta;
    } cartella;
typedef struct {
 unsigned char LenNome;
 char *nome;
 unsigned char LenCogn;
    char *cogn;
    int  eta;
    } PersistCartella;
#pragma pack()
void PreparePersist(cartella *pSrc,PersistCartella *pDest){
 pDest->eta    =pSrc->eta;
 pDest->LenNome=strlen(pSrc->nome);
 pDest->nome=malloc(pDest->LenNome+1);
 strcpy(pDest->nome,pSrc->nome);
 pDest->LenCogn=strlen(pSrc->cogn);
 pDest->cogn=malloc(pDest->LenCogn+1);
 strcpy(pDest->cogn,pSrc->cogn);
}
void DestroyPersist(PersistCartella *pDest){
 free(pDest->nome);
 free(pDest->cogn);
}
int main (int argc, char ** argv){
 cartella MyCartella;
 PersistCartella MyPersist;
 char String1[]="Mario";
 char String2[]="Bianchi";
 int  fd;
 MyCartella.nome=String1;
 MyCartella.cogn=String2;
 MyCartella.eta=21;
 PreparePersist(&MyCartella,&MyPersist);
 fd=_open("c:\\temp\\try001.dat",_O_CREAT | _O_RDWR);
  _write(fd,&MyPersist.LenNome,sizeof(unsigned char));
  _write(fd,MyPersist.nome,MyPersist.LenNome);
  _write(fd,&MyPersist.LenCogn,sizeof(unsigned char));
  _write(fd,MyPersist.cogn,MyPersist.LenCogn);
  _write(fd,&MyPersist.eta,sizeof(int));
 _close(fd);
 DestroyPersist(&MyPersist);
 return 1;
}
+-------------------------------+----------------------------+
| name    : Brugiolo Ivan       | C/C++ Win32 programming    |
| address : via Conche 59       | NT administration          |
|           35020, Brugine (PD) | Linux user                 |
| phone   : 39+049-9735498      | Windows CE device drivers  |
| email   : 
iv...@iperv.it
      | ASP                        |
+-------------------------------+----------------------------+



