Ti copio-incollo i suggerimenti del mio prof per risolvere un esercizio mooolto simile al tuo, vedi tu se puoi trovarli utile:
traccia: «Salvare» una lista su file e «ricaricarla»
• Supponiamo di avere in memoria una generica lista
dinamica, definita nel modo "consueto":
typedef struct Elem { Tipo dato;
struct Elem * next; } Nodo;
• Vogliamo scrivere due funzioni
– void saveList( Nodo * lista, FILE * fp );
– Nodo * loadList( FILE * fp );
che salvano su file il contenuto della lista e
ricostruiscono una lista analoga a quella salvata
Così la lista potrà sopravvivere al tempo di vita del programma
SOLUZIONE COME FILE DI TESTO
• Scrittura
– Scriviamo sul file, in forma di sequenza di stringhe, il contenuto
di tutti i nodi, elencando separatamente campi e/o elementi di
Tipo (se si tratta di un tipo struct e/o array)
• Operiamo le eventuali conversioni necessarie dai generici
tipi base in stringhe (interi, float, … convertiti in opportune
stringhe)
• Lettura
– Leggiamo uno alla volta i valori dal file, riempiendo i nodi di una
lista via via allocati per accogliere tali valori
• Operiamo le conversioni opposte, in base alla
corrispondenza posizionale tra i valori e i campi (il primo
valore nel primo campo, il secondo nel secondo, …
convertendo stringhe ? interi, float, …)
• Con questa strategia il file generato è ragionevolmente leggibile (e modificabile)
da parte dell'occhio umano, intervenendo con un normale editor di testo
SOLUZIONE COME FILE BINARIO
• Scrittura
– Scriviamo sul file una sequenza di "blocchi di byte" che siano
ognuno la "immagine fedele" (bit a bit) del contenuto della
memoria occupata dai dati (di tipo Tipo), senza conversioni
• In questo modo un intero di valore 35 non sarà rappresentato
dai caratteri consecutivi '3' e '5', ma dai byte della sua codifica in
complemento a due (00000000 00000000 00000000 00100011)
• Ogni blocco scritto "misura" esattamente sizeof(Tipo) byte
• Lettura
– Leggiamo i blocchi di byte dal file a ritmo di sizeof(Tipo),
riempiendo progressivamente i nodi di una lista
• La corrispondenza è ancora posizionale, ma direttamente sulle
celle di memoria, "riempite" nell'ordine in cui furono "svuotate"
• Il file così generato è (di norma) del tutto illeggibile per l'occhio
umano
ATTENZIONE
• Non possiamo salvare su file i valori dei puntatori e sperare che, in futuro, alla loro lettura
(da parte di un altro programma, magari su altro elaboratore) essi siano ancora
validamente dereferenziabili
• Salviamo i dati su file nell'ordine in cui compaiono nella lista, e l’ "infrastruttura di
collegamento" (i puntatori) dovrà essere ricreata ogni volta che si carica la lista
• N.B. Attenzione anche al contenuto dei dati…
– È possibile che i dati contenuti nei nodi (cioè le struct di tipo Tipo) siano direttamente
contenuti nella struct, senza puntatori ad altre parti (stringhe o altri dati dinamici).
– Ma è anche possibile che il Tipo contenga puntatori ad altri dati… ovviamente anche quei
puntatori, se messi su file, perderebbero significato!
• Occorre recuperare i dati puntati e salvare su file anche quelli, per poter poi ricostruire la lista…