Domanda

Sto sviluppando un database di un'applicazione che memorizza una struttura contenente:

struct Dictionary
{
    char *key;
    char *value;

    struct Dictionary *next;
};

Come potete vedere, sto usando una lista collegata per memorizzare le informazioni.Ma il problema inizia quando l'utente chiude il programma.Voglio le informazioni che devono essere memorizzati da qualche parte.Quindi stavo pensando di memorizzare l'elenco collegato in modo permanente o temporaneo file utilizzando fopen, quindi, quando l'utente avvia il programma, è possibile recuperare la lista collegata.Qui è il metodo che stampa la lista collegata alla console:

void PrintList()
{
    int count = 0;
    struct Dictionary *current;

    current = head;

    if (current == NULL)
    {
            printf("\nThe list is empty!");
        return;
    }

    printf("    Key \t  Value\n");
    printf("  ======== \t ========\n");

    while (current != NULL)
    {
        count++;
        printf("%d.  %s \t %s\n", count, current->key, current->value);
        current = current->next;
    }
}

Così sto pensando di modificare questo metodo per stampare le informazioni attraverso fprintf invece di printf e quindi il programma sarebbe solo ottenere le informazioni dal file.Qualcuno potrebbe aiutarmi su come posso leggere e scrivere il file?Che tipo di file deve essere temporanea o regolare?Come devo modificare il formato del file (come pensavo di aver appena prima la chiave, quindi il valore, quindi un carattere di nuova riga)?

È stato utile?

Soluzione

Il file dovrebbe probabilmente essere regolare. Un file temporaneo non è garantito per essere lì la prossima volta che il vostro avviare l'applicazione. Inoltre, il formato non guarda bene per l'uomo, non così bene per le macchine. Mi raccomando sia creare il proprio formato di file binario o utilizzando XML (o forse JSON?). Si potrebbe probabilmente formattarlo abbastanza facilmente come

key1\0value1\0key2\0value2\0....

scriverò un esempio veloce è il codice psuedoish:

//To write...
Dictionary *this=begin_list;
while(this!=null){
  for(i=0;i<strlen(this->key);i++){
    write_byte(this->key[i]);
  }
  for(i=0;i<strlen(this->value);i++){
    write_byte(this->value[i]);
  }
  this=this->next;
}

