Вопрос

Я разрабатываю аналогичную базу данных приложение, которое хранит структуру AA, содержащую:

struct Dictionary
{
    char *key;
    char *value;

    struct Dictionary *next;
};

Как видите, я использую связанный список для хранения информации. Но проблема начинается, когда пользователь выходит из программы. Я хочу, чтобы информация была хранена где-то. Поэтому я думал о хранении связанного списка в постоянном или временном или временном файле, используя Fopen, затем, когда пользователь запускает программу, извлеките связанный список. Вот метод, который печатает связанный список к консоли:

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

Поэтому я думаю о модификации этого метода для печати информации через FPRINTF вместо Printf, а затем программа просто получит информацию из файла. Может кто-нибудь помочь мне о том, как я могу прочитать и писать в этот файл? Какой файл должен быть, временный или обычный? Как я должен отформатировать файл (например, я думал просто иметь ключ первым, то значение, то новенький символ)?

Это было полезно?

Решение

Файл, вероятно, должен быть регулярным. Файл TEMP не гарантирован там в следующий раз, когда ваш запуск вашего приложения. Кроме того, ваш формат там выглядит хорошо для людей, не так хорошо для машин. Я бы порекомендовал либо создать свой собственный формат двоичного файла или использование XML (или, возможно, JSON?). Вы, вероятно, могли бы отформатировать его довольно легко

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

Я напишу быстрый пример - это код 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;
}

Я знаю, что это плохой пример. Я думаю, что Scanf или аналогичный может сделать работу тонкой проще, но мои навыки C становится ржавым.

Другие советы

Фундаментальная проблема заключается в том, что указатели не переводятся на внешнее хранилище. Нет никакой гарантии, что когда ваша программа снова выполняется, она будет иметь одни и те же диапазоны памяти (адреса). Учитывая этот принцип, есть альтернативные методы для хранения ваших данных.

Процессы для постоянных данных:
1. Используйте базу данных, небольшую или большую.
2. Преобразуйте данные в текст ASCII в сканнете.
3. Используйте двойные двоичные записи
4. Используйте бинарные записи переменной размеров
5. Воспользуйтесь структурой данных словаря с использованием смещенных файлов вместо указателей.

Используя базу данных
Пусть профессиональное приложение (которое было проверено и работает) управлять вашими данными. Это позволяет сконцентрироваться на использовании данных, а не хранения и рефроивации.

Преобразовать в сканнетный формат
Идея здесь состоит в том, чтобы написать данные в файл в формате, который легко получить и поддерживать. Примеры включают запятые значения (CSV), XML и IINI. Это требует кода с вашей стороны для чтения и записи данных. Есть библиотеки, чтобы помочь.

Используйте фиксированную длину двоичных записей
С помощью записей фиксированной длины данные прочитаны из файла и вставляются в ваш словарь. Двоичные файлы очень эффективны, что и передающие данные, но не очень портативные, особенно при изменении версий операционной системы, изменение платформ или версии компилятора. Там может быть пустая трата пространства для текстовых записей.

Используйте бинарные записи переменной размеров
Эта техника экономит пространство, но увеличивает время обработки. Каждая запись должна быть обработана для того, чтобы найти местоположение следующего. Случайный доступ к записям трудно. В противном случае похоже на фиксированную длину двоичных записей.

Внедрить структуру данных словаря в файле
Та же алгоритм, что и ваша структура данных на основе памяти, за исключением использования файлов смещений вместо указателей. Новые записи могут быть добавлены до конца файла. Восстановление удаленных записей сложно и приведет к фрагментации. Фрагментация может быть разрешена путем написания нового файла. Если вы проходите много усилий, вы также можете использовать существующую приложение базы данных.

Один из способов прочитать или писать в файл, использует фриопен, как это: freopen ("file.out", "WT", stdout), то вы будете отправляться в файл. Наук, и вам не нужно будет изменять Код много.

Вы можете хранить информацию в простом тексте, но я действительно думаю, что лучший способ сделать это, это сохранить информацию в двоичном файле. Вы можете узнать больше об этой поисковой информации о FRAD и FWRITE.

Вот один из способов решить проблему.

Создайте структуру данных для ваших элементов списка:

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

Вам нужно будет определить значения MAX_KEY_LENGTH а также MAX_VALUE_LENGTH Согласно данным, которые вы ожидаете.

Теперь конвертируйте свой связанный список в массив этих структур. Вместо того, чтобы хранить указатель для определения следующего элемента, вы будете хранить индекс массива следующего элемента. Это преобразует ваш список в формат, в котором каждый элемент предсказуемый размер, ваш список - один последовательный промежуток памяти. Теперь вы можете fwrite Этот массив в двоичный файл для архивирования его и fread Это возвращается, чтобы восстановить его.

Гораздо больше космической альтернативы использования фиксированного размера char Массивы выше - вместо этого определяют пользовательский формат файла вместо использования статических структур. Для вашего случая вы можете использовать формат файла, такой как это, чтобы сохранить данные в полученном виде:

  • Список записывается в файл в порядке, начиная с головы и после next указатели на хвост
  • Каждый элемент списка будет храниться с использованием четырех полей данных в следующем порядке:
    1. 16-битное целое число, key_length
    2. 8-битный массив CHAR с key_length элементы, key_data
    3. 16-битное целое число, value_length
    4. 8-битный массив CHAR с value_length элементы, value_data

Теперь вы можете пройти список, сбрасывать данные в узел файлов на узле. Чтобы повторно создать данные, прочитайте двоичный файл, генерируйте новые struct Dictionary Элементы для каждой записи и связывают их вместе в порядке их появления в файле.

Ваш код для записи данных в файл данных будет выглядеть что-то подобное (только непроверенному, для иллюстрации):

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

Ваш код для чтения данных будет очень похожим (читать вместо записи и создать новый struct Dictionary Объект для каждой петли итерации).

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top