【问题标题】:Segmentation Fault on Linked List Using C使用 C 的链表上的分段错误
【发布时间】:2016-08-30 13:34:17
【问题描述】:

我是 C 的新手,并尝试学习如何在链表上实现 C。我真的很困惑为什么我不能在主函数中访问 myList ?因为当我尝试myList->data 时,这是分段错误。我认为我的 addtohead 函数有一些错误? 以下是我的代码:

#include <stdio.h>
#include <stdlib.h>

typedef struct NODE{
    int data;
    struct NODE *next;
}node;

node * myList;

node * addToHead(node*, int);
void printList();

int main(){
    myList = NULL;
    int input;
    while (scanf("%i",&input) == 1){
           addToHead(myList, input);
           printf("%d \n", myList->data);
       }

    printf("My List:\n");
    printList(myList);
    return 0;
}

node* addToHead(node* head, int newData){
    node *temp = (node *)malloc(sizeof(node));
    temp -> data = newData;
    temp -> next = NULL;
    if(head != NULL){
        temp -> next = head;
        }
    head = temp;
    return head;
}

void printList(node* head){
    node *temp = head;
    while(temp != NULL){
        printf("%d ", temp->data);
        temp = temp -> next;
    }
    printf("\n");
}

【问题讨论】:

  • 你没有对函数的返回值做任何事情。参数head 是主参数的副本。试试myList = addToHead(myList, input);
  • head into addToHead 具有本地范围。

标签: c linked-list singly-linked-list


【解决方案1】:

您的 addToHead 函数应该将 mallocated 内存返回给调用者。

所以你应该首先将返回值分配给 mylist:

int main(){
    node *myList = NULL;
    int input;
    while (scanf("%i",&input) == 1){
           myList = addToHead(myList, input);
           printf("%d \n", myList->data);
       }

    printf("My List:\n");
    printList(myList);
    return 0;
}

到你写的addToHead函数中

head = temp;

head 具有本地作用域,分配的值不会反映到指针myList

为此,您必须使用指向指针的指针。

int main(){
    node *myList = NULL;
    int input;
    while (scanf("%i",&input) == 1)
    {
       if (addToHead(&myList, input) == true)
       {
           printf("%d \n", myList->data);
       }
       else
       {
           fprintf(stderr, "Error addToHead\n");
       }
    }

    return 0;
}

bool addToHead(node** head, int newData){
    node *temp = malloc(sizeof(node));
    if (temp != NULL)
    {
       temp -> data = newData;
       temp -> next = NULL;
       if(head != NULL)
       {
          temp -> next = *head;
       }

       *head = temp;

       return true;
   }

   return false;
}

最后永远记得检查malloc返回值:它可能会失败。

【讨论】:

    【解决方案2】:

    您从addToHead 返回新的头节点,但您不使用它做任何事情。您需要将此值分配给 myList 以更新它:

    myList = addToHead(myList, input);
    

    另外,您在以下行中拼错了一个变量:

    printf("%d \n", myListd->data);
    

    应该是:

    printf("%d \n", myList->data);
    

    【讨论】:

      【解决方案3】:

      在这个函数定义中

      node* addToHead(node* head, int newData){
          node *temp = (node *)malloc(sizeof(node));
          temp -> data = newData;
          temp -> next = NULL;
          if(head != NULL){
              temp -> next = head;
              }
          head = temp;
          return head;
      }
      

      参数node* head是函数的局部变量。参数的任何更改都不会影响原始参数。退出函数后,函数参数将被销毁。

      您可以通过以下方式考虑函数定义及其调用

      addToHead(myList, input);
      //...
      node* addToHead(/*node* head, int newData*/){
          node *head = myList;
          int newData = input;
      
          node *temp = (node *)malloc(sizeof(node));
          temp -> data = newData;
          temp -> next = NULL;
          if(head != NULL){
              temp -> next = head;
              }
          head = temp;
          return head;
      }
      

      所以函数调用后原来的变量myList不会改变。您必须将返回的值显式分配给变量

      myList = addToHead(myList, input);
      

      该功能也有一个缺点。新节点未分配时不报错。

      编写函数的更好方法如下所示

      int /* _Bool */ addToHead( node **head, int newData )
      {
          node *temp = ( node * )malloc( sizeof( node ) );
          int /* _Bool */ success = temp != NULL;
      
          if ( success )
          {
              temp -> data = newData;
              temp -> next = *head;
              *head = temp;
          }
      
          return success;
      }
      

      在这种情况下,可以通过以下方式循环调用函数

      while ( scanf( "%i", &input ) == 1 && addToHead( &myList, input ) )
      {
          //...
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-10-21
        • 2012-06-12
        • 2020-09-10
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多