my assignment is to create a linked list and then write a bool function attempts to add a student with given id and name into the given list; if a student with that id is already in the list then return false, otherwise the list is modified and true is returned. Im a beginner and I rarely understand why segmentation faults occur so any help will be appreciated.
here are my structure definitions(provided by prof)
struct snode{
int id;
char * name;
struct snode * next;
};
struct slist{
struct snode * front;
};
here is my bool function
bool insert_student(int id, char name[], struct slist * lst) {
struct snode *head = malloc(sizeof(struct snode));
head = lst->front;
// check if list is empty
if (head != NULL) {
struct snode *node = malloc(sizeof(struct snode));
while (node != NULL) {
// traverse the list to see if student exists in list
if (node->id = id) {
return 0;
}
else {
// if it doesnt exist, add it
struct snode *ins_std = malloc(sizeof(struct snode));
ins_std = node->next;
ins_std->id = id;
ins_std->name = name;
ins_std->next = lst->front;
lst->front = ins_std;
return 1;
}
node = node->next;
}
} // if list is empty
else {
head->next = NULL;
head->name = name;
head->id = id;
return 1;
}
}
main function
int main() {
struct slist *head = create_list();
int id1 = 11001;
int id2 = 11002;
int id3 = 11003;
int id4 = 11004;
int id5 = 11005;
char name1[] = "Dave";
char name2[] = "Ali";
char name3[] = "John";
char name4[] = "Randall";
char name5[] = "Kelly";
assert(insert_student(id1, name1, head) == 1);
insert_student(id2, name2, head);
insert_student(id3, name3, head);
insert_student(id4, name4, head);
insert_student(id5, name5, head);
}
CodePudding user response:
Im a beginner and I rarely understand why segmentation faults occur I suspect you never do at this stage.
struct snode *head = malloc(sizeof(struct snode));
head = lst->front;
Here you allocated some space and save the reference to head
, only to be overwritten by lst->front
(which could be NULL
). These two lines already cause segfault. I think what you are trying to do is to save the reference to the allocated space to lst->front
, namely lst->front = head;
instead of the other way around.
if(node->id = id){
Common error, use ==
for equality check.
struct snode *ins_std =malloc(sizeof(struct snode));
ins_std = node->next;
Similar issue to the first code snippet.
Solving the above issues should fix the segfaults and assertion errors. There are also a few logical loopholes in the code, but that is for another story.
CodePudding user response:
As a beginner, it helps to have "working code" to study. Here's a 'stripped down' version of your assignment. Make sure you understand what it does, then gradually add elaborations to build-up toward the entire project.
Programs aren't "typed-in", straight from brain to keyboard. You start off with something simple, then SLOWLY embellish that. Compile (with warnings turned up to the max) often, and test each step along the way.
Best wishes.
struct snode{
int id;
struct snode * next;
};
bool addNode( struct snode **pList, int id ) {
for( struct snode *pSrch = *pList; pSrch; pSrch = pSrch->next )
if( pSrch->id == id )
return false; // already on list...
struct snode *pNew = malloc( sizeof( *pNew ) );
// check of malloc() success omitted
pNew->id = id;
pNew->next = *pList; // PREpending to existing list
*pList = pNew;
return true;
}
int main() {
int ids[] = { 11001, 11002, 11003, 11004, 11005, 11002, 11006, 11007, }; // Notice blooper
const int nIDs = sizeof ids/sizeof ids[0];
struct snode *pList = NULL; // This will be 'buried' as "front"...
for( int i = 0; i < nIDs; i ) {
printf( "ID %d ... ", ids[i] );
if( addNode( &pList, ids[i] ) )
printf( "Success\n" );
else
printf( "Failed\n" );
}
for( struct snode *pWalk = pList; pWalk; pWalk = pWalk->next )
printf( "Walking... ID %d\n", pWalk->id );
return 0;
}
CodePudding user response:
There are several mistakes in the code shown.
Here is a cleaned up example.
Within insert_student
we:
- Immediately check that
lst
is notNULL
. If it is, we immediately return false. Every point in the function afterward we can assumelst
is notNULL
. - Create a pointer to a node that will point to the last node in the list.
- If the front node in the list is not
NULL
we proceed to check if the node is the last. If it is, store a pointer to it inlast
. And if theid
is already taken, we immediately return false. - Now we allocate a new node, making sure to allocate space for the name (and the null terminator character), and using
strcpy
to copy thename
argument into the memory we've just allocated. - If
last
was assigned something other thanNULL
, have itsnext
pointer point to the new node. - If
last
is stillNULL
it stands to reasonlst->front
wasNULL
. Assign the new node pointer to that pointer. - If execution has reached this point, the insertion has happened. Return true.
A further exercise would be to write a function to free the allocated memory.
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <stdio.h>
struct snode {
int id;
char *name;
struct snode *next;
};
struct slist {
struct snode *front;
};
bool insert_student(struct slist *lst, int id, const char *name);
int main() {
struct slist *lst = malloc(sizeof(struct slist));
insert_student(lst, 1, "Bob");
insert_student(lst, 2, "Dave");
for (struct snode *cur = lst->front; cur; cur = cur->next) {
printf("-, %s\n", cur->id, cur->name);
}
return 0;
}
bool insert_student(struct slist *lst, int id, const char *name) {
if (!lst) return 0;
struct snode *last = NULL;
if (lst->front) {
for (struct snode *cur = lst->front; cur; cur = cur->next) {
if (cur->next == NULL) last = cur;
if (cur->id == id) return 0;
}
}
struct snode *new_node = malloc(sizeof(struct snode));
new_node->id = id;
new_node->name = malloc(strlen(name) 1);
strcpy(new_node->name, name);
if (last) {
last->next = new_node;
}
else {
lst->front = new_node;
}
return 1;
}
Output:
1, Bob
2, Dave