Newsgroup: it.comp.lang.c
Titolo: lista collegata e file

Salve ragazzi, mi chiedevo, visto che un file binario puo' salvare
un'area di memoria (contigua) se potesse salvare anche una lista
collegata. Se si.come?
Grazie a tutti

 collegata. Se si.come?
Il modo piu semplice e' avere la lista organizzata in "pagine" di
dimensione fissa. Le memorizzi, a partire dalla prima, di seguito
una dietro l'altra usando fwrite() :-)
sapendo il numero di pagina e la dimensione della pagina, puoi usare
fseek() per recuperare una pagina specifica.
HTH
C:\>iao Angelo
-- 
Posted via Mailgate.ORG Server - 
http://www.Mailgate.ORG

 collegata. Se si.come?
Quello che chiedi è possibile, ma è un grandissimo rebelòtt!
Il fatto è che una lista, sotto sotto, altro non è che un typo "struct" che
contiene almeno un puntatore a sè stesso. Il problema è che non si può
scrivere in un file un puntatore. O meglio, si può anche, solo che il valore
di un puntatore cessa di avere senso quando termina l'esecuzione del
programma.
Per poter fare una cosa del genere devi, prima di scrivere i record nel
file, convertire i puntatori che esso contiene in un identificatore
convenzionale e poi, quando rileggi i record, devi essere in grado da quegli
identificatori convenzionali di ricostruire tutti i "link" fra i vari
record, cioè dei nuovi puntatori analoghi a quelli di partenza.
Siccome oggi ci avevo un po' di tempi morti per un'installazione che sto
facendo sull'altra macchina, ho provato a fare un'implementazione usando
come identificatori convenzionali dei numeri progressivi che corrispondono
all'ordine in cui i record si presentano in uno dei possibili
attraversamenti della lista. Eccaccà:
// *INIZIO*
#include <stdlib.h>
#include <stdio.h>
typedef struct _MyList_ MyList;
typedef union
{
   MyList * Ptr;
   int Index;
}
MyListPtr;
struct _MyList_
{
   int Pippo; // Dovrà pur contenere qualche dato, 'sta lista...
   MyListPtr Prev;
   MyListPtr Next;
};
typedef struct
{
   int NumElems;
}
MyListHeader;
void MyListWrite (const char * fname, const MyList * list)
{
   MyListHeader header;
   MyList buff;
   const MyList * (*conv);
   const MyList * elem;
   FILE * f;
   int i;
   // Conta gli elementi
   for (header.NumElems = 0, elem = list;
        elem != NULL;
        elem = elem->Next.Ptr, header.NumElems++)
      ;
   // Crea la tabella di conversione da puntatori a indici
   conv = malloc(sizeof(MyList*) * header.NumElems);
   for (i = 0, elem = list; elem != NULL; elem = elem->Next.Ptr, i++)
      conv[i] = elem;
   // Scrivi la header
   f = fopen(fname, "wb");
   fwrite(&header, sizeof(header), 1, f);
   // Scrivi tutti gli elementi
   for (elem = list; elem != NULL; elem = elem->Next.Ptr)
   {
      buff = *elem;
      // Converti i puntatori in indici
      buff.Prev.Index = buff.Next.Index = 0;
      for (i = 0;
           i < header.NumElems && buff.Prev.Index == 0 && buff.Next.Index == 0;
           i++)
      {
         if (conv[i] == elem->Prev.Ptr)
            buff.Prev.Index = i;
         if (conv[i] == elem->Next.Ptr)
            buff.Next.Index = i;
      }
      fwrite(&buff, sizeof(buff), 1, f);
   }
   // Chiudi tutto
   free(conv);
   fclose(f);
}
MyList * MyListRead (const char * fname)
{
   MyListHeader header;
   MyList ** conv;
   MyList * list;
   FILE * f;
   int i;
   // Leggi la header
   f = fopen(fname, "rb");
   fread(&header, sizeof(header), 1, f);
   // Alloca e leggi tutti gli elementi
   conv = malloc(sizeof(MyList*) * header.NumElems);
   for (i = 0; i < header.NumElems; i++)
   {
      conv[i] = malloc(sizeof(MyList));
      fread(conv[i], sizeof(sizeof(MyList)), 1, f);
   }
   // Converti gli indici in puntatori
   for (i = 0; i < header.NumElems; i++)
   {
      if (conv[i]->Prev.Index == 0)
         conv[i]->Prev.Ptr = NULL;
      else
         conv[i]->Prev.Ptr = conv[conv[i]->Prev.Index];
      if (conv[i]->Next.Index == 0)
         conv[i]->Next.Ptr = NULL;
      else
         conv[i]->Next.Ptr = conv[conv[i]->Next.Index];
   }
   // Chiudi tutto
   list = conv[0];
   free(conv);
   fclose(f);
   return list;
}
// *FINE*
T'avviso che *NON* ho assolutamente testato queste funzioni, quindi "nessuna
garanzia implicita o esplicita, bla bla bla bla". Probabilissimo che siano
piene di bagherozzi. Inoltre, come vedi, le funzioni sono appena abbozzate:
come minimo bisogna aggiungere il controllo dei possibili errori di
allocazione di memoria e di accesso ai file.
--
Cingar
--------------------------------
Inviato via 
http://arianna.libero.it/usenet/

          conv[i]->Next.Ptr = conv[conv[i]->Next.Index];
Analogamente, questo codice nella funzione MyListRead dovrebbe essere così:
   if (conv[i]->Prev.Index == 0)
      conv[i]->Prev.Ptr = NULL;
   else
      conv[i]->Prev.Ptr = conv[conv[i]->Prev.Index - 1];
   if (conv[i]->Next.Index == 0)
      conv[i]->Next.Ptr = NULL;
   else
      conv[i]->Next.Ptr = conv[conv[i]->Next.Index - 1];
--
Cingar
-- 
questo articolo e` stato inviato via web dal servizio gratuito 
http://www.newsland.it/news
 segnala gli abusi ad 
ab...@newsland.it

 record, cioè dei nuovi puntatori analoghi a quelli di partenza.
Senza aver guardato il codice... basta scrivere tutti gli elementi della
lista in ordine, senza necessita` di utilizzare un id e tralasciando i
puntatori. Stessa cosa si puo` fare con gli alberi (es. visito in
preorder dumpando tutti i nodi - NULL compresi - e poi ricostruisco il
tutto).
Luca
-- 
Home: 
http://kronoz.cjb.net
Windows NT: Designed for the Internet. The Internet: Designed for Unix.

ragazzi siate stati meravigliosi. vi ringrazio!!!