【问题标题】:C: Adding data from text file into a singly linked listC:将文本文件中的数据添加到单链表中
【发布时间】:2014-11-05 21:12:17
【问题描述】:

我最近开始学习 C 编程。我有一些java经验,所以我知道我的代码方式,我喜欢思考.. 我正在做的这件小事正在杀死我。 我正在尝试制作一个从文本文件中读取行的程序->将其存储在单链表中->打印出单链表 到目前为止,这是我的代码:

typedef struct node {
    char *data;
    struct node *next;
} node;

node *start = NULL;
node *current;


void add(char *line) {

    node *temp = malloc(sizeof(node));
    // This line under I believe where my problem is...
    temp->data = line;
    temp->next = NULL;
    current = start;

    if(start == NULL) {
        start = temp;
    } else {
        while(current->next != NULL) {
            current = current->next;
        }
        current->next = temp;
    }
}

这是我读取文件并将字符发送到添加函数的函数

void readfile(char *filename) {
    FILE *file = fopen(filename, "r");

    if(file == NULL) {
        exit(1);
    }

    char buffer[512];

    while(fgets(buffer, sizeof(buffer), file) != NULL) {
        // I've tried to just send i.e: "abc" to the add function
        // which makes the program work.
        // like: add("abc");
        // my display method prints out abc, but when I'm sending buffer
        // it prints out nothing
        // Thing is, I've spent way to much time trying to figure out what
        // I'm doing wrong here...
        add(buffer);
    }

    fclose(file);
}

我确信这是一个相当简单的问题,但我在这个问题上花了太多时间。 如果还有其他看起来不合适/可能更好的东西,我也很感谢您的反馈:)

【问题讨论】:

    标签: c file singly-linked-list


    【解决方案1】:

    试试:

    temp->data = strdup(line);
    

    duplicate(复制)什么线指向。

    否则,每一行都指向buffer,每行都会覆盖该buffer

    【讨论】:

    • 解决了问题!谢谢你这么快重播
    • 请注意,strdup 不是 ANSI C 标准的一部分(在 Windows 上已弃用)。 (对于我猜这是的任务,你应该没问题,只要确保你理解strdup() 执行malloc() 时会发生什么,你需要free())。
    【解决方案2】:

    您需要为字符串分配内存 - 每一行都被读入 buf,因此您需要将其复制出来,否则它将被后续行覆盖。我建议两种方法中的一种,第一种是最简单的你已经拥有的方法,但第二种更好,因为你只需要为每个对象执行一次 free()。

    第一个只是对 add() 函数的一次更改:

    temp->data = malloc(strlen(line)+1);
    strcpy(temp->data, line);
    

    现在,当您想释放链表中的对象时,您必须首先对数据调用 free(),然后对对象本身调用 free()。

    但是你可以稍微改变结构,然后你可以一次性分配整个对象:

    typedef struct node {
      struct node *next;
      char data[0];
    } node;
    

    那么你的 add() 函数将如下所示:

    void add(char *line) {
    
      node *temp = malloc(sizeof(node)+strlen(line)+1);
      strcpy(temp->data, line);
      temp->next = NULL;
      current = start;
    
      if(start == NULL) {
        start = temp;
      } else {
        while(current->next != NULL) {
          current = current->next;
        }
        current->next = temp;
      }
    }
    

    请注意,您当然应该在生产代码中的每个 malloc() 之后进行错误检查。处理完一个对象后,一个 free() 就足以释放整个结构。

    编辑:“数组长度 0”功能是 GCC 特定的扩展,如 cmets 中的 @crashmstr 所述。如果你使用长度为 1 的数组,它应该可以在任何编译器中工作:

    typedef struct node {
      struct node *next;
      char data[1];
    } node;
    

    由于在这种情况下已经分配了一个额外的字节,所以 add() 函数中的 malloc() 调用将变为:

      node *temp = malloc(sizeof(node)+strlen(line)+1-1);
    

    (当然+1-1可以省略,但这只是为了表明我们仍然需要空终止符的空间,但是sizeof中已经包含了一个额外的字节)。

    【讨论】:

    • 当然,您也可以按照上面 John Hascall 的建议进行操作 - 这是第一个版本的简写,我只是为了教学价值明确地这样做了。 strdup() 与上面的 malloc/strcpy 对完全相同,(如果 malloc 失败,则返回 NULL)。
    • 第二个选项看起来像 GCC 扩展 Arrays of Length Zero,我会避免使用它。
    • @crashmstr 你是对的,我已经使用了足够多的时间,以至于我把它误认为是标准功能。最好避免用于可移植程序。您可以使用长度为 1 的数组,或使用您引用的文章中的 C99 语法。
    猜你喜欢
    • 1970-01-01
    • 2018-04-25
    • 2012-11-03
    • 1970-01-01
    • 1970-01-01
    • 2019-04-28
    • 2021-08-20
    • 2023-03-21
    • 1970-01-01
    相关资源
    最近更新 更多