首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在C中创建链表,获取分段错误

在C中创建链表,获取分段错误
EN

Stack Overflow用户
提问于 2019-11-08 03:29:25
回答 2查看 64关注 0票数 0

我需要创建一个节点链表,以便main函数能够工作;我不能更改main函数中的任何内容。我是C语言的新手,所以我可能犯了一两个简单的错误,当我尝试运行我的代码时,我得到了一个分段错误。我是不是漏掉了什么明显的东西?

分段错误发生在标记的行上

代码语言:javascript
运行
复制
#include <stdio.h>
#include <stdlib.h>

typedef struct Node{
    char *value;
    struct Node *next;
}Node;
typedef struct Node** List;

Node *new_node(char *input);
void delete_node(Node *input);
void push(List list, char *value);
List new_list();

Node *new_node(char *input) {
  Node *new;
  new = malloc(sizeof(Node));
  new->value = input;
  return new;
}

void delete_node(Node *input) {
  free(input);
}

void push(List head, char *input) {
  if (*head == NULL) {  
    *head = new_node(input);
  }
  else {
    Node *new = new_node(input);
    while ((*head)->next != NULL) {
      *head = (*head)->next;
    }
    (*head)->next = new;    
  } 
}

List new_list() {
  List list = malloc(sizeof(List));
  *list = NULL;
  return list;
}

int main( void ) {
  List list = new_list();
  push(list, "First!\n");
  push(list, "Second!\n");
  push(list, "Third!\n");
  push(list, "Fourth!");

  printf("%s", (*list)->value);
  printf("%s", (*list)->next->value);
  printf("%s", (*list)->next->next->value);       //Segmentation fault
  printf("%s", (*list)->next->next->next->value);

  return 0;
}

当我用gdb运行它时,我得到了这样的消息:

代码语言:javascript
运行
复制
Third!                                                                                                               

Program received signal SIGSEGV, Segmentation fault.                                                                 
0x0000000000400752 in main () at main.c:54                                                                           
54        printf("%s", (*list)->next->next->value);
EN

回答 2

Stack Overflow用户

发布于 2019-11-08 03:41:09

创建新节点时,从不设置新创建节点的next成员。这会使其处于未初始化状态,导致在取消引用指针时出现未定义的行为。

修复方法很简单。添加

代码语言:javascript
运行
复制
new->next = NULL;

在分配了value之后,将其转换为您的new_node函数。

票数 3
EN

Stack Overflow用户

发布于 2019-11-08 05:34:39

链表可以有单指针或双指针。单链表有指向下一个元素的指针,双向链表有指向下一个元素和前一个元素的指针。您选择了单个链表。

要添加到列表末尾的函数必须在每次追加到列表操作时遍历整个列表。这意味着添加到列表中是一个O(n)复杂度的操作。链表的主要优点是O(1)添加和删除操作,当实现时提供该功能。

声明列表为指向头部(列表的)和尾部(列表的)的指针,

代码语言:javascript
运行
复制
typedef struct {
    Node* head;
    Node* tail;
} List;

不是将列表声明为指向节点的指针的指针,

代码语言:javascript
运行
复制
typedef struct Node** List;

现在,添加到列表和从列表中删除的复杂性是O(1) (常量)时间操作……

代码语言:javascript
运行
复制
//enqueue to tail of list (not push)
void enqueue(List* list, char *input) {
  if( !list ) return; //no list
  Node* new = new_node(input); //new node
  if( NULL == list->head ) { //list empty
    list->head = new; //add at tail, tail equals head
  }
  else {
    list->tail->next = new; //list not empty, add at tail
  }
  list->tail = new;
}

//dequeue from head of list
Node* dequeue(List* list) {
    if( !list ) return NULL; //no list
    if( NULL == list->head ) return NULL; //list empty
    Node* node = list->head; //node at head of list
    list->head = list->head->next; //remove from list
    if( NULL == list->head ) list->tail = NULL; //empty now
    //oh, should also: node->next = NULL;
    return node;
}

而且,正如其他人所说,你应该初始化你的“构造函数”中的所有指针,

代码语言:javascript
运行
复制
Node *new_node(char *input) {
  Node *new;
  if( ! (new = malloc(sizeof(Node))) ) return NULL;
  //new = calloc(sizeof(Node)); //calloc fills allocated memory with zero bytes
  //initialize all values in Node structure
  new->value = input;
  new->next = NULL; //either use calloc or init the individual elements
  return new;
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/58755690

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档