将 fscanf 中的字符串附加到 C 中的链表
Append a string from fscanf to linked list in C
我想读取一个文件并将每个单词放在一个链表中。当我读取文件时,链表的节点数很好,但所有节点都等于最后一个字。
举个例子,如果我的文本文件是:
Hello good sir
我的链接列表将如下所示:
[sir,sir,sir]
应该是这样的:
[Hello, good, sir]
我的main.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
typedef struct NodeTag {
char *data;
struct NodeTag *next;
} Node;
Node *Node_create();
typedef struct ListTag {
struct NodeTag *first;
} List;
List *List_create();
void List_append(List *list, char *str);
void List_print(List *list);
int main(void) {
char word[100];
FILE *file = fopen("file.txt", "r");
if(file == NULL) {
printf("error in opening file\n");
return 1;
}
List *l = List_create();
while(fscanf(file, "%s", word) == 1){
List_append(l, word);
}
return 0;
}
这是我的功能。我删除了 destroy 和 free 函数以使其更清楚。
Node *Node_create() {
Node *node = malloc(sizeof(Node));
assert(node != NULL);
node->data = "";
node->next = NULL;
return node;
}
List *List_create() {
List *list = malloc(sizeof(List));
assert(list != NULL);
Node *node = Node_create();
list->first = node;
return list;
}
void List_append(List *list, char *str) {
assert(list != NULL);
assert(str != NULL);
Node *node = list->first;
while (node->next != NULL) {
node = node->next;
}
node->data = str;
node->next = Node_create();
}
void List_print(List *list) {
assert(list != NULL);
printf("[");
Node *node = list->first;
while (node->next != NULL) {
printf("%s", node->data);
node = node->next;
if (node->next != NULL) {
printf(", ");
}
}
printf("]\n");
}
如果我这样做,它会正常工作。所以我想我只附加了单词的指针,所以它一次又一次地指向同一个地方?
List_append(l, "test1");
List_append(l, "test2");
输出:
[test1, test2]
请注意,在 main
中,您有一个缓冲区存储字符串:
char word[100];
您将 word
作为参数传递给您的 List_append
方法,在此期间您编写
node->data = str;
这意味着所有节点都指向 main
中的 word
缓冲区以获取其字符串,因此所有节点都将显示相同的字符串。
要解决此问题,您需要在某处复制缓冲区。我建议您这样做:
node->data = strdup(str);
代码中可能还有其他问题,但这肯定是您在继续之前需要解决的问题。尝试更新它,看看它是否能解决您的问题。正如@Sean Bright 指出的那样,当您进行追加时,您似乎也在覆盖错误的字符串指针,因此您可能还需要修复它。
希望对您有所帮助!
在 List_append
内,您正在这样做:
node->data = str;
这会保存一个指向作为 str
传入的数据的指针。您在 main 中调用 List_append(l, word)
,这意味着您每次都将同一块内存传递给它,因此每个列表成员都指向同一块内存。
您需要在 List_append
:
中执行此操作
node->data = strdup(str);
这会将字符串复制到新分配的缓冲区中。清理时一定要free
它。
我想读取一个文件并将每个单词放在一个链表中。当我读取文件时,链表的节点数很好,但所有节点都等于最后一个字。
举个例子,如果我的文本文件是:
Hello good sir
我的链接列表将如下所示:
[sir,sir,sir]
应该是这样的:
[Hello, good, sir]
我的main.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
typedef struct NodeTag {
char *data;
struct NodeTag *next;
} Node;
Node *Node_create();
typedef struct ListTag {
struct NodeTag *first;
} List;
List *List_create();
void List_append(List *list, char *str);
void List_print(List *list);
int main(void) {
char word[100];
FILE *file = fopen("file.txt", "r");
if(file == NULL) {
printf("error in opening file\n");
return 1;
}
List *l = List_create();
while(fscanf(file, "%s", word) == 1){
List_append(l, word);
}
return 0;
}
这是我的功能。我删除了 destroy 和 free 函数以使其更清楚。
Node *Node_create() {
Node *node = malloc(sizeof(Node));
assert(node != NULL);
node->data = "";
node->next = NULL;
return node;
}
List *List_create() {
List *list = malloc(sizeof(List));
assert(list != NULL);
Node *node = Node_create();
list->first = node;
return list;
}
void List_append(List *list, char *str) {
assert(list != NULL);
assert(str != NULL);
Node *node = list->first;
while (node->next != NULL) {
node = node->next;
}
node->data = str;
node->next = Node_create();
}
void List_print(List *list) {
assert(list != NULL);
printf("[");
Node *node = list->first;
while (node->next != NULL) {
printf("%s", node->data);
node = node->next;
if (node->next != NULL) {
printf(", ");
}
}
printf("]\n");
}
如果我这样做,它会正常工作。所以我想我只附加了单词的指针,所以它一次又一次地指向同一个地方?
List_append(l, "test1");
List_append(l, "test2");
输出:
[test1, test2]
请注意,在 main
中,您有一个缓冲区存储字符串:
char word[100];
您将 word
作为参数传递给您的 List_append
方法,在此期间您编写
node->data = str;
这意味着所有节点都指向 main
中的 word
缓冲区以获取其字符串,因此所有节点都将显示相同的字符串。
要解决此问题,您需要在某处复制缓冲区。我建议您这样做:
node->data = strdup(str);
代码中可能还有其他问题,但这肯定是您在继续之前需要解决的问题。尝试更新它,看看它是否能解决您的问题。正如@Sean Bright 指出的那样,当您进行追加时,您似乎也在覆盖错误的字符串指针,因此您可能还需要修复它。
希望对您有所帮助!
在 List_append
内,您正在这样做:
node->data = str;
这会保存一个指向作为 str
传入的数据的指针。您在 main 中调用 List_append(l, word)
,这意味着您每次都将同一块内存传递给它,因此每个列表成员都指向同一块内存。
您需要在 List_append
:
node->data = strdup(str);
这会将字符串复制到新分配的缓冲区中。清理时一定要free
它。