Inserting to beginning of linked list (revisited) - c

I'm very new to coding in C (and therefore the silly exercise I am working on). I tried looking at this other solution to a similar question, but it seems like my coding strategy is different, and ultimately I would like to understand what is the problem with my code. I would greatly appreciate your input.
I have a linked list, a function that inserts a new node at the beginning of my list, a function that prints my linked list, and main function.
Unfortunately my knowledge of C is not good enough to understand why my function is not inserting at the beginning of the list. What is even more unfortunate is that this code does not crash.
#include <stdio.h>
#include <stdlib.h>
typedef struct Node {
int data;
struct Node* next;
} *Node_t;
void print_list(Node_t root) {
while (root) {
printf("%d ", root->data);
root = root->next;
}
printf("\n");
}
void add_to_list(Node_t *list, Node_t temp){
// check if list is empty
if ((*list)->next == NULL) {
// insert first element
(*list) = temp;
}
else {
temp->next = (*list);
(*list) = temp;
}
}
int main () {
int val1 = 4;
int val2 = 8;
int val3 = 15;
Node_t list = malloc(sizeof(struct Node));
Node_t temp1 = malloc(sizeof(struct Node));
Node_t temp2 = malloc(sizeof(struct Node));
Node_t temp3 = malloc(sizeof(struct Node));
temp1->data = val1;
temp1->next = NULL;
temp2->data = val2;
temp2->next = NULL;
temp3->data = val3;
temp3->next = NULL;
//Initialize list with some values
list->data = 0;
list->next = NULL;
/* add values to list */
add_to_list(&list,temp1);
add_to_list(&list,temp2);
add_to_list(&list,temp3);
print_list(list);
}
This code will only ever print the last node I have attempted to add to the list, therefore overwriting the previous nodes.
For example:
Running…
15
Debugger stopped.
Program exited with status value:0.

