I am trying to teach myself linked-lists with node structs and was hoping someone could help me with this. I would take input from the command line and it would make me a nested list and I could output it.
Example:
Input: “1 2 3 4 5”
Output:”1 2 3 4 5″
There are two things I am having trouble with:
1) When I run the program I keep getting warning: ‘typedef’ was ignored in this declaration [enabled by default]
How can I get rid of this?
EDIT: I have changed this to typedef struct Node* NodePtr;
2) My code is not working properly. How can I fix this? I am trying to teach myself linked lists in C++.
typedef struct Node;
typedef Node* NodePtr;
struct Node{
int x;
NodePtr next;
};
int main ()
{
int n;
NodePtr head, ptr = NULL;
head = ptr;
while (cin >> n){
ptr = new Node;
ptr->x = n;
ptr->next = NULL;
ptr = ptr->next;
}
NodePtr bling = head;
while(bling != NULL){
cout << bling->x << endl;
bling = bling->next;
}
return 0;
}
Ideally what I want to do is to make a linked-list like the following.
1 -> 2 -> 3 -> NULL.
First, regarding the declaration of your structure and the pointer typedef you seem to want, there are a number of ways of doing this. The following will work in C or C++.
That said, I honestly do not recommend doing this. Most engineers want a clear and syntax-visible definition that screams to them, “THIS IS A POINTER!” You may be different. I, personally would simply prefer this:
So long as you, and equally important, other engineers reading your code, understand your usage of
NodePtras a pointer-to-node, then go with what works best in your situation. Pointer type declaration is near-religious to some, so just keep that in mind. Some prefer seeing those asterisks (I being one), some may not (sounds like you =P).Note: there is one place that using a
typedefed pointer-type can be beneficial in avoiding potential errors: multiple variable declarations. Consider this:Having a
typedef struct Node *NodePtr;allows this:If you spend enough time writing code in C the former of these will come back to bite you enough times you learn to not make that mistake, but it can still happen once in awhile.
The Load Loop
Regarding the load-loop for piecing together your list, you’re not wiring up your list correctly, and frankly there are a million ways to do it, one being the one below. This does not require you to clean out “an extra node”. Nor does it require any
if (head){} else{}block structure to avoid said-same condition. Consider what we’re really trying to do: create nodes and assign their addresses to the right pointers:How It Works
ptr.ptr(thus the*ptr). On the first iteration this holds the address of theheadpointer, so theheadvariable will get our new node allocation. On all subsequent iterations, it contains the address of thenextpointer of the last node inserted. Incidentally, saving the address of this new target pointer is the last thing that is done in the loop before we move to the next allocation cycle.nextpointer set to NULL to ensure a properly terminated linked list. This is mandatory. We conveniently have a pointer to that pointer (the same one we’ve been using all this time), and thus we set the pointer it “points to” to NULL. Our list is terminated and our load is complete. Brain Food: What pointer will it be pointing to if the load loop never loaded any nodes? Answer:&head, which is exactly what we want (aNULLhead pointer) if our list is empty.Design
I hope this will help better explain how it works through three full iterations of the loop.
Initial configuration
After one iteration:
After two iterations
After three iterations
If we stopped at three iterations, the final termination assignment (
*ptr = NULL;), gives:Notice that
headnever changes once the first iteration is finished (it always points to the first node). Also notice thatptralways holds the address of the next pointer that is to be populated, which after the initial iteration (where it started as the address of our head pointer), will always be the address of thenextpointer in the last node added.I hope that gives you some ideas. It is worth noting that pairing these two pointers (the
headpointer and theptrpointer) into their own structure and having the appropriate management functions defines the textbook Queue; where one end is only for insertions (ptr) one is for extractions (head) and the container does not allow random access. There isn’t much need for such a thing these days with the standard library container adapters likestd::queue<>, but it does provide an interesting adventure into a good use of pointer-to-pointer concepts.Complete Working Sample
This sample just loads our queue with 20 elements, prints them, then cleans out the queue and exits. Adapt to your usage as needed (hint: like change the source of the incoming data perhaps)
Output