I'm trying to create a list in alphabetical order (first by author, then by name). I tried to do it by comparing the two strings with strcmp()
but I'm getting a segmentation fault.
I'll leave the GDB run result down here and the function, it's one of the first programs I made with lists so the code has probably other errors.
GDB run :
Program received signal SIGSEGV, Segmentation fault.
0x0000000000400c65 in insert (lPtr=0x7fffffffeb38, isbn_i=978044,
name_i=0x7fffffffeb40 "Suzanne Collins",
author_i=0x7fffffffeb80 "The Hunger Games") at main.c:178
178 while(strcmp(author_i, currPtr->author) < 0){
typedef struct library{ //struct insertion from stdin
int isbn;
char *author;
char *name;
int act; //actual books in memory
int tot; //total books
struct library *nextPtr; //node
}Lib;
typedef Lib *NodePtr;
//called by a while, receives input from integers and two arrays of char
void insert(NodePtr *lPtr, int isbn_i, char *name_i, char *author_i){
NodePtr newPtr = malloc(sizeof(Lib));
newPtr->isbn = isbn_i; //scanf insertion in node
newPtr->author = author_i;
newPtr->name = name_i;
newPtr->nextPtr = NULL;
NodePtr prevPtr = NULL;
newPtr->act = 1;
newPtr->tot = 1;
if(lPtr == NULL){ //empty list
*lPtr = newPtr;
return;
}
NodePtr currPtr = *lPtr;
while(strcmp(author_i, currPtr->author) < 0){ //author is different, list slides
prevPtr = currPtr;
currPtr = currPtr->nextPtr;
}
if(strcmp(author_i, currPtr->author)== 0){ //same author
while(strcmp(name_i, currPtr->name) < 0){ //list sliding
prevPtr = currPtr;
currPtr = currPtr->nextPtr;
}
if(strcmp(name_i, currPtr->name) == 0){
currPtr->act += 1; //updates current counter and returns (to avoid duplicates)
currPtr->tot += 1;
free(newPtr);
return;
}
}
prevPtr->nextPtr = newPtr; //insertion between two nodes
newPtr->nextPtr = currPtr;
}
in the following code :
while(strcmp(author_i, currPtr->author) < 0){ //author is different, list slides
prevPtr = currPtr;
currPtr = currPtr->nextPtr;
}
you do not check if currPtr->nextPtr
is NULL
(at the end of your list),
if your list author only contains author that should be ordered after author_i
you will reach the end without finding a place to insert.
Example (unrelated field omitted for brievty):
currPtr = {author:"Cressida Cowell", nextPtr=NULL};
insert(lPtr = &currPtr, ...,author_i = "Suzanne Collins", ...);
/// insertion location loop
// while loop unrolled
if("Suzanne Collins" > "Cressida Cowell") {
prevPtr = currPtr ; // prevPtr = {author:"Cressida Cowell", nextPtr=NULL};
currPtr = currPtr->nextPtr; // currPtr = NULL
}
// next iteration
if("Suzanne Collins"> NULL->author ) // de-referencing a NULL pointer, causing a Segmentation fault
you could partially fix the code with the following fix:
while(strcmp(author_i, currPtr->author) < 0){ //author is different, list slides
prevPtr = currPtr;
currPtr = currPtr->nextPtr;
if(currPtr == NULL) {break;} // exit loop if at end of the list
}
you still need to handle currPtr == NULL
to avoid de-referencing the NULL pointer in currPtr
when checking for title, my recommendation would be to combine the conditions in the insertion location searching loop.
// implement a node comparison function
int compareLib(NodePtr lib1, NodePtr lib2) {
if((lib1 == NULL)||(lib2 == NULL)) return 0;
int author_compare = strcmp(lib1->author, lib2->author);
if (author_compare != 0) return author_compare;
return strcmp(lib1->name, lib2->name);
}
...
while(compareLib(newPtr, currPtr)){
prevPtr = currPtr;
currPtr = currPtr->nextPtr;
if(currPtr == NULL) {break;} // exit loop if at end of the list
}
You still need to Handle currPtr == NULL
when adding the new list node