A single mistake in add_to_list() function:
if ((*list)->next == NULL) { // checks next of first is NULL not list is NULL
// to insert at first
should be just:
if ((*list) == NULL){ // You need to check list is NULL
Check working code
Why you were getting only 15 the last node (temp3) value?
Because in main you creates three temp nodes and initialized next of every node to NULL, including list node so in add_to_list() function if condition ((*list)->next == NULL) always evaluates true and list always initialized with temp node.

Related

Linked List Reversal has errors

In our class right now we're covering nodes and linked lists, and are working on our first linked list program.
We've been given the following guidelines by the teacher:
Make sure your main function will accept 10 characters from STDIN and create a linked list with those characters (so your nodes will have a char member). Then, add an additional function called reverse. The purpose of the reverse function will be to create a copy of the linked list with the nodes reversed. Finally, print off the original linked list as well as the reversed linked list.
I've gotten it all written out, and I've compiled it with no errors - but the program doesn't work as intended, and I'm not entirely sure why. I'm sure it has something to do with how I've set up the pointers to "walk" the nodes - as the debug I put in shows it looping twice per user input letter. Specifications are that we're only supposed to use one function, and we pass a Node* to the function, and it returns the same. The function cannot print out anything - only make the second list that is a reverse of the first.
Any help would be greatly appreciated, I'm not terribly good at this yet and I'm sure I've made some rather silly mistakes.
#include <stdio.h>
#include <stdlib.h>
//struct declaration with self-reference to make a linked list
struct charNode {
char data;
struct charNode *nextPtr;
struct prevNode *prevPtr;
};
typedef struct charNode Node; //makes Node an alias for charNode
typedef Node *NodePtr; //makes NodePtr an alias for a pointer to Node (I think?)
//function declaration for a reverse function
Node* reverse(Node *stPtr);
int main(void)
{
//main function takes 10 letters and puts them in a linked list
//after that, it calls the reverse function to create a reversed list of those characters
//lastly it prints both lists
NodePtr newNode = NULL;
char input;
Node* revStart;
unsigned int counter = 0;
printf("Enter 10 letters to make a list: ");
NodePtr currentPtr = NULL; //sets currentPointer to startNode.
NodePtr previousPtr = NULL; //set previousPointer to null to start
while(counter<= 10)
{
scanf("%c", &input); //gather next letter
NodePtr newNode = malloc(sizeof(Node)); //creates a new node
if (newNode != NULL) //checks to make sure the node was allocated correctly
{
newNode->data = input; //makes the new node's data == input
newNode->nextPtr = NULL; //makes the nextPtr of the newNode NULL
}
currentPtr = newNode; //sets currentPtr to the address of the newNode
if(previousPtr == NULL) { //first time around previousPtr == NULL
newNode->nextPtr = newNode;
previousPtr = newNode; //sets previousPtr to the address of the new node (1st time only)
} else { //afterwards, currentPtr won't be NULL
previousPtr->nextPtr = currentPtr; //last node's pointer points to the current node
previousPtr = newNode; //update previous pointer to the current node
}
++counter;
//debug
printf("\nLoop #%d\n", counter);
}
revStart = reverse(newNode);
puts("The list is: ");
while (newNode != NULL){
printf("%c --> ", newNode->data);
currentPtr = currentPtr->nextPtr;
}
puts("NULL\n");
}
//reversing the nodes
Node* reverse(Node *stPtr)
{
//make a new node
NodePtr currentPtr = stPtr->nextPtr; //get the next letter ready (this will point to #2)
NodePtr prevRevPtr = NULL; //previous reverse node pointer
Node* revStart;
for(unsigned int counter = 1; counter <= 10; ++counter)
{
NodePtr revNode = malloc(sizeof(Node));
if(revNode != NULL) //if reverseNode is allocated...
{
if(prevRevPtr = NULL) //if previousReversePointer = NULL it's the "first" letter
{
revNode->data = stPtr->data; //letter = current letter
revNode->nextPtr = NULL; //this is the "last" letter, so NULL terminate
prevRevPtr = revNode; //previousReversePointer is this one
}else //after the first loop, the previous ReversePointer will be set
{
revNode->data = currentPtr->data; //set it's data to the pointer's data
revNode->nextPtr = prevRevPtr; //reverseNode's pointer points to last node entered
currentPtr = currentPtr->nextPtr; //moves to next letter
prevRevPtr = revNode; //changes previous reverse node to current node
if(counter == 10)//on the last loop...
{
revStart = revNode; //set revStart as a pointer to the last reverse node
//which is technically the "first"
}
}
}
}
return revStart;
}
Assuming your list is properly wired from inception, reversing a double-linked list is basically this:
Node *reverse(Node *stPtr)
{
Node *lst = stPtr, *cur = stPtr;
while (cur)
{
Node *tmp = cur->nextPtr;
cur->nextPtr = cur->prevPtr;
cur->prevPtr = tmp;
lst = cur;
cur = tmp;
}
return lst;
}
That's it . All this does is walk the list, swapping pointers, and retaining whatever the last node processed was. When done correctly the list will still be end-terminated (first node 'prev' is null, last node 'next' is null, and properly wired between.
I strongly advise walking a list enumeration through this function in a debugger. With each iteration watch what happens to cur as it marches down the list, to the active node's nextPtr and prevPtr values as their swapped, and to lst, which always retains the last-node processed. It's the new list head when done.
Okay so we don't need to contend with no line breaks in commments:
Node *reverse(Node *list) {
Node *rev = NULL;
while (list) {
Node *elt = list; // pop from the list
list = list->next;
elt->next = rev; // push onto reversed list.
rev = elt;
}
return rev;
}
As you wrote in comments, you probably don't need to have a previous pointer; you can just create a singly linked list.
There are several issues in your code, including:
When malloc returns NULL, you still continue with the loop -- only part of the code is protected by the if that follows, but not the rest. You should probably just exit the program when this happens.
Your algorithm does not maintain a reference to the very first node, i.e. the place where the linked list starts. When you print the list you should start with the first node of the list, but instead you start with newNode, which is the last node you created, so obviously not much will be printed except that last node. Moreover, both other pointers you have, will also point to the last node (currentPtr, previousPtr) when the loop ends.
newNode->nextPtr = newNode; temporarily creates an infinite cycle in your list. This is resolved in the next iteration of the loop, but it is unnecessary to ever make the list cyclic.
In the reverse function you have if(prevRevPtr = NULL)... You should get a warning about that, because that is an assignment, not a comparison.
Some other remarks:
The reverse function unnecessarily makes distinction between dealing with the first node and the other nodes.
It is also not nice that it expects the list to have 10 nodes. It would be better to just rely on the fact that the last node will have a NULL for its nextPtr.
It is a common habit to call the first node of a linked list, its head. So naming your variables like that is good practice.
As you are required to print both the initial list and the reversed list, it would be good to create a function that will print a list.
As you need to create new nodes both for the initial list and for the reversed list, it would be good to create a function that will create a node for you.
(I know that your teacher asked to create only one function, but this is just best practice. If this doesn't fit the assignment, then you'll have to go with the malloc-related code duplication, which is a pitty).
As you defined the type NodePtr, it is confusing to see a mix of Node* and NodePtr in your code.
Your question was first not clear on whether the reversal of the list should be in-place or should build a new list without tampering with the initial list. From comments it became clear you needed a new list.
I probably didn't cover all problems with the code. Here is a corrected version:
#include <stdio.h>
#include <stdlib.h>
struct charNode {
char data;
struct charNode *nextPtr;
};
typedef struct charNode Node;
typedef Node *NodePtr;
NodePtr reverse(Node *stPtr);
void printList(Node *headPtr);
NodePtr createNode(int data, NodePtr nextPtr);
int main(void) {
NodePtr headPtr = NULL; // You need a pointer to the very first node
NodePtr tailPtr = NULL; // Maybe a better name for currentPtr
printf("Enter 10 letters to make a list: ");
for (int counter = 0; counter < 10; counter++) {
char input;
scanf("%c", &input);
NodePtr newNode = createNode(input, NULL);
if (headPtr == NULL) {
headPtr = newNode;
} else {
tailPtr->nextPtr = newNode;
}
tailPtr = newNode;
}
NodePtr revHeadPtr = reverse(headPtr);
puts("The list is:\n");
printList(headPtr);
puts("The reversed list is:\n");
printList(revHeadPtr);
}
void printList(NodePtr headPtr) {
while (headPtr != NULL) {
printf("%c --> ", headPtr->data);
// You can just move the head pointer: it is a variable local to this function
headPtr = headPtr->nextPtr;
}
puts("NULL\n");
}
NodePtr createNode(int data, NodePtr nextPtr) {
NodePtr newNode = malloc(sizeof(Node));
if (newNode == NULL) { // If malloc fails, exit the program
puts("Cannot allocate memory\n");
exit(1);
}
newNode->data = data;
newNode->nextPtr = nextPtr;
return newNode;
}
NodePtr reverse(NodePtr headPtr) {
NodePtr revHeadPtr = NULL;
while (headPtr != NULL) {
revHeadPtr = createNode(headPtr->data, revHeadPtr);
// You can just move the head pointer: it is a variable local to this function
headPtr = headPtr->nextPtr;
}
return revHeadPtr;
}

Printing struct data from a singly-linked list

I'm trying to build a singly-linked list using a struct with 2 data types: char* and int, as well as next to point to other nodes of course.
I have two functions: addToList, and printList as well as the main method to run everything.
What my code is supposed to do is add a node after the head, and check to see if another node with the same data has already been added. If so, it does not add the new node, while incrementing the count data of the already-linked node.
Then, printList() prints the count data and the char* data of each node.
The first issue is that my char comparison doesn't seem to be working, since duplicate nodes are still added. Then, my printList function does not print the char* data correctly. Here's my code (I made sure to comment it so it's easy to follow along):
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// Struct for node. Has an extra data variable to keep track of which node is next
// in a singly-linked list.
typedef struct node {
char *str;
unsigned int count;
struct node *next;
} node;
// Creates a HEAD node with NULL data.
node *head = NULL;
// Adds a new node and populates the data.
struct node* addToList(struct node* Listptr, char* word){
struct node* new = malloc(sizeof(struct node));
new->str = malloc(sizeof(char) * 34);
strcpy(new->str, word);
new->count = 1;
new->next = Listptr;
// If the head is NULL, sets the new node as the head.
if(head == NULL){
head = new;
return new;
}
// Sets a node iterator "cur" to the first position.
node *cur = head;
// Sets a node iterator to be one place behind cur.
node *prev;
// Loops through the linked list, in order to count the previous words and determine
// if it is necessary to add another node.
// Otherwise, it sets cur to the next node, and prev to the node cur was just at.
while(cur != NULL){
if(cur->str == new->str){
cur->count++;
new = NULL;
return new;
} else{
prev = cur;
cur = cur->next;
}
}
// Checks to see if cur is NULL, if so, sets the previous node.next to the one we're adding.
if(cur == NULL){
prev->next = new;
return new;
}
}
// Prints out the count and word values of each node.
void printList(){
node* cur = head;
while(cur != NULL){
printf("%d %c\n", cur->count, cur->str);
cur = cur->next;
}
}
int main() {
node* Z = NULL;
char *a = "hello";
char *b = "world.";
char *c = "hello";
addToList(Z, a);
addToList(Z, b);
addToList(Z, c);
printList(Z);
return 0;
}
I expect to get:
2 hello
1 world
But in the console, I get:
1 l
1 (weird symbol)
1
Don't use == to compare strings rather use strcmp().
Change if (cur->str == new->str) to this:
if (strcmp(cur->str, new->str) == 0)
Read this to know more on string compare: How do I properly compare strings?

Checking if a Linked list is Empty in C

I have a simple linked list (Which I'm given for a assignment), and I'm trying to check if it's empty (It has no header node), but my implementation doesn't seem to work.
I have the .c file:
#include <stdio.h>
#include <stdlib.h>
#include "test.h"
int main(void) {
List * node;
node = NULL;
node = malloc(sizeof(List));
addToList(node);
return 0;
}
void addToList(List * node) {
if(node == NULL) {
node->value = 3;
node->next = NULL;
}
else {
//add to end of the list:
List * temp = malloc(sizeof(List));
temp->value = 4;
while(node->next != NULL)
node = node->next;
node->next = temp;
temp->next = NULL;
}
}
And the Linked list in the struct (In the .h file)
typedef struct List {
int value;
List * next;
}List;
However, the if statement never executes, even though the list is empty. The struct I'm given doesn't have a header node(I can't change it), so how would I go about fixing this?
Any help would be much appreciated.
The problem is in addToList
node == NULL
should be
node->next == NULL
then you'll also need to insure that function isn't given a null pointer.
Currently you are providing a valid pointer the function and so it is never == NULL
See:
node = malloc(sizeof(List));
addToList(node);
here node is assigned a pointer to a List and provided to addToList.
I suspect what you are really looking for doesn't include that if/else at all and should look something like this (NOTE: You must initialize your list node by hand before calling this function. malloc just gives you a pointer to garbage).
//add to end of the list:
void addToList(List *node) {
if (node == NULL)
return;
List * temp = malloc(sizeof(List));
temp->value = 4;
while(node->next != NULL)
node = node->next;
node->next = temp;
temp->next = NULL;
}
As it was already said the problem is that at first you allocated a node
node = malloc(sizeof(List));
and it got the address of the allocated memory and only after that you called the function
addToList(node);
with this node as an argument.
As result this condition within the function
if(node == NULL) {
equal to false. node is not equal to NULL. It is equal to the address of the allocated memory.
It is much better when the function allocates itself each new node. However in this case you have to declare the function differently.
It and its call can look the following way
#include <stdio.h>
#include <stdlib.h>
#include "test.h"
void addToList( List ** node, int value );
// ^^^^^^^ ^^^^^^^^^
int main(void)
{
List * node NULL;
addToList( &node, 4 );
return 0;
}
void addToList( List ** node, int value )
{
while ( *node ) node = &( *node )->next;
List * temp = malloc( sizeof( List ) );
if ( temp != NULL )
{
temp->value = value;
temp->next = NULL;
*node = temp;
}
}
The condition node == NULL is always false because, before accessing the addToList function, you write node = malloc(sizeof(List)).
Try remove this declaration and change the if statement in
if(node == NULL) {
node = malloc(sizeof(List));
node->value = 3;
node->next = NULL;
}

Linked list shows only first node element on printing

I am trying to create a linked list in order to enhance my concepts of pointers and address. I have to create linked list in following way:
(1) Read all the nodes together at once at terminal.
(2) Then show the final linked list so formed at last.
How i try to do so ?
I am reading first the size of linked list (total number of nodes to be entered). Then i read all the nodes 1 by one in do-while loop. After reading all the nodes i try to create linked list. I differentiate the case when the node is first node to be created by a count variable which will have count=0 when the node is first node after that it will be in another loop.
The output i get is as follows:
enter the size of node
4
start entering the number of elements until your size
2
3
4
5
Printing linked list
2-> //It don't print the other nodes, Just first one
hp#ubuntu:~/Desktop/pointer$
My full code to do so is :
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <string.h>
struct node
{
int freq;
struct node * next;
};
typedef struct node node;
node * tree;
void main()
{
int size, data;
int count = 0; //this count flag is to check is it's first node or not inside the do-while loop.
tree = NULL;
printf("enter the size of node\n");
scanf("%d", & size);
printf("start entering the number of elements until your size\n");
node * temp3 = tree;
node * prev;
//Problem creating area is below
do
{
scanf("%d", & data);
if (count == 0)
{
node * temp;
temp = (node * ) malloc(sizeof(node));
temp-> freq = data;
temp-> next = NULL;
prev = temp;
}
else if (count != 0)
{
node * temp;
temp = (node * ) malloc(sizeof(node));
temp-> freq = data;
temp-> next = NULL;
prev-> next = temp;
}
size--;
++count;
}
while (size > 0);
printf("Printing linked list\n");
node * temp1;
temp1 = prev;
//there may be problem here
while (temp1-> next != NULL)
{
printf("%d-> ", temp1-> freq);
temp1 = temp1-> next;
}
printf("\n");
}
Couldanyone please help me in printing the full linked list by pointing me the error with it's solution ?
Okay there is some unnecessary pointers and a few pointer mistakes being made, for ease of answering I've rewritten your code, I'll try to explain what I did here:
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <string.h>
struct node
{
int freq;
struct node * next;
};
typedef struct node node;
//only need two pointers when building a linked list, one for the top and one for the
//current node
node *tree = NULL, *curr = NULL; //init both pointers to NULL initially
int main()
{
int size, data; //dont need count, you'll see in a minute why
printf("enter the size of node\n");
scanf("%d", & size);
printf("start entering the number of elements until your size\n");
//Problem creating area is below
do
{
scanf("%d", &data);
if (tree == NULL) //just test for top node being NULL instead of using count
{
node *temp;
temp = malloc(sizeof(node));
temp->freq = data;
temp->next = NULL;
//stylistically i like using curr rather than prev, just a style choice
tree = temp; //set tree to first node
curr = tree; //make the top node the current node
}
else //don't need else if, there are only two conditions
{
node *temp = malloc(sizeof(node));
temp->freq = data;
temp->next = NULL;
curr->next = temp; //set the next node in list to the new one
curr = curr->next; //here's where you had pointer issues, move the current
//to the newly created node
}
size--;
}
while (size > 0);
printf("Printing linked list\n");
curr = tree; //reuse curr, no need to make a new pointer
//test for the current node being NULL, takes care of special case of empty list
//causing a segfault when you attempt to access a member of an invalid pointer
while (curr != NULL)
{
printf("%d->", curr->freq);
curr = curr->next; //move to next item in list
}
printf("\n");
return 0;
}
I ran a sample run with size of 3 and inputs of 1, 2, and 3, and I get as output: 1->2->3->
You got two problems.
else if (count != 0)
{
node * temp = prev;
temp = (node * ) malloc(sizeof(node));
temp-> freq = data;
temp-> next = NULL;
prev-> next = temp;
}
You aren't changing prev to point to your new node. It still points to '2' in your scenario, and you'll never have more than two nodes in the list.
Try something like
else if (count != 0)
{
/* node * temp = prev; */ //This code is not doing anything useful
temp = (node * ) malloc(sizeof(node));
temp-> freq = data;
temp-> next = NULL;
prev-> next = temp;
prev = temp;
}
Next, your printing loop should probably be
node* temp1 = start; //You need a variable that points to the first node in the list
do
{
printf("%d-> ", temp1-> freq);
temp1 = temp1-> next;
}
//The last item will always have next == NULL, and must be included
while (temp1-> next != NULL);

nodes, pass by value, weird string behaviour in C

So I have a self-made double-linked-list implementation that is being used as a stand in for a queuer. (implemented in C, a language that I am admittedly weak in).
my typedef for the node:
typedef struct Node
{
char *name;
int data;
int recurring;
struct Node *next;
struct Node *prev;
}node;
which says "a node has a name, a datapoint, whether it's recurring or not and pointers to the previous and next nodes"
the insertion function like so
node * insertFromTail(node *tail, int data, int recurring, char *name)
{
node *newNode;
node *oldNext;
node *origTail = tail;
/*assume *pointer points to tail of list*/
/*printf("tail data is %d\n", tail->data);
printf("before loop\n");*/
while(tail->prev != NULL && tail->data > data)
{
/*printf("inside while loop\n");*/
tail = tail -> prev;
}
/*printf("after loop\n");*/
/*if we are looking at a no item list or tail*/
if(tail->next == NULL)
{
/*printf("pointer is tail\n");*/
return insert(tail, data, recurring, name);
}
else /*tail pointer points at item before the point of insertion*/
{
/*printf("default case\n");
printf("pointer data is %d\n", tail->data);*/
oldNext = tail->next;
newNode = (node *)malloc(sizeof(node));
newNode->data = data;
newNode->recurring = recurring;
newNode->name = name;
oldNext -> prev = newNode;
newNode -> next = oldNext;
tail -> next = newNode;
newNode -> prev = tail;
return origTail;
}
}
with the internal insert
node * insert(node *tail, int data, int recurring, char *name)
{
/* Allocate memory for the new node and put data in it.*/
tail->next = (node *)malloc(sizeof(node));
(tail->next)->prev = tail;
tail = tail->next;
tail->data = data;
tail->recurring = recurring;
tail->name = name;
tail->next = NULL;
return tail;
}
which is passed the tail of the list, the data point, the time at which the next item will recur at and the name of the item.
if we start with a node that is empty and has NULL prev and next references (a dummy node), and I add three unique nodes with a function called ADD that calls insertFromTail taking input from stdIn
int main()
{
node *start,*temp,*tail;
start = (node *)malloc(sizeof(node));
temp = start = tail;
temp->next = NULL;
temp->prev = NULL;
if(strcmp(command, "ADD") == 0)
{
scanf("%d",&argTime);
scanf("%s",&argName);
tail = insertFromTail(head, argTime, 0, *argName);
}
}
with input as so:
INPUT:
ADD 10 Gin
ADD 20 Vodka
ADD 30 Rum
PRINT
I would get an output of
OUTPUT:
Rum 10
Rum 20
Rum 30
This is an error, as the desired output would be
OUTPUT:
Gin 10
Vodka 20
Rum 30
I have a feeling it has to do with how the string is passed into the node, but as you can see, I'm stumped. This is the last thing left on the assignment and everything else is working perfectly, so I decided to ask here to see if anyone can nudge me on the right path. Thanks for your help in advance :)
P.S. Sorry for bad everything, I'm sleep deprived :(
Short answer: you'll need to duplicate that name:
tail->name = strdup(name);
Longer answer: at each iteration you're storing the same pointer. You're storing it and then the next time you're writing to it again. So you end up with 3 identical pointers to whatever you input last.
A simple fix is to duplicate the string and store a copy: precisely what strdup does. But if your implementation lacks strdup, you can try:
tail->name = malloc(strlen(name) + 1);
strcpy(tail->name, name);
Don't forget to check for errors
Don't forget to free the memory at some point

Resources