C 链表生成分割错误
下面我用C语言制作了一个简单的链表。代码目前产生了一个分段错误,我觉得这很奇怪,因为我从我们当前的书中复制了一个例子。我对代码所做的唯一一件事就是将代码放入方法“addToList”中。我知道分割错误来自方法addToList,但我不知道我在哪里出错C 链表生成分割错误,c,debugging,segmentation-fault,C,Debugging,Segmentation Fault,下面我用C语言制作了一个简单的链表。代码目前产生了一个分段错误,我觉得这很奇怪,因为我从我们当前的书中复制了一个例子。我对代码所做的唯一一件事就是将代码放入方法“addToList”中。我知道分割错误来自方法addToList,但我不知道我在哪里出错 #include <stdio.h> #include <stdlib.h> typedef struct node { int val; struct node *next; } Node; void addTo
#include <stdio.h>
#include <stdlib.h>
typedef struct node {
int val;
struct node *next;
} Node;
void addToList(Node *, int);
void printList(Node *);
void main() {
int x;
Node *head = malloc(sizeof(Node));
for (x = 1; x < 4); x++) {
printf("Enter an integer: ");
x = scanf("%d");
addToList(head, x);
}
printList(head);
}
void addToList(Node *head, int val) {
Node *current = head;
while (current->next != NULL) {
current = current->next;
}
current->next = malloc(sizeof(Node));
current->next->val = val;
current->next->next = NULL;
}
void printList(Node *head) {
Node *current = head;
while (current != NULL) {
printf("%d->", current->val);
current = current->next;
}
printf("\n");
}
#包括
#包括
类型定义结构节点{
int-val;
结构节点*下一步;
}节点;
void addToList(节点*,int);
作废打印列表(节点*);
void main(){
int x;
Node*head=malloc(sizeof(Node));
对于(x=1;x<4);x++){
printf(“输入一个整数:”);
x=扫描频率(“%d”);
地址列表(头,x);
}
印刷品清单(标题);
}
void addToList(节点*头,int val){
节点*电流=头部;
while(当前->下一步!=NULL){
当前=当前->下一步;
}
当前->下一步=malloc(sizeof(Node));
当前->下一步->val=val;
当前->下一步->下一步=空;
}
无效打印列表(节点*头){
节点*电流=头部;
while(当前!=NULL){
printf(“%d->”,当前->值);
当前=当前->下一步;
}
printf(“\n”);
}
如果您能告诉我哪里出了问题或哪里出了错,我们将不胜感激。请仔细查看您的代码:
int main(void) {
int x;
Node *head = malloc(sizeof(Node));
for (x = 1; x < 4); x++) {
...
addToList(head, x);
}
...
}
将循环未定义的次数。第一个当前->下一个是最
可能不是NULL
,因此执行current=current->next
。此时,current
没有指向任何地方,因此未定义的行为在您的情况下会导致segfault
必须按如下方式初始化内存:
Node *head = malloc(sizeof *head);
if(head == NULL)
// error handling
head->next = NULL;
但是您也可以使用calloc
,这也会将内存设置为0,因此您不必初始化值(在本例中):
您应该始终检查malloc
/calloc
/realloc
的返回值
还要注意,main
函数的签名可以是以下之一:
int main(无效)代码>
intmain(intargc,char**argv)代码>
intmain(intargc,char*argv[])代码>
编辑
我现在注意到的另一个错误是:
x = scanf("%d");
这不是工作原理。您必须传递一个指针,scanf
保存
通过传递的指针扫描值scanf
返回匹配的
成功的价值观,在这种情况下,成功是1:
int num;
int ret = scanf("%d", &num);
if(ret != 1)
{
fprintf(stderr, "Could not read value from the user\n");
continue; // to contiune looping
// you could also do a break; and stop the looping, or
// exit(1), etc.
}
// error with scanf
对于循环迭代和用户输入,也不要使用相同的变量x
,
否则,您将搞乱循环
编辑
用户user3629249在评论中写道
好的信息,但是结果将是链表中的第一个条目将包含垃圾。
最好通过以下方式声明头部:节点*head=NULL
;函数addToList()
检查是否为NULL并相应地继续
没错,head
元素不会以这种方式保存任何数字
选项1:双指针
此处addToList
接收一个双指针。head
的初始化发生
当*head
指向NULL
时。函数为它分配内存,初始化
内存,保存值并返回。在addToList的并发调用中
*head
不会为NULL
,因此addToList
会查找列表的末尾
我对您执行malloc
和realloc
的方式做了一些小的更改。我还补充说
freeList
的一种实现,用于释放内存:
void addToList(Node **head, int val) {
if(head == NULL)
{
fprintf(stderr, "head cannot be NULL\n");
return;
}
if(*head == NULL)
{
*head = calloc(1, sizeof **head);
head[0]->val = val;
head[0]->next = NULL;
return;
}
Node *current = *head;
while (current->next != NULL) {
current = current->next;
}
current->next = malloc(sizeof *current->next);
if(current->next == NULL)
return;
current->next->val = val;
current->next->next = NULL;
}
int main(void)
{
int x;
Node *head = NULL;
for (x = 1; x < 4; x++)
{
int val;
printf("Enter an integer: ");
if(scanf("%d", &val) != 1)
{
fprintf(stderr, "Could not read from user. Skipping entry\n");
continue;
}
addToList(&head, val);
}
printList(head);
freeList(head);
return 0;
}
void freeList(Node *head)
{
if(head == NULL)
return;
Node *current = head;
Node *next;
while(next = current->next)
{
free(current);
current = next;
}
free(current); // the last one
free(head);
}
请仔细查看您的代码:
int main(void) {
int x;
Node *head = malloc(sizeof(Node));
for (x = 1; x < 4); x++) {
...
addToList(head, x);
}
...
}
将循环未定义的次数。第一个当前->下一个是最
可能不是NULL
,因此执行current=current->next
。此时,current
没有指向任何地方,因此未定义的行为在您的情况下会导致segfault
必须按如下方式初始化内存:
Node *head = malloc(sizeof *head);
if(head == NULL)
// error handling
head->next = NULL;
但是您也可以使用calloc
,这也会将内存设置为0,因此您不必初始化值(在本例中):
您应该始终检查malloc
/calloc
/realloc
的返回值
还要注意,main
函数的签名可以是以下之一:
int main(无效)代码>
intmain(intargc,char**argv)代码>
intmain(intargc,char*argv[])代码>
编辑
我现在注意到的另一个错误是:
x = scanf("%d");
这不是工作原理。您必须传递一个指针,scanf
保存
通过传递的指针扫描值scanf
返回匹配的
成功的价值观,在这种情况下,成功是1:
int num;
int ret = scanf("%d", &num);
if(ret != 1)
{
fprintf(stderr, "Could not read value from the user\n");
continue; // to contiune looping
// you could also do a break; and stop the looping, or
// exit(1), etc.
}
// error with scanf
对于循环迭代和用户输入,也不要使用相同的变量x
,
否则,您将搞乱循环
编辑
用户user3629249在评论中写道
好的信息,但是结果将是链表中的第一个条目将包含垃圾。
最好通过以下方式声明头部:节点*head=NULL
;函数addToList()
检查是否为NULL并相应地继续
没错,head
元素不会以这种方式保存任何数字
选项1:双指针
此处addToList
接收一个双指针。head
的初始化发生
当*head
指向NULL
时。函数为它分配内存,初始化
内存,保存值并返回。在addToList的并发调用中
*head
不会为NULL
,因此addToList
会查找列表的末尾
我对您执行malloc
和realloc
的方式做了一些小的更改。我还补充说