I have a program written in C. And I struggle with the effect I can't understand. The app reads a sequence of words as a command line input. While reading an input it puts one-by-one words into a list. And then it prints the list. What blows my mind is why values added ouside the loop are printed correctly whilst values added inside the loop aren't. I mean whichever values are input by user, only the last one will be printed. And furthermore it will be printed as many times as the number of values were input is. The two primary suspects are push and printList methods:
void push(struct List * list, char* newValue){
assert(list != NULL);
assert(newValue != NULL);
Node* node = createNode();
node->data = newValue;
node->next = NULL;
if(list->firstNode != NULL){
node->next = list->firstNode;
list->firstNode = node;
}
else list->firstNode = node;
}
void printList(struct List * list){
assert(list != NULL);
Node *node = list->firstNode;
while(node->next != NULL){
printf("%s ", node->data);
node = node->next;
}
if(node != NULL) printf("%s ", node->data);
}
But I couldn't find any bugs in there. What I did is I compared the behaviour with and without a while loop:
int main(){
struct List* list = createList();
char s[256];
int a;
push(list, "he");
push(list, "bee");
push(list, "gee");
while(scanf("%s", &s) == 1) push(list, s);
printList(list);
}
The output I got is:
c c c gee bee he
Whilst the input is:
a b c
So I expected to get
c b a gee bee he
What did I miss? Any suggestion is highly appreciated.
P.S. The type defs and methods used above are:
typedef struct Node {
char* data;
struct Node *next;
} Node;
typedef struct List {
struct Node *firstNode;
} List;
Node *createNode(){
Node* node = malloc(sizeof(struct Node));
assert(node != NULL);
node->data = "";
node->next = NULL;
return node;
}
List *createList(){
List* list = malloc(sizeof(struct List));
list->firstNode = NULL;
assert(list != NULL);
return list;
}
createListyou put your assertion in the wrong place, so it will have no effect: Iflistis null, you will seg fault before you even reach the assertion. Always check the return value ofmallocbefore attempting to access the pointer it returns.node->data = newValueassigns a pointer, and when you callpush(list, s);you are passing the same pointer each time.push. In the case of string constants, it's not an issue, but for the string read byscanf, you're using an automatic arraysover and over. You can usestrdupto allocate storage and copy the strings.