//to read...
Dictionary *prev;
Dictionary *this;
char *buffer;
while(!eof){
  buffer=malloc(MAX_STRING_LEN);
  int i=0;
  this=malloc(sizeof(Dictionary)
  while(i<MAX_STRING_LEN){ //note no error checking
    buffer[i]=read_byte();
    if(buffer[i]==0){
      break;
    }
  }
  this->key=buffer;
  buffer=malloc(MAX_STRING_LEN)
  while(i<MAX_STRING_LEN){ //note no error checking
    buffer[i]=read_byte();
    if(buffer[i]==0){
      break; 
    }
  }
  this->value=buffer;
  if(prev!=null){
    prev->next=this;
  }
  this->next=null;
  prev=this;
}

Lo so che è un cattivo esempio. Credo che scanf o simili possono rendere il lavoro una tonnellata più facile, ma le mie capacità C sono sempre arrugginito.

Altri suggerimenti

Il problema di fondo è che i puntatori non si traduce in un archivio esterno.Non vi è alcuna garanzia che quando il programma viene eseguito di nuovo, avrà lo stesso range di memoria (indirizzi).Dato questo principio, ci sono metodi alternativi per la memorizzazione dei dati.

Processi per persistente di dati:
1.L'utilizzo di un database, di piccole o grandi dimensioni.
2.Convertire i vostri dati di testo ASCII in un acquisibile in formato.
3.L'uso di binari di lunghezza fissa record
4.Utilizzare con dimensioni variabili binarie record
5.Implementare un dizionario struttura di dati utilizzando il file offset invece di puntatori.

Utilizzo Di Un Database
Lascia un applicazione professionale (che è stato testato e funziona) gestione dei dati.Questo consente di concentrarsi sull'utilizzo di dati piuttosto che di stoccaggio e di retreival.

Convertire in un formato leggibile
L'idea è quella di scrivere i dati in un file in un formato che è facile da recuperare e mantenere.Gli esempi includono i Valori Separati da Virgola (CSV), XML e file INI.Questo richiede che il codice per leggere e scrivere i dati.Ci sono librerie per assistere.

L'uso di binari di lunghezza fissa record
Con record di lunghezza fissa, la lettura dei dati dal file e inserito nel dizionario.I file binari sono molto efficienti quanto riguarda il trasferimento di dati, ma non è molto portatile, soprattutto quando le versioni del sistema operativo cambiare, piattaforme di modificare o di versioni del compilatore cambiare.Ci possono essere uno spreco di spazio per il record di testo.

Utilizzare con dimensioni variabili binarie record
Questa tecnica consente di risparmiare spazio, ma aumenta il tempo di elaborazione.Ogni record deve essere elaborato al fine di trovare la posizione di quella successiva.L'accesso casuale ai record è difficile.Altrimenti simili a binari di lunghezza fissa record.

Implementare un dizionario struttura di dati nel file
Stesso algoritmo come memoria di base struttura di dati ad eccezione di usa offset di file invece di puntatori.Nuovo record può essere aggiunto alla fine del file.Bonifica voci eliminate è difficile e comporta la frammentazione.La frammentazione può essere risolto mediante la scrittura di un nuovo file.Se si sta andando attraverso questo grande sforzo, si potrebbe anche utilizzare un database esistente applicazione.

Un modo è possibile leggere o scrivere il file sta usando freopen in questo modo: freopen ( "file .out", "peso", stdout), allora siete di printf andrà al file .out e non sarà necessario modificare il codice di molto.

È possibile memorizzare le informazioni in formato testo, ma credo davvero che il modo migliore per farlo è salvare le informazioni in un file binario. È possibile controllare più su questa ricerca informazioni su fread e fwrite.

Ecco un modo per risolvere il problema.

Creare una struttura di dati per le voci di elenco come questo:

struct DictionaryArchive {
    char key[MAX_KEY_LENGTH];
    char value[MAX_VALUE_LENGTH];
    int next;
};

Si dovrà determinare i valori di MAX_KEY_LENGTH e MAX_VALUE_LENGTH secondo i dati che si aspettano.

Ora, convertire il vostro elenco collegato in un array di queste strutture. Invece di memorizzare un puntatore per posizionare l'elemento successivo, si memorizzare l'indice di campo dell'elemento successivo. Questo trasforma la lista in un formato in cui ogni elemento è una dimensione prevedibile l'intero elenco è una campata consecutivo di memoria. Ora, è possibile fwrite questa matrice in un file binario per archiviarlo, e fread di nuovo fuori per ripristinarla.

A molto più efficiente dello spazio alternativa all'uso matrici char dimensione fissa sopra è quello di definire invece un formato di file personalizzato invece di utilizzare strutture statiche. Per il vostro caso, è possibile utilizzare un formato di file come questo per memorizzare i dati in un modo recuperabili:

  • La lista è scritto nel file in ordine, iniziando con la testa e seguendo le indicazioni next alla coda
  • Ogni elemento della lista verrà memorizzato utilizzando quattro campi di dati nel seguente ordine:
    1. 16-bit integer, key_length
    2. array char 8 bit con elementi key_length, key_data
    3. 16-bit integer, value_length
    4. array char 8 bit con elementi value_length, value_data

Ora, si può camminare l'elenco, lo scarico dei dati al nodo di file per nodo. Per ricostruire i dati, leggere il file binario, generare nuovi elementi struct Dictionary per ogni voce, e collegarli insieme nell'ordine in cui appaiono nel file.

Il codice per scrivere i dati nel file di dati sarebbe simile a questa (non testato, solo a scopo illustrativo):

FILE* fd;
size_t len;
struct Dictionary* pDict = list_head;
fd = fopen("output_file.dat", "w");

// Walk through the list, storing each node
while (pDict != NULL) {
    // Store key
    len = strlen(pDict->key);
    fwrite(&len, sizeof(len), 1, fd);
    fwrite(pDict->key, len, sizeof(char), fd);

    // Store value
    len = strlen(pDict->value);
    fwrite(&len, sizeof(len), 1, fd);
    fwrite(pDict->value, len, sizeof(char), fd);

    // Move to next list node
    pDict = pDict->next;
};

fclose(fd);

Il tuo codice per leggere l'out di dati sarebbe molto simile (leggere, invece di scrivere, e di creare un nuovo oggetto struct Dictionary per ogni iterazione del ciclo).

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top