-3

I am confused why my code wouldn't print the good result when trying to add a node at the end of a linked list. I want to understand the logic behind it, I will show you two different codes the first one only prints the first node even if the list 'contains' more than one node, the second one works exactly as intended but I don't understand WHY or how it works.

First code: (The confusing one)

#include <stdio.h>
#include <stdlib.h>
struct Node{
    int data;
    struct Node *next;
};
typedef struct Node Node;
Node *head;
void insertNode(int value){
    Node *t = head;
    //t = head;
    if (head == NULL){
        Node *tmp = malloc(sizeof(Node));
        tmp->data = value;
        tmp->next = NULL;
        head = tmp;
    }

    else{
        while (t != NULL) {
        t = t->next;
    }
    Node *tmp = malloc(sizeof(Node));
    tmp->data = value;
    tmp->next = NULL;
    t = tmp;
    }
}
void showNode(){
    Node *tmp = head;
    while (tmp != NULL) {
        printf("-> %d",tmp->data);
        tmp = tmp->next;
    }
}
int main(){
    int n,value;
    head = NULL;
    printf("Node number: ");scanf("%d",&n);
    for (int i = 0; i < n; i++) {
        scanf("%d",&value);
        insertNode(value);
    }
    showNode();
    printf("\n");
    return 0;
}

The second code: (The correct one)

The only difference is in the insertNode function,

void insertNode(int value){
    Node *t = head;
    //t = head;
    if (head == NULL){
        Node *tmp = malloc(sizeof(Node));
        tmp->data = value;
        tmp->next = NULL;
        head = tmp;
    }

    else{
        while (t->next != NULL) {
        t = t->next;
    }
    Node *tmp = malloc(sizeof(Node));
    tmp->data = value;
    tmp->next = NULL;
    t->next = tmp;
    }
}

So, my question is HOW both codes work and what's wrong with the first code ?

Thank you, :)

Kevin
  • 6,993
  • 1
  • 15
  • 24
Ayoub EL
  • 3
  • 2
  • 2
    I tagged em both, C and C++. And it doesn't matter C or C++ in here, both work. – Ayoub EL Dec 11 '15 at 16:58
  • 4
    It does matter, because c is not c++ and c++ is not c. – 463035818_is_not_an_ai Dec 11 '15 at 16:59
  • `t = temp` is updating the local variable. It changes the list in no way. Doing `t->next = temp` (where `t` is the last node, not `NULL`) actually references the last node's `next` pointer, thus updating the list. – David G Dec 11 '15 at 16:59
  • I pick C. And this is a code I wrote. – Ayoub EL Dec 11 '15 at 17:00
  • 1
    Questions seeking debugging help ("why isn't this code working?") must include the desired behavior, a specific problem or error and the shortest code necessary to reproduce it in the question itself. Questions without a clear problem statement are not useful to other readers. See: How to create a Minimal, Complete, and Verifiable example. – too honest for this site Dec 11 '15 at 17:01
  • Sounds great. That's what I am looking for, let me think about it and I'll let you know, Thank you, 0x499602D2, :) – Ayoub EL Dec 11 '15 at 17:03
  • I don't get that C is not C++. I believe a C program would run under C++ complier so the code I wrote is both executable either in C or C++, I don't see the difference. – Ayoub EL Dec 11 '15 at 17:05
  • C is not C++. But C++ is C. – Ayoub EL Dec 11 '15 at 17:06
  • @YennoRyzom While C++ is indeed a superset of C, there is absolutely nothing c++ specific in the code you posted, making the tag redundant. – Lloyd Crawley Dec 11 '15 at 17:07
  • @YennoRyzom: Not that again! If one really think C++ is "C with classes", she does not know at least one of the languages. Both have constructs the other languafges doesn't have and some semantics differ - despite identical syntax. – too honest for this site Dec 11 '15 at 17:08
  • @MetalMessiah: C++ is **not** a superset of C! Please point me at the C++ standard's definition of VLAs, flexible array members, etc. Also some semantics differ. Try not casting `void *` in C++ and you get an error. I c you should not cast, etc. Finally, if you program any non-trivial program in C++ the same style as in C you do something wrong. – too honest for this site Dec 11 '15 at 17:10
  • both designs are incredibly wrong. insert_node should take a pointer to a struct Node and a value, or else It will be useless. – ForeverStudent Dec 11 '15 at 17:13
  • @Olaf I hear you. Just found this very interesting question http://stackoverflow.com/questions/1201593/c-subset-of-c-where-not-examples Thanks for inspiring me to investigate this – Lloyd Crawley Dec 11 '15 at 17:15
  • Thank you all. I have learnt a lot. :) – Ayoub EL Dec 11 '15 at 18:35

3 Answers3

1

The big change is the condition in the while loop:

while (t != NULL)

and

while (t->next != NULL)

In the first one a new node is created but there is no "link" to the existing list used, the pointer used to traverse the nodes has already gone past the end point.

In the second case the use of the conditional and the code

t->next = tmp;

means that the new tmp node does in fact have a connection to the existing list, it isn't just dangling in some limbo like the first case's new nodes.

Lloyd Crawley
  • 606
  • 3
  • 13
1

The 2nd example works because the while loop does not go all the way till the last node. See the while condition. The first example fails because you go to the last node, and set the newly allocated Node *tmp to t(which is NULL) by definition of your while loop condition.

Graphically:

When your while loop breaks:

NODE 1--> NODE 2--> NODE 3--> NODE 4--> NODE 5 -->NULL

                                  t points here  ^(1st case)

NODE 1--> NODE 2--> NODE 3--> NODE 4--> NODE 5 -->NULL

                            t points here ^       (2nd case)

(So, basically you're assigning something to NULL. NULL is not your last node). Also, t is a local variable

This is correct since you're not assigning a new node at the end of the last one.

Kedar Paranjape
  • 1,822
  • 2
  • 22
  • 33
0

The first code does not insert multiple elements in the list. It inserts only one, which is why it prints only one.

At the end of this loop while (t != NULL), t is NULL. The rest of the block simply creates a new node, and assigns it to t, without updating the list.

In the second code, t points to the last element of the list. So adding an element at t->next does update the list.

Richard St-Cyr
  • 970
  • 1
  • 8
  • 14