C:用于构建char *的链接列表的fgets用法

我是否错误地使用了fgets()

我正在尝试构建一个字符串链接列表( char * ),将每个新行添加到LL的末尾。 我正在从文件中读取这些行,但由于某种原因,每个行都被正在处理的当前行覆盖,只有在while循环中使用fgets() while ,add函数似乎正在正确接收每一行。

如果我在main()单独添加行,则没有问题。

这是一个示例输入文件:

input.txt中:

 This life, which had been the tomb of his virtue and of his honour, is but a walking shadow; a poor player, that struts and frets his hour upon the stage, and then is heard no more: it is a tale told by an idiot, full of sound and fury, signifying nothing. --William Shakespeare 

代码:

 #include  //printf, fopen #include  //exit, EXIT_FAILURE #include  //strlen struct node { char *line; struct node *next; }; void print(struct node *node); void add(struct node **head, char *newLine) { //printf("%s", newLine); struct node *new_node = (struct node *)malloc(sizeof(struct node)); struct node *curr = *head; new_node->line = newLine; new_node->next = NULL; if (*head == NULL) { *head = new_node; } else { while (curr->next != NULL) { curr = curr->next; } curr->next = new_node; } print(*head); } void print(struct node *node) { printf("\n"); while (node != NULL) { printf("%s\n", node->line); node = node->next; } } int main(int argc, char *argv[16]) { char newLine[81]; struct node *head = NULL; FILE *fp = fopen(argv[1], "r"); if (fp == NULL) { printf("ERROR: file open failed"); exit(EXIT_FAILURE); } while (fgets(newLine, 81, fp)) { add(&head, newLine); } add(&head, "why"); add(&head, "does"); add(&head, "this"); add(&head, "work??"); fclose(fp); print(head); return 0; } 

有人可以向我解释发生了什么事吗? 我一直把头撞在墙上太久了。 我已经尝试使用一些注释的打印语句,但调试失败。

您的问题出在add()方法中。 它不断向列表添加相同的缓冲区指针。 您需要将列表中的缓冲区复制到新分配的空间,即。 node-> line也需要进行malloced,并将newLine复制到其中。 不要忘记malloc(strlen(newLine)+ 1)。

您有一个用于存储输入的缓冲区。 并且在添加节点时将指针传递给此单个缓冲区的第一个元素。 这意味着所有节点中的字符串指针将指向同一个缓冲区。 最后会包含您阅读的最后一个字符串。

最简单的解决方案是使节点结构中的字符串成为一个数组,并将字符串复制到其中。

另一种解决方案是动态地为字符串分配内存(记住终止空字符)并再次将字符串复制到该内存中。

使用常量字符串文字时的区别在于每个字符串都是不同的数组。

您必须为每一行分配内存。 按照当前编码,所有节点都指向main()的本地数组,每次调用fgets()都会覆盖其内容。

另请注意,添加到列表中的每一行都包含一个终止换行符,您可能应该在调用之前将其删除。

这是一个更正版本:

 #include  // printf, fopen #include  // exit, EXIT_FAILURE #include  // strlen, strdup struct node { char *line; struct node *next; }; void print(struct node *node); void add(struct node **head, char *newLine) { //printf("%s", newLine); struct node *new_node = malloc(sizeof(struct node)); struct node *curr = *head; new_node->line = strdup(newLine); new_node->next = NULL; if (*head == NULL) { *head = new_node; return; } while (curr->next != NULL) { curr = curr->next; } curr->next = new_node; print(*head); } void print(const struct node *node) { printf("\n"); while (node != NULL) { printf("%s\n", node->line); node = node->next; } } int main(int argc, char *argv[16]) { char newLine[81]; struct node *head = NULL; FILE *fp = fopen(argv[1], "r"); if (fp == NULL) { printf("ERROR: file open failed"); exit(EXIT_FAILURE); } while (fgets(newLine, sizeof newLine, fp)) { newLine[strcspn(newLine, "\n")] = '\0'; // strip the newline if present add(&head, newLine); } add(&head, "why"); add(&head, "does"); add(&head, "this"); add(&head, "work??"); fclose(fp); print(head); return 0; }