【问题标题】:Read linked list from a file and load the data从文件中读取链表并加载数据
【发布时间】:2017-10-31 04:17:05
【问题描述】:

我编写了一个 C 代码来使用链表实现字典(节点按排序顺序) 我想将数据保存到文件中,并且能够在下次运行程序时重新加载数据。我无法从文件中加载数据。这是我的数据读写代码:

struct node{
    char word[20];
    char meaning[5][100]; //2D array for saving multiple meanings of a word
    struct node *next;
};

void ReadData(struct node *head)
{
    struct node *tail;
    FILE *fp = fopen("dictionary.data", "rb");
    if(fp == NULL)
    {
        printf("Error opening file..\n");
        return;
    }
    while(!feof(fp))
    {
        tail = (struct node*)calloc(1, sizeof(struct node));
        fread(tail->word, sizeof(head->word), 1, fp);
        fread(tail->meaning, sizeof(head->meaning), 1, fp);
        if(head == NULL) //for fresh run head is initialized with NULL
        {
            tail->next = head;
            head = tail;
        }
        else
        {
            head->next = tail;
            head = head->next;
        }
    }
    fclose(fp);
}

我无法将文件中的数据加载到链接列表中。代码不工作。我不知道问题出在哪里..
这是我将数据写入文件的方式:

/*I think this code is working because size of the file increases after running the code*/
void WriteData(struct node *head)
{
    FILE *fp = fopen("dictionary.data", "wb");
    if(fp == NULL)
    {
        printf("Error opening file..\n");
        return;
    }
    while(head != NULL)
    {
        fwrite(head->word, sizeof(head->word), 1, fp);
        fwrite(head->meaning, sizeof(head->meaning), 1, fp);
        head = head->next;
    }
    fclose(fp);
}

我使用了sizeof,而不是strlen,它是一个字符串。最后会有空字符 - 字符串没问题。但它会消耗更多的内存。

【问题讨论】:

  • 那个不是用来读的。它是用来写数据到下一个节点的。阅读将由fread完成
  • in ReadData 读取由fread if-else 部分用于修复节点之间的链接
  • else部分head->next = tail将新节点的地址分配给head指向的节点的next文件。现在我们必须将头指向新节点(尾),新节点的地址分配给前一个节点(head->next = tail)的next字段。因此,为了将head 指向新节点,我使用head = head->next 作为head->next=tail 的地址
  • 好的.. 但我认为这是一回事。因为head->next 持有tail 的地址
  • 主要问题是你不能在函数中改变调用者的head。在ReadData 中,不需要任何参数。 head 应该被返回。

标签: c file struct io linked-list


【解决方案1】:

试试这个(未经测试):

void ReadData(struct node **head){//or struct node *ReadData(void){ ... return head; }
    struct node temp = { .next = NULL };//{ {0}, {{0}}, NULL}
    struct node *hp, *curr;
    FILE *fp = fopen("dictionary.data", "rb");

    if(fp == NULL){
        printf("Error opening file..\n");
        return;
    }

    hp = *head;
    while(fread(temp.word, sizeof(temp.word), 1, fp) && fread(temp.meaning, sizeof(temp.meaning), 1, fp)){
        struct node *np = malloc(sizeof(*np));
        if(np == NULL){
            perror("couldn't make new node by malloc:");
            return ;//release list
        }
        *np = temp;

        if(hp == NULL){//for fresh run head is initialized with NULL
            curr = hp = np;
        } else {//If *head isn't NULL, you need to move to the last node first.
            curr = curr->next = np;
        }
    }
    fclose(fp);
    *head = hp;
}
//....................
int main(void){
    //...
    struct node *head = NULL;
    //...
    ReadData(&head);
    //...

【讨论】:

  • void 函数不能返回 NULL。如果malloc() 失败,则必须将所有指针传递给free(),否则会出现大量内存泄漏。
  • @user3629249 是的,Null 的返回是我的错误。谢谢你指出。我只是指出了Malloc失败时列表的发布,因为它不是中心的例子。
最近更新 更多