0

我正在努力寻找以下链表实现中的segmentation fault错误。当我在开头追加或添加时出现错误

请帮助我在哪里做错了

#包括

#include<stdlib.h>

struct node
{
    int data;
    struct node*link;
};

void append(struct node *p,int num)
{
    struct node *temp,*q;
    q=p;
    temp=(struct node*)malloc(sizeof(struct node));
    temp->data=num;
    temp->link=NULL;
    if(p==NULL)
        p=temp;
    else
    {
        while(q->link!=NULL)
            q=q->link;

        q->link=temp;
    }
}



int main()
{
    int i,choice,num,pos;
    struct node p;
    printf("Enter your choice\n");
    printf("1-Append\n2-Add At Beg\n3-Add after\n4-Delete\n5-Exit");
    scanf("%d",&choice);
    while(choice!=5)
    {
        switch(choice)
        {
            case 1:printf("Enter the number\n");
                    scanf("%d",&num);
                    append(&p,num);
                    break;


        }
        printf("1-Append\n2-Add At Beg\n3-Add after\n4-Delete\n5-Exit");
        scanf("%d",&choice);
    }
}
4

3 回答 3

3

struct node*p=NULL;

像这样调用附加 -

append(&p,num);

我们这样做是因为我们想保留指向链接列表第一个节点的指针。通过执行 append(p,num),指针的副本进入我们的方法,并且当该方法返回时,对 p 的更改将丢失。

并将附加例程编写为-

void append(struct node **p,int num)
{
   struct node *temp,*q;
   q=*p;
   temp=(struct node*)malloc(sizeof(struct node));
   temp->data=num;
   temp->link=NULL;
   if(*p==NULL)
   {
        *p=temp;
        printf("here");
    }
  else
   {
       while(q->link!=NULL)
        q=q->link;

       q->link=temp;
   }
}

对添加例程做类似的操作。

于 2013-09-21T13:03:43.290 回答
1

最终编辑:用户 vaibhav 抓住了它:struct node *p未初始化,即使列表为空也可能不是 NULL。

只是为了一般的享受,clang静态分析器似乎得到了它:

clang -Wall --analyze lists.c
lists.c:13:5: warning: Assigned value is garbage or undefined
  q = *p;
    ^ ~~
1 warning generated.

无效追加(结构节点* p,int num);

虽然算法本身看起来不错,但处理 - 参数的方式存在问题p。您按值传递指针p,这意味着更改*p将更改分配的内存,但对p自身的更改不会传播到调用上下文。

处理这种情况的正确方法是:

无效追加(结构节点**p,int num){*p = temp;}

#include<stdlib.h>

struct node
{
  int data;
  struct node*link;
};

void append(struct node **p,int num)
{
  struct node *temp,*q;
  q = *p;
  temp = (struct node*)malloc(sizeof(struct node));
  temp->data = num;
  temp->link = NULL;
  if(*p == NULL)
    *p = temp;
  else
    {
      while(q->link != NULL)
        q = q->link;

      q->link = temp;
    }
}

int main()
{
  struct node *p;

  append(&p, 1);
  append(&p, 2);
  append(&p, 3);
}
于 2013-09-21T12:44:23.273 回答
0

在这一行:

struct node*p;

它应该是

struct node p;

您正在创建指向节点的指针。但是以后不要初始化它,所以没有创建节点并且它指向随机位置。然后你将它作为参数传递给你的函数。
当您在函数中取消引用此指针时,您p->会遇到分段错误。

在您的main函数中,您应该声明“节点”,而不是pointer to node,然后将节点的地址传递给带有&运算符的函数。

所以你的函数声明void addatbeg(struct node *p,int num);很好,但它应该被调用(在你声明节点 p 之后):

addatbeg(&p,some_number);

此外,每个使用 p 的函数都应更改为将 p 视为结构,而不是指向结构的指针。

您在这里所做的事情混淆了链表上的一些信息。
通常将headsingly linked list声明为指向节点的指针。当我自己实现 sll 时,我也这样做了。然后通过引用在链表上操作的函数来传递该指针,它工作正常。
另一方面,您得到了,并且将 head视为另一个节点doubly linked lists更方便,但没有价值。 你试图将这些想法混合在一起,而不了解它们背​​后的想法。 我给了你一堆关于如何使它工作的提示,但修复它意味着我必须重写你的整个代码。doubly linked list



这不是重点,因为您应该自己学习。

于 2013-09-21T12:40:12.913 回答