简体   繁体   English

链表显示分段错误错误

[英]Linked list shows segmentation fault error

I'm pretty new to C and pointers.我对 C 和指针很陌生。

Following codes are for implementing a linked list in which each node contains a data of record.以下代码用于实现一个链表,其中每个节点都包含一个记录数据。

However, when I compile and run this program, it shows an error "segmentation fault", and I guess the following part from my code makes an error.但是,当我编译并运行该程序时,它显示错误“分段错误”,我猜我的代码中的以下部分会出错。
head->next = NULL in functions in list.c head->next = NULL在列表中的函数中。c
I doubt the segmentation fault error happens due to dereferencing a null pointer but have no idea what's wrong with my code.我怀疑由于取消引用 null 指针而发生分段错误错误,但不知道我的代码有什么问题。

list.h列表.h

#ifndef LIST_H
#define LIST_H
#include <stddef.h>
#include "record.h"

typedef struct node node;

struct node {         
  record  data;           
  node   *next;             
};

typedef node *record_list;  /* a record list is represented by its "head"
                               pointer */

void list_init(record_list *plist);

int list_insert(record_list *plist, const record *prec);

void list_clear(record_list *plist);

void list_print(const record_list *plist);
#endif

io.h io.h

#ifndef IO_H
#define IO_H
#include "record.h"

void print_record(const record *p);

int read_record(record *p);

/* reads a string from stdin */
int get_word(const char prompt[], char word[]);

/* reads an int from stdin */
int get_int(const char prompt[], int *p);
#endif

record.h记录.h

#ifndef RECORD_H
#define RECORD_H

#define IDSIZE    10
#define NAMESIZE  20

typedef struct {          
  char   last[NAMESIZE];   
  char   first[NAMESIZE];  
} name;

typedef struct {   
  char  id[IDSIZE]; 
  name  name;      
  int   score;  
} record;
#endif

list.c列表.c

#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include "record.h"
#include "list.h"
#include "io.h"

/* initializes a record list (specified via plist) to an empty list */
void list_init(record_list *plist) {
  node *head;
  head = *plist;
  head = NULL;
  head->next = NULL;
  printf("%s", "segmentation???\n");
}

/*
 * inserts a record (specified via prec) into a record list
 */
int list_insert(record_list *plist, const record *prec) {
  node *current, *temp;
  printf("%s", "list insert\n");
  current = *plist;
  while (current->next != NULL) {
    current = current->next;
  }
  temp = (node *)malloc(sizeof(node));
  if (temp == NULL) {
    fprintf(stderr, "memory allocate failed");
    return 0;
  }
  current->next = temp;
  current->next->data = *prec;
  current->next->next = NULL;

  printf("%s", "list insert done\n");
  return 1;
}

/*
 * deallocates all dynamic memory associated with a record list (specified
 * via plist) & resets the record list to an empty list
 */
void list_clear(record_list *plist) {
  printf("%s", "list clear\n");
  free((*plist)->next);
  plist = NULL;
  (*plist)->next = NULL;
}

/* prints all records in a record list (specified via plist) */
void list_print(const record_list *plist) {
  node *current;
  current = *plist;
  printf("%s", "list print\n");
  while (current->next != NULL) {
    print_record(&(current->data));
    current = current->next;
  }
}

io.c io.c

#include <stdio.h>
#include <string.h>
#include "record.h"
#include "io.h"
#define LINESIZE 1024

/*
 * prints a record (specified via p);
 */
void print_record(const record *p) {
  printf("%d %s %s %s\n", p->score, p->name.last, p->name.first, p->id);
}

/*
 * reads a record from stadard input & stores it via p;
 */
int read_record(record *p) {
  return (
        get_word("Enter id: ", p->id)
    &&  get_word("Enter last name: ", p->name.last)
    &&  get_word("Enter first name: ", p->name.first)
    &&  get_int("Enter score: ", &(p->score))
  );
}

/* reads a string from stdin */
int get_word(const char prompt[], char word[]){
  char line[LINESIZE];
  char temp[LINESIZE];
  while (1) {
    printf("%s", prompt);
    if(!fgets(line, LINESIZE, stdin)){
      clearerr(stdin);
      return 0;
    }
    if (sscanf(line, "%s", temp) == 1){
      strcpy(word, temp);
      return 1;
    }
  }
}

/* reads an int from stdin */
int get_int(const char prompt[], int *p) {
  char line[LINESIZE];
  while (1) {
    printf("%s", prompt);
    if (!fgets(line, LINESIZE, stdin)) {
      clearerr(stdin);
      return 0;
    }
    if (sscanf(line, "%d", p) == 1) {
      return 1;
    } else {
      printf("%s", "Error: The input is not given in integer.\n");
    }
  }
}

main.c main.c

#include <stdio.h>
#include "record.h"
#include "list.h"
#include "io.h"


int main(void) {
  record_list  list;
  record       r;

  printf("address of list: %ld\n", &list);
  printf("address of list: %ld\n", &(list->next));
  list_init(&list);

  while (read_record(&r)) {
    printf("%s\n", "read success");
    if (!list_insert(&list, &r))
      break;
  }

  list_print(&list);
  return 0;
}

If your goal is to create an empty list and plist is the pointer to the head of the list you have to set the variable pointed by plist to NULL with *plist = NULL;如果您的目标是创建一个空列表并且plist是指向列表头的指针,则您必须将plist指向的变量设置为 NULL ,其中*plist = NULL; , you can get rid of the code is causing the segmentation fault ,就可以摆脱导致分段错误的代码

Ok I think I find the next error:好的,我想我发现了下一个错误:

current = *plist;
while (current->next != NULL) {
    current = current->next;
}

Will cause errors because the first time you call list_insert you have *plist equals to NULL because the list is empty and so current->next != NULL will cause the error (current is also equals to NULL)会导致错误,因为第一次调用 list_insert 你有 *plist 等于 NULL 因为列表是空的,所以 current->next != NULL 将导致错误(current 也等于 NULL)

I suggest the following:我建议如下:

printf("%s", "list insert\n");

if (*plist == NULL) {
    temp = (node * )malloc(sizeof(node));
    if (temp == NULL) {
        fprintf(stderr, "memory allocate failed");
        return 0;
    }
    plist = temp;
    (*plist) ->data = *prec;
    (*plist) ->next = NULL;
    return 1;
}

current = *plist;
while (current->next != NULL) {
    current = current->next;
}

And the rest of the code as it was, I added an if for the case *pilist is equals to NULL, in that case temp is going to point at the first element and has to be assigned to plist和代码的 rest 原样,我为这种情况添加了一个 if *pilist 等于 NULL,在这种情况下 temp 将指向第一个元素并且必须分配给 plist

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM