So here I have created a C program to create and display a singly linked list.
#include <stdio.h>
#include <conio.h>
int main()
{
struct node
{
int data;
struct node *next;
};
struct node *head = malloc(sizeof(struct node));
struct node *temp = malloc(sizeof(struct node));
struct node *newnode;
int choice=1,count=0;
while(choice==1){
newnode=(struct node *)malloc(sizeof(struct node));
printf("Enter data");
scanf("%d",&newnode->data);
newnode->next=0;
if(head==0)
{
head=temp=newnode;
}
else
{
temp->next=newnode;
temp=newnode;
}
printf("\nDo you want to continue\n");
scanf("%d",&choice);
}
temp=head;
while(temp!=NULL){
printf("%d",temp->data);
temp=temp->next;
count++;
}
getch();
}
I'm not getting the desired output i.e. the linked list I am creating is not being displayed. Can someone please help me out and tell me where I went wrong?
Some comments on your code:
head should not start as a node instance: you don't have any value yet. It should start as NULL, which is also in line with the if condition you have in the loop. NULL represents an empty list, which is what you want to start with. Two problems are the consequence of this:
Since it isn't NULL at the start, the (head==0) condition is never true, and the loop never updates head. All the work done remains detached from this head node.
head references a node that is not initialised. Its value is undefined, and worse, its next reference is undefined. This leads to undefined behaviour during the print loop, where this next reference is used.
temp starts as a node instance, but as in the loop, temp is assigned temp->next, the code loses a reference to the original temp node. And each time temp progresses to the next, also the references to all other created nodes are lost.
temp is not a very useful name, as this variable has the same life time as head. In practice it represents the tail of the list in the first loop, so call it tail. The first point holds also for this tail: it should start as NULL
count is never used. Moreover, it should not be incremented during a print-job: that is mixing two jobs. Either count the nodes or print them, but don't do it together. Anyway, as this code has no use for this count, I'd just drop it.
It is better practice to use NULL when related to a pointer data type, not 0.
Separate functionality: now you have literally everything happening in one function: creating nodes, getting input, outputting nodes,... This is not maintainable. Separate different domains of functionality in separate functions.
If the only reason for include conio.h is to make that final getch call, presumably because you want to use to press enter at the end of the program, then just leave it out.
Here is some suggested code:
#include <stdio.h>
#include <stdlib.h>
// Define struct outside of main
struct node
{
int data;
struct node *next;
};
// Define some functions that perform common actions for a list
struct node *createNode(int data)
{
struct node *newnode = malloc(sizeof(struct node));
// Initialise the struct, so avoiding undefined behaviour
newnode->data = data;
newnode->next = NULL;
return newnode;
}
struct node *appendNode(struct node *tail, int data)
{
struct node *newnode = createNode(data);
if (tail != NULL) {
tail->next = newnode;
}
return newnode;
}
void printList(struct node *head)
{
while (head != NULL) {
printf("%d ", head->data); // Space between outputs
head = head->next; // head is a local variable, so we can change it
}
printf("\n"); // Terminate line
}
int main()
{
struct node *head = NULL; // Start with empty list
struct node *tail = NULL; // Better name. In beginning we don't have a tail
int choice = 1, data = 0;
while (choice == 1) {
// First get the data, and only then create the node
printf("Enter data: ");
scanf("%d", &data);
tail = appendNode(tail, data);
if (head == NULL) // Use NULL constant
{
head = tail;
}
printf("Do you want to continue? (0=no, 1=yes): ");
scanf("%d", &choice);
}
printList(head);
return 0;
}
Related
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;
}
I am working on creating a linked list program in C. I am having trouble displaying the entire list. All I can get to display is the first and last elements. Not sure what is going on. I have tried changing the links to every different way I can think of, and none of them will quite work. I am pretty sure this is just a simple mistake I am making somewhere. I would appreciate any help and suggestions.
Here is the code
#include <stdio.h>
#include <stdlib.h>
struct node
{
int data;
struct node *next;
}
*start = NULL;
void display();
void create ();
int main(void)
{
int numberOfElements = 0;
printf("How many elements do you want to enter?\n");
scanf("%d",&numberOfElements);
for (int i = 0; i < numberOfElements; ++i){
printf("Please enter data for element number %d\n", i+1);
createList();
}
display();
return 0;
}
void display(){
struct node *tempNode;
printf("Now displaying the list\n");
tempNode = start;
while (tempNode != NULL){
printf("%d---> ",tempNode->data);
tempNode = tempNode->next;
}
printf("NULL\n");
}
void createList(){
struct node *newNode, *current;
newNode = (struct node *)malloc(1 * sizeof (struct node));
//printf("Please enter the data for each element\n");
scanf("%d", &newNode ->data);
// For testing
printf("You entered %d\n",newNode->data);
newNode->next = NULL;
if(start == NULL){
start = newNode;
current = newNode;
}
else {
current->next = newNode;
current = newNode;
}
}
So when the user enters some data, say two elements, of 22 and 28, the display should be 22--->28--->NULL instead what is displayed is 22--->NULL
Thank you
Your code expects/requires that the variable current in createList maintain its value between calls of the function. By default it doesn't work that way in C. The value of variables inside a function doesn't keep their value from call to call.
If you want a variable in a function to behave that way, you need to use the keyword static.
So if you change:
struct node *newNode, *current;
to
struct node *newNode;
static struct node *current;
the variable current will keep its value between calls and your code will (probably) work.
In more technical terms you should read about "automatic storage duration" and "static storage duration".
That said, it's not a good idea to do something like that - in fact, it's a rather bad idea. Also it's a bad idea to have start as a global variable.
Instead you should define two variables in main- for instance head and tail - and pass these (or their address) to the insert-function.
Something like:
int main(void)
{
struct node* head = NULL;
struct node* tail = NULL;
createList(&head, &tail);
createList(&head, &tail);
createList(&head, &tail);
display(head);
return 0;
}
void createList(struct node* pHead, struct node* pTail)
{
// malloc and initialize new node
if (*pHead == NULL)
{
*pHead = newNode;
*pTail = newNode;
return;
}
(*pTail)->next = newNode;
*pTail = newNode;
}
The reason is, current is locally scoped in your CreateList function, though you're persisting the current node in the current, when CreateList exits, current is vanished, during another call of the CreateList, current knows nothing from previous execution, as it's created as brand-new variable for this particular invocation of the function. But you're persisting the value only for first node as start is globally scoped, it exists unless your program finishes execution.
So, make current global variable, that fixes the bug:
Look at this: https://ideone.com/yWQLDL
I must write a code for a lab and i don't understand how i can insert the nodes with which function.
struct list
{int value;
struct list * next;};
int main()........
the code says that we ask the user how many integers (N) he wants to insert to the list.. so easy printf, scanf
AND THEN ..It will ask for the numbers and list them in the order they are given.
I think that i need a for loop
but i know many function for inserting for example insertAfter, push etc, etc
I need you help! Thank you
The structure you have given represents a node. You first create a head of the list, then you need to read numbers one by one, create a node for each number and append it at the end of the list using append() function defined in the code given below.
Here is the full program you require (function codes taken from geeksforgeeks.org):
#include <stdio.h>
#include <stdlib.h>
// A linked list node
struct Node
{
int data;
struct Node *next;
};
/* Given a reference (pointer to pointer) to the head
of a list and an int, appends a new node at the end */
void append(struct Node** head_ref, int new_data)
{
/* 1. allocate node */
struct Node* new_node = (struct Node*) malloc(sizeof(struct Node));
struct Node *last = *head_ref; /* used in step 5*/
/* 2. put in the data */
new_node->data = new_data;
/* 3. This new node is going to be the last node, so make next of
it as NULL*/
new_node->next = NULL;
/* 4. If the Linked List is empty, then make the new node as head */
if (*head_ref == NULL)
{
*head_ref = new_node;
return;
}
/* 5. Else traverse till the last node */
while (last->next != NULL)
last = last->next;
/* 6. Change the next of last node */
last->next = new_node;
return;
}
// This function prints contents of linked list starting from head
void printList(struct Node *node)
{
while (node != NULL)
{
printf(" %d ", node->data);
node = node->next;
}
}
int main()
{
/* Start with the empty list */
struct Node* head = NULL;
int n;
scanf("%d", &n);
for(int i=0; i<n; i++) {
int e;
scanf("%d", &e);
append(&head, e);
}
printList(head);
}
I've been asked to make a couple of programs using C. In one of these programs, I need to create a linked list so I can do some stuff with it. But, I am not allowed to use global variables nor loops (While, For, etc.) in any of these programs. So here is a small program I wrote just to fresh up linked lists:
#include <stdio.h>
#include <stdlib.h>
struct node {
int number;
struct node *next;
};
void create (struct node *, struct node *);
void insert (struct node *, struct node *);
void display (struct node *);
int main(void) {
struct node *head;
struct node *current;
struct node *temp;
create ( head, current );
insert ( head, current );
temp = head;
display ( temp );
}
void create ( struct node *head, struct node *current ) {
int a;
printf("Insert: ");
scanf("%d", &a);
current = malloc(sizeof(struct node));
current -> number = a;
current -> next = NULL;
head = current;
}
void insert ( struct node *head, struct node *current ) {
int b;
printf("insert: ");
scanf("%d", &b);
if ( b == -1 ) return;
else {
current = malloc(sizeof(struct node));
current -> number = b;
current -> next = NULL;
}
insert ( head, current );
}
void display ( struct node *temp ) {
if ( temp != NULL ) {
printf("%d \t", temp -> number); //Error: EXC_BAD_ACCESS (code=EXC_I386_GPFLT)
temp = temp -> next;
display ( temp );
}
else return;
}
It's more or less the standard code that every book has, but instead of loops I use recursive functions. If you look closely, I have a problem with the display() function. I get this error: EXC_BAD_ACCESS (code=EXC_I386_GPFLT) inside the function, at the printf() line. So I can't print my list on screen. I've been debugging it for like 4 hours now and I can't find what's wrong, any help will be appreciated!
A third problem on top of the one posted by weather vane :
your insert is very weird. You ask for input and then recursively call insert again. Asking for input, ...
But you never hook in the current in the chain of the linked list.
Your code contains two problems. Firstly, the functions insert and create should take struct node ** arguments instead of struct node * arguments. Then you need to call them in this way:
create ( &head, ¤t );
insert ( &head, ¤t );
because otherwise the changes made to head and current do not get reflected in the values of head and current because C has call by value semantics (and call by reference is emulated by using pointers). So, the current = malloc(...); and head = current; lines don't actually change the current and head pointers in the main function, just the local variables.
Then, you need to access them in this style:
*current = malloc(sizeof(struct node));
(*current) -> number = a;
(*current) -> next = NULL;
*head = *current;
which would be part of the code of the create function.
You're also not actually updating the next link of current node in insert. So, instead of:
current = malloc(sizeof(struct node));
current -> number = b;
current -> next = NULL;
Try this:
(*current)->next = malloc(sizeof(struct node));
*current = (*current)->next;
(*current) -> number = b;
(*current) -> next = NULL;
I also see a problem in your code that you don't check the return value of malloc. You should never assume that memory allocation is always successful. Handle the NULL return from malloc by printing a descriptive error message and exiting your program.
Two major faults:
You have not initialiased the list pointers in main() so their values are effectively random.
You are passing copies of these variables to the create() and insert() functions. These functions have no effect, because the copies are thrown away when the functions return.
The result is when you try to display() the list, you get a crash, as you are passing the still uninitialised pointers.
UPDATE
Here is a revision to your program. The insertion, display and freeing are recursive. Rather than pass a double pointer for the insert() function to modify, it returns the new head of the list. Note that creating the empty list needs no more than setting its pointer to NULL. Also, please see that display() is simpler.
#include <stdio.h>
#include <stdlib.h>
struct node {
int number;
struct node *next;
};
struct node *insert (struct node *head) {
// return new list pointer
int b = 0;
struct node *current;
printf("Insert: ");
if (1 != scanf("%d", &b) || b == -1)
return head;
current = malloc(sizeof(struct node));
if (current == NULL) {
printf("Bad malloc!\n");
exit (1);
}
current->number = b;
current->next = head;
return insert(current);
}
void display (struct node *list) {
if (list) {
printf("%d \t", list->number);
display(list->next);
}
}
void free_list (struct node *list) {
if (list) {
free_list(list->next);
free(list);
}
}
int main(void) {
struct node *head = NULL;
head = insert (head);
printf("List is: ");
display(head);
printf("\n");
free_list (head);
return 0;
}
Program output:
Insert: 1
Insert: 2
Insert: 3
Insert: 4
Insert: -1
List is: 4 3 2 1
Some minor problems dealt with: not checking the return value from scanf() or from malloc(). It might seem a bore to do this, but in time you will value the routine of checking everything that you do, since most of the language checking in C happens at compiler time, not at run time. At runtime, there is very little protection.
i am trying to create a singly link list but while displaying it stores the last entered value only the first entered value goes missing
for ex:
if i am entering 1 node or 1 element it works fine but as soon as i enter 2 elements it displays only the last entered value the first value goes missing.
#include<stdio.h>
#include<stdlib.h>
struct node
{
int data;
struct node *next;
};
struct node *create(struct node *head,int data)
{
if(head->next==NULL)
{
head->data=data;
head->next=NULL;
}
else
{
head=head->next;
head->data=data;
head->next=NULL;
}
return head;
}
void display(struct node * head)
{
while(head!=NULL)
{
printf("%d",head->data);
head=head->next;
}
}
main()
{
struct node *head=(struct node*)malloc(sizeof(struct node)),*head1;
int n,data,i;
printf("\n enter how many elements ");
scanf("%d",&n);
for(i=0;i<n;i++)
{
printf("enter data");
scanf("%d",&data);
head=create(head,data);
}
display(head);
}
That is because head in main() is re-assigned to the new, last, element all the time.
There will only ever be one element in your linked list since the only time an element is created is in the first line in your main method.
In the create() function, malloc() a new element and assign head->next to its value, then populate it with data.
struct node *create(struct node *element, int data)
{
if (element)
{
while(element->next)
{
element = element->next;
}
element->next = malloc(sizeof(struct node));
element = element->next;
}
else
{
element = malloc(sizeof(struct node));
}
element->data = data;
return element;
}
Now, do not reassign head to the returned value from the call to create() in main(), but if you later want to optimize for some reason, you could always save a tail pointer and use that as the parameter to create(), so that you will not have to traverse the entire list each time.
Also, not that I haven't compiled this, so there may be some syntactic errors...
Use the below linked list create function and get the required result.
To solve that you need to assign struct node *head=NULL and use the below create function.
Create Function:
struct node *create(struct node *head,int value)
{
struct node *temp;
/* updated code start */
if(head == NULL)
{
head=(struct node *)malloc(sizeof(struct node));
temp->data=value;
temp->next=NULL;
}
else
{
/*Updated code ends */
temp=head;
while(temp->next != NULL)
temp=temp->next;
temp->next=(struct node *)malloc(sizeof(struct node));
if (temp->next !=NULL)
{
temp=temp->link;
temp->data=value;
temp->next=NULL;
}
}
return head;
}
Update:
Due to memory allocation unable to find whether the first position is empty or not.
we can also do something in for statement before calling the create function, like
if(i==0)
{
head->data=value;
head->next=NULL;
continue;
}
The above code is also one of the way to do the same thing with the existing code.