我被要求使用C制作一些程序。在其中一个程序中,我需要创建一个链表,以便我可以用它做一些事情。但是,我不允许在任何这些程序中使用全局变量或循环(While,For等)。所以这是一个我写的新程序链接列表的小程序:
#include <stdio.h>
#include <stdlib.h>
struct node {
int number;
struct node *next;
};
void create (struct node *, struct node *);
void insert (struct node *, struct node *);
void display (struct node *);
int main(void) {
struct node *head;
struct node *current;
struct node *temp;
create ( head, current );
insert ( head, current );
temp = head;
display ( temp );
}
void create ( struct node *head, struct node *current ) {
int a;
printf("Insert: ");
scanf("%d", &a);
current = malloc(sizeof(struct node));
current -> number = a;
current -> next = NULL;
head = current;
}
void insert ( struct node *head, struct node *current ) {
int b;
printf("insert: ");
scanf("%d", &b);
if ( b == -1 ) return;
else {
current = malloc(sizeof(struct node));
current -> number = b;
current -> next = NULL;
}
insert ( head, current );
}
void display ( struct node *temp ) {
if ( temp != NULL ) {
printf("%d \t", temp -> number); //Error: EXC_BAD_ACCESS (code=EXC_I386_GPFLT)
temp = temp -> next;
display ( temp );
}
else return;
}
它或多或少是每本书所具有的标准代码,但我使用递归函数而不是循环。仔细观察,我的display()函数有问题。我收到此错误:函数内的EXC_BAD_ACCESS(代码= EXC_I386_GPFLT),在printf()行。所以我无法在屏幕上打印我的列表。我现在已经调试了4个小时了,我找不到什么错误,任何帮助都会受到赞赏!
答案 0 :(得分:0)
两个主要缺点:
您尚未在main()
中初始化列表指针,因此它们的值实际上是随机。
您正在将这些变量的副本传递给create()
和insert()
函数。这些函数无效,因为函数返回时会丢弃副本。
结果是当你尝试display()
列表时,你会发生崩溃,因为你传递的是未经初始化的指针。
<强>更新强>
以下是您的计划的修订版。插入,显示和释放是递归的。它不是传递要修改的insert()
函数的双指针,而是返回列表的新头部。请注意,创建空列表只需将其指针设置为NULL
即可。另外,请注意display()
更简单。
#include <stdio.h>
#include <stdlib.h>
struct node {
int number;
struct node *next;
};
struct node *insert (struct node *head) {
// return new list pointer
int b = 0;
struct node *current;
printf("Insert: ");
if (1 != scanf("%d", &b) || b == -1)
return head;
current = malloc(sizeof(struct node));
if (current == NULL) {
printf("Bad malloc!\n");
exit (1);
}
current->number = b;
current->next = head;
return insert(current);
}
void display (struct node *list) {
if (list) {
printf("%d \t", list->number);
display(list->next);
}
}
void free_list (struct node *list) {
if (list) {
free_list(list->next);
free(list);
}
}
int main(void) {
struct node *head = NULL;
head = insert (head);
printf("List is: ");
display(head);
printf("\n");
free_list (head);
return 0;
}
节目输出:
Insert: 1
Insert: 2
Insert: 3
Insert: 4
Insert: -1
List is: 4 3 2 1
处理了一些小问题:不检查scanf()
或malloc()
的返回值。这样做似乎很麻烦,但是随着时间的推移,你会重视检查你所做的一切的例程,因为C中的大多数语言检查都是在编译时发生的,而不是在运行时。在运行时,几乎没有保护。
答案 1 :(得分:0)
风向标发布的第三个问题:
你的插页非常奇怪。您要求输入,然后再次递归调用插入。要求输入,...... 但是你永远不会挂钩链表中的当前链接。
答案 2 :(得分:0)
您的代码包含两个问题。首先,insert和create函数应该使用struct node **参数而不是struct node * arguments。然后你需要以这种方式调用它们:
create ( &head, ¤t );
insert ( &head, ¤t );
因为否则对head和current的更改不会反映在head和current的值中,因为C具有按值语义调用(并且通过引用调用通过使用指针进行模拟)。所以,current = malloc(...);和头=当前;这些行实际上并没有改变主函数中的当前和头部指针,只是局部变量。
然后,您需要以这种方式访问它们:
*current = malloc(sizeof(struct node));
(*current) -> number = a;
(*current) -> next = NULL;
*head = *current;
这将是create function代码的一部分。
您还没有实际更新插入中当前节点的下一个链接。所以,而不是:
current = malloc(sizeof(struct node));
current -> number = b;
current -> next = NULL;
试试这个:
(*current)->next = malloc(sizeof(struct node));
*current = (*current)->next;
(*current) -> number = b;
(*current) -> next = NULL;
我还发现您的代码中存在一个问题,即您没有检查malloc的返回值。你永远不应该假设内存分配总是成功的。通过打印描述性错误消息并退出程序来处理malloc的NULL返回。