C 中的链表
我在运行此链表实现(包含单词作为数据)时遇到一些问题。问题是当我尝试打印链接列表中的单词(我插入的)时,我什么也没得到。我做错了什么,为此伤透了脑筋?我希望这不是一件愚蠢的事情。无论如何,这是代码 -
typedef struct node
{
void *data;
struct node *next;
} NODE;
NODE *new_node(void *data)
{
NODE *new = malloc(sizeof(NODE));
if(new)
{
new->data = data;
new->next = NULL;
return new;
}
else
{
return NULL;
}
}
void print_list(NODE *head, void (print_fn) (void*))
{
if(head && head->next)
{
while(head->next)
{
if(print_fn)
print_fn(head->data);
else
printf("Word: %s\n", (char *)head->data);
head = head->next;
}
}
return;
}
void append(NODE **head, NODE *node)
{
NODE *tmp = *head;
if(tmp && node)
{
while(tmp->next)
tmp = tmp->next;
(*head)->next = node; /*add as last node*/
}
return;
}
NODE *create_list()
{
FILE *dict_file = fopen("trial.txt", "r");
if(dict_file)
{
NODE *head = new_node(NULL);
if(!head) return NULL;
char word[20];
int first = TRUE;
memset(word, '\0', 20);
while(fgets(word, sizeof(word), dict_file) != NULL )
{
if(first)
{
head->data = (void*)word;
first = FALSE;
}
else
{
append(&head, new_node((void*)word));
}
}
fclose(dict_file);
return head;
}
else
{
printf("ERROR: File not found");
return NULL;
}
}
int main(int argc, char *argv[])
{
NODE *head = create_list();
if(!head)
{
printf("ERROR: Either malloc() failed or data not found\n");
return FALSE;
}
else
{
print_list(head, NULL);
return TRUE;
}
}
I am having some trouble running this linked list implementation (containing words as data). Problem is when I try to print the words (that I inserted) in the Linked List,I get nothing. What am I doing wrong, breaking my head over this? I hope it's not something silly. Anyway here's the code -
typedef struct node
{
void *data;
struct node *next;
} NODE;
NODE *new_node(void *data)
{
NODE *new = malloc(sizeof(NODE));
if(new)
{
new->data = data;
new->next = NULL;
return new;
}
else
{
return NULL;
}
}
void print_list(NODE *head, void (print_fn) (void*))
{
if(head && head->next)
{
while(head->next)
{
if(print_fn)
print_fn(head->data);
else
printf("Word: %s\n", (char *)head->data);
head = head->next;
}
}
return;
}
void append(NODE **head, NODE *node)
{
NODE *tmp = *head;
if(tmp && node)
{
while(tmp->next)
tmp = tmp->next;
(*head)->next = node; /*add as last node*/
}
return;
}
NODE *create_list()
{
FILE *dict_file = fopen("trial.txt", "r");
if(dict_file)
{
NODE *head = new_node(NULL);
if(!head) return NULL;
char word[20];
int first = TRUE;
memset(word, '\0', 20);
while(fgets(word, sizeof(word), dict_file) != NULL )
{
if(first)
{
head->data = (void*)word;
first = FALSE;
}
else
{
append(&head, new_node((void*)word));
}
}
fclose(dict_file);
return head;
}
else
{
printf("ERROR: File not found");
return NULL;
}
}
int main(int argc, char *argv[])
{
NODE *head = create_list();
if(!head)
{
printf("ERROR: Either malloc() failed or data not found\n");
return FALSE;
}
else
{
print_list(head, NULL);
return TRUE;
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这已经成为一个相当长的答案。不要认为这是针对你个人的,但你已经犯了很多新手错误。我在大学里遇到过很多人,我帮助他们学习了 C 语言和一般的编程,所以我已经习惯了注意到这些事情。
我可以找到的重要问题
您将指向堆栈变量的指针分配给
words
这完全是糟糕的,因为一旦执行结束创建它的函数,该值就会被覆盖。 解决方案:将该变量的内容复制到堆变量中。
您的
append
函数有错误它将附加元素添加到第二个位置而不是最后一个位置。请注意,您也不需要最后返回。要求双指针作为
append
方法的输入也是没有意义的。另外,在将head
分配给tmp
后,检查 tmp 是否为NULL
也是徒劳的,因为它不会是NULL
如果head
不是NULL
。另外,我建议也检查新节点是否为 NULL。如果它是NULL
,这可以让您免于迭代整个集合。create_list
函数不是最优的首先,区分第一种情况和其他情况是徒劳的。引入另一个指针(在我的代码中称为
current
)将消除检查它是否是第一个的需要。接下来,您总是在head
上调用append
函数,因此您始终需要迭代整个集合。这也可以通过引入current
变量来优化。 (在开始时,应分配head
的值。)print_list
函数是错误的如果只有一个节点,它不会打印任何内容。它还冗余地检查指针是否为空。 (循环的开头也会检查它。)此
void
函数末尾的 return 语句也是不必要的。不使用内存时应释放内存
@Baltasarq 在他的答案中写了一个很好的
clear
函数,你应该使用它。 :)不是严重错误,但您应该注意它们
您不应该使用
void*
而不是char*
如果您知道
NODE
结构的data
成员将存储字符,为什么要使用void*
?这是不好的做法! (当然,除非你有充分的理由。)使用
new
一词作为变量名会使您的代码不符合 C++。因此,我建议不要这样做。请采用更好的编码风格 - 这将使您的代码更容易阅读
不一致:如果在
print_list
您没有分配新变量来遍历集合(就像您在append
中使用tmp
变量一样),那么它会产生误导将参数命名为head
。 (我在代码中将其重命名为node
。)这是固定代码
(请注意,可能存在小的语法错误,因为我在浏览器中输入了代码而没有实际测试它。)< /em>
This has become quite a long answer. Don't take this personally, but you have made quite a few rookie mistakes. I have met with many people at university whom I helped to learn the C language and programming in general, so I've got used to notice these kinds of things.
The important issues I could find
You assign a pointer to a stack variable to
words
This is completely bad, because that value will be overwritten once the execution gets out of the function that creates it. Solution: copy the content of that variable into a heap variable.
Your
append
function is faultyIt adds the appended element to the second place instead of the last place. Note that you don't need the return at the end either. There is also no point in requiring a double-pointer as input to the
append
method. Also, after assigninghead
totmp
, it is futile to check tmp againstNULL
as well, since it won't beNULL
ifhead
isn'tNULL
. Also, I recommend checking the new node againstNULL
as well. If it isNULL
, this saves you from iterating over the entire collection.The
create_list
function is sub-optimalFist, the distinction between the first and the other cases are futile. Introducing another pointer (called
current
in my code) will eliminate the need to check whether it is the first or not. Next, you always call theappend
function on thehead
, thus you always need to iterate over the entire collection. This can be also optimized by introducing thecurrent
variable. (Which, at start, should be assigned the value ofhead
.)The
print_list
function is errornousIt doesn't print anything if there is only one node. It also redundantly checks the pointers for null. (The beginning of the loop checks it, too.) The return statement at the end of this
void
function is also unnecessary.You should free up memory when you don't use it
@Baltasarq wrote a nice
clear
function in his answer, you should use it. :)Not serious errors, but you should be aware of them
You should not use
void*
instead ofchar*
If you know that the
data
member of theNODE
structure is going to store characters, why do you usevoid*
? It is bad practice! (Unless you have a good reason, of course.)Using the
new
word as a variable name makes your code not compliant with C++. Thus, I recommend against it.Adopt a better coding style, please - it will make your code so much easier to read
Inconsistency: if in
print_list
you don't allocate a new variable to go through the collection (like you do with thetmp
variable inappend
) then it is misguiding to name the parameter ashead
. (I renamed it tonode
in my code.)Here is the fixed code
(Note that there may be small syntax errors because I typed the code into the browser without actually testing it.)
请小心,因为当内存不足时,malloc() 及其派生函数可以使用 NULL 指针进行应答。事实上,请考虑到您还需要一个 clear() 方法来释放所有数据以及节点本身。
你的 main() 函数应该向操作系统返回 EXIT_SUCCESS 或 EXIT_FAILURE 的退出代码,而不是 TRUE 或 FALSE。
Be careful, since malloc() and derivatives can answer with a NULL pointer when there is not enough memory. In fact, take into account that you'll also need a clear() method that free's all the data, as well as the nodes themselves.
Your main() function should return an exit code to the operating system of EXIT_SUCCESS or EXIT_FAILURE, instead of TRUE or FALSE.