I'm pretty new to C and pointers.
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
I doubt the segmentation fault error happens due to dereferencing a null pointer but have no idea what's wrong with my code.
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
list.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;
}
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;
, 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)
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
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.