簡體   English   中英

鏈表顯示分段錯誤錯誤

[英]Linked list shows segmentation fault error

我對 C 和指針很陌生。

以下代碼用於實現一個鏈表,其中每個節點都包含一個記錄數據。

但是,當我編譯並運行該程序時,它顯示錯誤“分段錯誤”,我猜我的代碼中的以下部分會出錯。
head->next = NULL在列表中的函數中。c
我懷疑由於取消引用 null 指針而發生分段錯誤錯誤,但不知道我的代碼有什么問題。

列表.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

#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

記錄.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

列表.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

#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

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

如果您的目標是創建一個空列表並且plist是指向列表頭的指針,則您必須將plist指向的變量設置為 NULL ,其中*plist = NULL; ,就可以擺脫導致分段錯誤的代碼

好的,我想我發現了下一個錯誤:

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

會導致錯誤,因為第一次調用 list_insert 你有 *plist 等於 NULL 因為列表是空的,所以 current->next != NULL 將導致錯誤(current 也等於 NULL)

我建議如下:

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

和代碼的 rest 原樣,我為這種情況添加了一個 if *pilist 等於 NULL,在這種情況下 temp 將指向第一個元素並且必須分配給 plist

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM