Frage

Ich bin eine Datenbank-ähnliche Anwendung zu entwickeln, dass speichert eine eine Struktur:

struct Dictionary
{
    char *key;
    char *value;

    struct Dictionary *next;
};

Wie Sie sehen können, bin ich eine verknüpfte Liste zu speichern Informationen verwenden. Aber das Problem beginnt, wenn der Benutzer des Programms beendet werden. Ich möchte, dass die Informationen, die irgendwo gespeichert. Also habe ich die verknüpfte Liste der Speicherung in einer permanenten oder temporären Datei fopen, dann dachte, wenn der Benutzer das Programm gestartet wird, rufen Sie die verknüpfte Liste. Hier ist die Methode, die verknüpfte Liste auf die Konsole ausgibt:

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;
    }
}

Also ich modifizieren diese Methode denke, die Informationen über fprintf anstelle von printf zu drucken und dann das Programm würde nur bekommen Infomationen aus der Datei. Könnte mir jemand helfen, wie ich in diese Datei lesen und schreiben können? Welche Art von Datei sollte es, vorübergehende oder regelmäßig sein? Wie soll ich das Dateiformat (wie ich den Wert zunächst nur den Schlüssel hat, dann, dann ein Newline-Zeichen zu denken war)?

War es hilfreich?

Lösung

Die Datei sollte wahrscheinlich regelmäßig sein. Eine temporäre Datei wird dort nicht das nächste Mal sein garantiert, um Ihre Anwendung starten. Auch Ihr Format es sieht gut aus für die Menschen, nicht so gut für Maschinen. Ich würde entweder empfehlen, ein eigenes binäres Dateiformat erstellen oder die Verwendung von XML (oder vielleicht JSON?). Man könnte es wahrscheinlich formatiert werden ziemlich leicht wie

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

Ich werde ein kurzes Beispiel schreiben ist psuedoish Code:

//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;
}

Ich weiß, es ist ein schlechtes Beispiel. Ich denke, scanf oder ähnliches kann den Job eine Tonne leichter machen, aber meine C Fähigkeiten bekommen rostig.

Andere Tipps

Das grundlegende Problem ist, dass Zeiger nicht übersetzen zu externen Speichern. Es gibt keine Garantie, dass, wenn Ihr Programm erneut ausgeführt wird, wird es die gleichen Speicherbereiche (Adressen) hat. Vor diesem Prinzip gibt es alternative Methoden, um Ihre Daten zu speichern.

Prozesse für persistente Daten:
1. Verwenden Sie eine Datenbank, klein oder groß.
2. Ihre Daten in ASCII-Text in einem abtastbaren Format konvertieren.
3. Verwenden fester Länge binäre Datensätze
4. Verwenden variabler Größe binäre Datensätze
5. Implementieren einer Struktur Wörterbuch Datendatei Offsets anstelle von Zeigern verwendet wird.

mit Hilfe einer Datenbank
Lassen Sie eine professionelle Anwendung (die getestet und funktioniert wurde) verwalten Sie Ihre Daten. Auf diese Weise können Sie konzentrieren sich die Daten über die Verwendung anstatt Lagerung und retreival.

Konvertieren zu einem abtastbaren Format
Die Idee dabei ist es, die Daten in die Datei in einem Format zu schreiben, die leicht abzurufen und zu pflegen ist. Beispiele hierfür sind Comma Separated Values ??(CSV), XML und INI. Dies erfordert Code auf Ihrer Seite, die Daten zu lesen und zu schreiben. Es gibt Bibliotheken zu unterstützen.

Verwendung fester Länge binäre Datensätze
Mit fester Länge Aufzeichnungen werden die Daten aus der Datei gelesen und in Ihr Wörterbuch eingefügt. Binär-Dateien sind sehr effizient, soweit die Übertragung von Daten, aber nicht sehr tragbar, vor allem, wenn Systemversionen ändern Betrieb, Plattformen verändern oder Compiler-Versionen ändern. Es kann eine Verschwendung von Platz für Text Aufzeichnungen sein.

Verwendung variabler Größe binäre Datensätze
Diese Technik spart Platz, sondern erhöht sich die Verarbeitungszeit. Jeder Datensatz muss bearbeitet werden, um den Standort des nächsten zu finden. Direktzugriff auf Aufzeichnungen ist schwierig. Ansonsten ähnliche binäre Datensätze mit fester Länge.

Implementieren Sie eine Wörterbuch-Datenstruktur in der Datei
Gleicher Algorithmus wie Ihr Gedächtnis basierte Datenstruktur außer Verwendungen Datei-Offsets anstelle von Zeigern. Neue Einträge können bis zum Ende der Datei angehängt werden. Reclaiming gelöschte Einträge ist schwierig und wird zu einer Fragmentierung führen. Fragmentierung kann durch das Schreiben eine neue Datei aufgelöst werden. Wenn Sie durch diese viel Mühe gehen, könnten Sie auch eine vorhandene Datenbank-Anwendung verwenden.

Eine Möglichkeit, um die Datei lesen oder schreiben kann, wird unter Verwendung der wie folgt freopen: freopen ( „file.out“, „wt“, stdout), dann werden Sie sind printf die zum file.out gehen und Sie werden den Code nicht viel ändern müssen.

können Sie speichern die Informationen im Klartext, aber ich glaube wirklich, dass der beste Weg, dies in einer Binärdatei speichert die Informationen zu tun ist. Sie können mehr über diese Suche Informationen über fread Check-out und fwrite.

Hier ist eine Möglichkeit, das Problem zu lösen.

Erstellen Sie eine Datenstruktur für Listenelemente wie folgt aus:

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

Sie müssen die Werte von MAX_KEY_LENGTH und MAX_VALUE_LENGTH entsprechend die Daten, um festzustellen, dass Sie erwartet werden.

Nun wandeln Sie Ihre verknüpfte Liste in ein Array dieser Strukturen. Statt einen Zeiger zu speichern, für das nächste Element Ortung, werden Sie den Array-Index des nächsten Elements speichern. Dieser wandelt die Liste in ein Format, wobei jedes Element eine vorhersagbare Größe Ihre gesamte Liste eine aufeinanderfolgende Spanne von Speicher ist. Jetzt können Sie dieses Array in eine Binärdatei fwrite es zu archivieren, und fread sie es wieder herzustellen wieder aus.

Eine viel mehr Platz sparende Alternative zur Verwendung von fester Größe char Arrays oben ist stattdessen ein Format benutzerdefinierte Datei zu definieren stattdessen statische Strukturen zu verwenden. Für Ihren Fall können Sie ein Dateiformat wie folgt verwenden Ihre Daten in einer abrufbaren Weise zu speichern:

  • Die Liste wird in die Datei geschrieben, um mit dem Kopf beginnend und im Anschluss an die next Zeiger auf den Schwanz
  • unter Verwendung von vier Datenfeldern in der folgenden Reihenfolge
  • Jeder Listeneintrag wird gespeichert:
    1. 16-Bit-Integer, key_length
    2. 8-Bit-Zeichen-Array mit Elementen key_length, key_data
    3. 16-Bit-Integer, value_length
    4. 8-Bit-Zeichen-Array mit Elementen value_length, value_data

Nun können Sie die Liste gehen, Ihre Daten in die Datei Knoten für Knoten Dumping. Um eine erneute zu erstellen, um Ihre Daten, lesen Sie die Binärdatei, erzeugen neue struct Dictionary Elemente für jeden Eintrag, und verknüpfen sie zusammen in der Reihenfolge, wie sie in der Datei angezeigt.

Ihr Code, um die Daten in die Datendatei zu schreiben, etwas würde wie folgt aussehen (ungetestet, nur zu Veranschaulichungszwecken):

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);

Ihr Code, um die Daten auszulesen sehr ähnlich wäre (lesen Sie statt schreiben, und erstellen Sie ein neues struct Dictionary Objekt für jede Schleife Iteration).

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top