我在C.中实现了一个链表
问题是,每当我试图使用函数print_list(struct linked_list *list)
打印节点数据时,我都会遇到分段错误。
我不确定是什么原因导致的,因为当我尝试print(struct linked_list *list)
时,它运行良好。
而且,当我尝试动态分配内存时,它也能很好地工作。但我很好奇这样的代码出了什么问题?为什么使用print
不会导致同样的错误?
#include <stdio.h>
#include <stdlib.h>
struct node{
char data;
struct node* next;
};
struct linked_list{
struct node *head;
};
void concat(struct linked_list* list1, struct linked_list* list2)
{
struct node* tmp = list1->head;
while(tmp->next != NULL)
tmp = tmp->next;
tmp->next = list2->head;
}
void print_list(struct linked_list *list)
{
struct node* tmp = list->head;
while(tmp != NULL){
printf("%c - ", tmp->data);
tmp = tmp->next;}
printf("n");
}
void print(struct linked_list *list)
{
struct node* tmp = list->head;
printf("%cn", tmp->data);
tmp = tmp->next;
printf("%cn", tmp->data);
tmp = tmp->next;
printf("%cn", tmp->data);
}
int main()
{
struct linked_list list1,list2;
struct node n1,n2,n3,n4,n5;
n1.data = 'A';
n2.data = 'B';
n3.data = 'C';
n4.data = 'D';
n5.data = 'E';
n1.next = &n2;
n2.next = &n3;
n4.next = &n5;
list1.head = &n1;
list2.head = &n4;
printf("List 1 containes :n");
print_list(&list1);
concat(&list1,&list2);
printf("List 1 after concat: n" );
print_list(&list1);
return 0;
}
此处:
struct node n1,n2,n3,n4,n5;
您创建了五个节点,但没有对它们进行初始化。C不会将局部变量初始化为null或零,因此节点的字段具有独立("垃圾"(值。稍后,将初始化一些字段,但不初始化列表中最后一个节点的next
字段。
有几种解决方案,例如:
(1( 显式初始化最后一个节点的next
字段:
n1.next = &n2;
n2.next = &n3;
n3.next = NULL;
n4.next = &n5;
n5.next = NULL;
(2( 用数据初始化节点,然后设置链接:
struct node n1 = {'A'};
struct node n2 = {'B'};
struct node n3 = {'C'};
struct node n4 = {'D'};
struct node n5 = {'E'};
n1.next = &n2;
n2.next = &n3;
n4.next = &n5;
初始化结构后,所有字段都将被初始化,即使没有显式给定值(如next
(。根据类型的不同,这些字段是用零或null隐式初始化的。现在您已经有了有效的(但未连接的(节点,您可以设置链接。
(3( 通过初始化定义一切:
struct node n5 = {'E', NULL};
struct node n4 = {'D', &n5};
struct linked_list list2 = {&n4};
struct node n3 = {'C', NULL};
struct node n2 = {'B', &n3};
struct node n1 = {'A', &n2};
struct linked_list list1 = {&n1};
现在您已经准备好了您的列表,但您必须向后定义它,这样当您引用它时就会知道next
节点
还有其他可能性可以在不在堆上分配内存的情况下设置链表,例如节点数组,但我认为你已经明白了。
首先尝试了解segmentation fault
是什么。
根据维基百科:
在计算中,分段故障(通常缩写为segfault(或访问违规是由具有内存保护的硬件引发的故障或故障条件,通知操作系统软件试图访问内存的受限区域(内存访问违规(。
所以发生这种情况是因为您的程序正在访问一个不应该访问的受限位置。但为什么呢?因为在while(tmp->next != NULL)
中,程序在遍历所有元素时不一定要找到NULL
。因此,在这种情况下,循环不会中断,它允许循环进一步继续,最终程序尝试访问受限制的位置。
因此,要解决此问题,请在node
结构的定义中初始化node* Next = NULL
。类似:
struct node{
char data;
struct node* next = NULL;
};
现在,next
的默认值明确设置为NULL
。因此,除非将其更改为指向另一个节点,否则它仍将保持为NULL
。这个问题应该得到解决。