C - 分段故障错误中的链表实现

时间:2013-09-21 12:33:48

标签: c

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

请帮助我在哪里做错了

的#include

#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);
    }
}

3 个答案:

答案 0 :(得分:3)

struct node*p=NULL;

呼叫追加这样 -

append(&p,num);

我们这样做是因为我们希望将指针保存到我们链接列表的第一个节点。通过执行追加(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;
   }
}

为添加例程做同样的事。

答案 1 :(得分: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.

  

void append(struct node * p,int num);

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

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

  

void append(struct node ** 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);
}

答案 2 :(得分:0)

在这一行:

struct node*p;

应该是

struct node p;

你正在创建指向节点的指针。但是不要在以后初始化它,因此不会创建任何节点并且它指向随机位置。然后你将它作为参数传递给你的函数 如果您在函数p->中取消引用此指针,则会出现分段错误。

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

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

addatbeg(&p,some_number);

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

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

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