Pergunta

Estou desenvolvendo um aplicativo semelhante ao banco de dados que armazena a estrutura AA contendo:

struct Dictionary
{
    char *key;
    char *value;

    struct Dictionary *next;
};

Como você pode ver, estou usando uma lista vinculada para armazenar informações. Mas o problema começa quando o usuário sai do programa. Eu quero que as informações sejam armazenadas em algum lugar. Então, eu estava pensando em armazenar a lista vinculada em um arquivo permanente ou temporário usando o FOPEN; então, quando o usuário inicia o programa, recupere a lista vinculada. Aqui está o método que imprime a lista vinculada ao 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;
    }
}

Por isso, estou pensando em modificar esse método para imprimir as informações através do FPRINTF em vez de PrintF e, em seguida, o programa receberá a informação do arquivo. Alguém poderia me ajudar sobre como eu posso ler e escrever para este arquivo? Que tipo de arquivo deve ser, temporário ou regular? Como devo formatar o arquivo (como se eu estivesse pensando em apenas ter a chave primeiro, depois o valor, depois um personagem de nova linha)?

Foi útil?

Solução

O arquivo provavelmente deve ser regular. Um arquivo temp não é garantido para estar lá na próxima vez que você inicie seu aplicativo. Além disso, seu formato parece bom para os seres humanos, não tão bem para as máquinas. Eu recomendo criar seu próprio formato de arquivo binário ou usar XML (ou talvez JSON?). Você provavelmente poderia formatá -lo com muita facilidade

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

Vou escrever um exemplo rápido é o código PSUDOISH:

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

Eu sei que é um mau exemplo. Eu acho que Scanf ou similar pode facilitar o trabalho, mas minhas habilidades C estão ficando enferrujadas.

Outras dicas

A questão fundamental é que os ponteiros não se traduzem em armazenamento externo. Não há garantia de que, quando o seu programa é executado novamente, ele terá os mesmos intervalos de memória (endereços). Dado esse princípio, existem métodos alternativos para armazenar seus dados.

Processos para dados persistentes:
1. Use um banco de dados, pequeno ou grande.
2. Converta seus dados em texto ASCII em um formato digitalizado.
3. Use registros binários de comprimento fixo
4. Use registros binários de tamanho variável
5. Implemente uma estrutura de dados do dicionário usando compensações de arquivos em vez de ponteiros.

Usando um banco de dados
Deixe um aplicativo profissional (que foi testado e trabalha) gerenciar seus dados. Isso permite que você se concentre no uso dos dados em vez de armazenamento e retroramento.

Converter em um formato reproduzido
A idéia aqui é escrever os dados no arquivo em um formato fácil de recuperar e manter. Exemplos incluem valores separados por vírgula (CSV), XML e INI. Isso requer código da sua parte para ler e escrever os dados. Existem bibliotecas para ajudar.

Use registros binários de comprimento fixo
Com registros fixos de comprimento, os dados são lidos no arquivo e inseridos no seu dicionário. Os arquivos binários são muito eficientes no que diz respeito à transferência de dados, mas não muito portáteis, especialmente quando as versões do sistema operacional mudam, as plataformas mudam ou as versões do compilador mudam. Pode haver um desperdício de espaço para registros de texto.

Use registros binários de tamanho variável
Essa técnica economiza espaço, mas aumenta o tempo de processamento. Cada registro deve ser processado para encontrar a localização do próximo. O acesso aleatório aos registros é difícil. Caso contrário, semelhante aos registros binários de comprimento fixo.

Implementar uma estrutura de dados do dicionário no arquivo
O mesmo algoritmo que sua estrutura de dados baseada em memória, exceto que usa compensações de arquivos em vez de ponteiros. Novos registros podem ser anexados ao final do arquivo. As entradas excluídas de recuperação são difíceis e levarão à fragmentação. A fragmentação pode ser resolvida escrevendo um novo arquivo. Se você estiver passando por tanto esforço, também pode usar um aplicativo de banco de dados existente.

Uma maneira de ler ou escrever no arquivo é usar o Freopen como o seguinte: Freopen ("file.out", "WT", stdout), então você está imprimindo, irá para o arquivo.out e você não precisará modificar o código muito.

Você pode armazenar as informações em texto simples, mas eu realmente acho que a melhor maneira de fazer isso é salvar as informações em um arquivo binário. Você pode conferir mais sobre essas informações de pesquisa sobre Fread e Fwrite.

Aqui está uma maneira de resolver o problema.

Crie uma estrutura de dados para os itens da sua lista como este:

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

Você precisará determinar os valores de MAX_KEY_LENGTH e MAX_VALUE_LENGTH De acordo com os dados que você estará esperando.

Agora, converta sua lista vinculada em uma matriz dessas estruturas. Em vez de armazenar um ponteiro para localizar o próximo item, você armazenará o índice de matriz do próximo item. Isso converte sua lista em um formato em que cada elemento é um tamanho previsível, toda a sua lista é um período consecutivo de memória. Agora você pode fwrite Esta matriz para um arquivo binário para arquivá -lo, e fread Volte para restaurá -lo.

Uma alternativa muito mais eficiente em termos de espaço para usar o tamanho fixo char As matrizes acima são definir um formato de arquivo personalizado em vez de usar estruturas estáticas. Para o seu caso, você pode usar um formato de arquivo como este para armazenar seus dados de maneira recuperável:

  • A lista é gravada no arquivo em ordem, começando com a cabeça e seguindo o next ponteiros para a cauda
  • Cada item da lista será armazenado usando quatro campos de dados na seguinte ordem:
    1. Inteiro de 16 bits, key_length
    2. Matriz de char de 8 bits com key_length elementos, key_data
    3. Inteiro de 16 bits, value_length
    4. Matriz de char de 8 bits com value_length elementos, value_data

Agora, você pode andar na lista, despejando seus dados no nó do arquivo por nó. Para recrutar seus dados, leia o arquivo binário, gerar novos struct Dictionary Elementos para cada entrada e vinculá -los na ordem em que aparecem no arquivo.

Seu código para escrever os dados para o arquivo de dados seria algo assim (apenas para fins de ilustração):

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

Seu código para ler os dados seria muito semelhante (leia em vez de gravar e criar um novo struct Dictionary objeto para cada iteração do loop).

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top