Связанный список показывает ошибку ошибки сегментации - PullRequest
0 голосов
/ 05 апреля 2020

Я довольно новичок в C и указателях. Следующие коды предназначены для реализации связанного списка, в котором каждый узел содержит данные записи.

Однако, когда я компилирую и запускаю эту программу, она показывает ошибку "ошибка сегментации", и я предполагаю, что следующая часть из моего кода делает ошибку.
head->next = NULL в функциях в списке. c
Я сомневаюсь, что ошибка ошибки сегментации происходит из-за разыменования нулевого указателя, но я не знаю, что не так с моим кодом.

list.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

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

1 Ответ

0 голосов
/ 05 апреля 2020

Если ваша цель - создать пустой список, а 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;
}

И остальной код как был, я добавил if для случая * pilist равен NULL, в этом случае temp будет указывать на первый элемент и должен быть назначен plist

...