How to Reverse singly linked list properly in C? [duplicate] - c

This question already has answers here:
How to reverse a singly linked list using only two pointers?
(36 answers)
Closed 7 years ago.
well im starting with C and i've been asked to do a linked list that has random integers in its nodes data, they must be in ascendant order and later i have to reverse their order with a function. The problem im having is that in my reverse output, im only getting the first number and its not even reversed.
#include <stdio.h>
#include <stdlib.h>
int N;
typedef struct node{
int num;
struct node *next;
}nodes;
int first_node(nodes *head){
if(head == NULL){
printf("Error");
}
else{
head -> num= rand();
head->next=NULL;
}
}
int second_node(nodes *head){
nodes *uno=malloc(sizeof(nodes));
if(uno == NULL){
printf("Error");
}
else{
uno->num = rand();
uno->next = NULL;
if( uno->num>head->num){
head->next=uno;
}
else{
head= uno->next;
}
}
}
int insert_node(nodes *head){
nodes *dos=malloc(sizeof(nodes));
if(dos == NULL){
printf("Error");
}
else{
dos->num = rand();
dos->next = NULL;
nodes *current = head;
while(current!= NULL){
if(current->num<dos->num && current->next==NULL){
current->next = dos;
return;
}
else if (current->num<dos->num && current->next->num>dos->num){
dos->next=current->next;
current->next=dos;
return;
}
else if(head->num>dos->num){
dos->next=head;
head=dos;
}
current=current->next;
}
}}
void printnodes(nodes *head){
nodes *current = head;
while (current != NULL){
printf("%d\n",current->num);
current = current ->next;
}
}
void reverse(nodes *head)
{
nodes *a=head->next;
if(a!=NULL)
{
nodes *b=a->next;
a->next=head;
head->next=NULL;
head=a;
if(b!=NULL)
{
while(b!=NULL)
{
a=b;
b=b->next;
a->next=head;
head=a;
}
a->next=head;
head=a;
}
}
}
int main(){
printf("Insert the number of nodes u want to create:");
scanf("%d", &N );
nodes *head =malloc(sizeof(nodes));
int i =3;
if(N==1){
first_node(head);
}
else if (N ==2){
first_node(head);
second_node(head);
}
else if (N>2){
first_node(head);
second_node(head);
while(i<=N){
insert_node(head);
i++;
}
}
printnodes(head);
printf("\n\n Reversed \n\n");
reverse(head);
printnodes(head);
return 0;
}
The output im getting creating 5 nodes is :
In order:
41
3445
3890
8709
16777
Reversed :
41
how can i fix this?, thanks and sorry for the bad english

There are two very obvious problems in your code:
The first is that you assign to a local variable, expecting that assignment to be reflected once the function returns. I'm talking about your assignment to head in most functions. The problem here is that when you pass an argument to a function. it's passed by value, meaning it's copied and what you have in the function you call is just a copy or the original value. And as you should know, changing a copy will not change the original.
The second problem that I see at a quick glance is in the second_node function, where you first do
uno->next = NULL;
and potentially followed by
head= uno->next;
This will assign NULL to head.
The first problem is easy to solve, by emulating something called pass by reference. I say emulating, as C only have pass by value. You can emulate pass by reference in C using pointer, which means that to pass a pointer "by reference" in C, you have to pass a pointer to the pointer, like
int second_node(nodes **head){
...
}
You then call it using the address-of operator:
second_node(&head);
Then in second_node you use the dereference operator * to access the "original" head pointer, like
*head = uno->next;
Writing the above I noticed a third problem, and that is that you declare some functions as returning an int, but you don't actually return anything from the functions. Thankfully it seems that you don't use the returned value anywhere, but it's still is undefined behavior to not return a value in a function that should return a value. If you should not return a value from a function it must be declared as returning void:
void second_node(nodes **head){...}

Related

Problem deleting the only node from a linked list

I am trying to create a function to delete a certain node if its value matches the value entered by the user. I created a case if there is only a single node, but after deleting the node with free(curr_node) and calling traverse function, the cmd prints out numbers endlessly. What am I missing?
typedef struct Node {
int data;
struct Node *next;
}Node;
Node *head = NULL;
int node_number = 0;
void traverse(Node *head, int count) {
int i = 1;
if(head == NULL) {
printf("No nodes to traverse!");
return;
}
printf("%d node(s), with their respective value: \n", count);
while(head != NULL) {
if(i == count)
printf("%d\n", head->data);
else
printf("%d-", head->data);
head = head->next;
i++;
}
}
void delete_item(Node *head) {
Node *curr_node = head;
int value;
printf("Enter value to search by: ");
scanf("%d", &value);
while(curr_node != NULL) {
if(curr_node->data == value) {
if(curr_node->next == NULL) {
free(curr_node);
head = NULL;
printf("Node deleted successfully!\n");
return;
}
}
//curr_node = curr_node->next;
}
}
Node *create_item() {
Node *result = NULL;
result = (Node *)malloc(sizeof(Node));
if(result == NULL) {
printf("Couldn't allocate memory!");
return 0;
}
printf("Value of node %d: ", node_number + 1);
scanf("%d", &result->data);
result->next = NULL;
node_number++;
return result;
}
int main() {
int nodes;
Node *temp;
head = create_item();
delete_item(head);
traverse(head, node_number);
return 0;
The change to head is not captured by the caller. The fact is, head is actually a local variable to delete_node, and any changes to it (not to be confused with changed through it using deference operations), are not being captured by the caller.
All function arguments in C are by-value. Some will say "that's not true for arrays"; they're wrong. Used in an expression, the "value" of an array is defined by the language standard as a temporary pointer referring to the address of the first element. I.e. still by-value, its just the value isn't what you may expect. But in your case, head is by value. If you had a function void foo(int x) you already know that modifying x within foo does not change the caller's int they passed; the same is true here. Just because its a pointer makes no difference. If you want to modify a caller-argument you have to build the road to get there.
There are two general schools around this.
Use a pointer to pointer argument and pass the address of head in main. This requires deference of the pointer-to-pointer to get the actual list head, but also allows you to modify the callers pointer.
Use the return result of the function to communicate the current list head back to the caller (i.e. the head after whatever operation is being performed.
The first is more complicated, but allows you to use the return result for other purposes (like error checking, hint). The latter is easier to implement. Both will accomplish what you want. The former is shown below:
void delete_item(Node **head)
{
int value;
printf("Enter value to search by: ");
if (scanf("%d", &value) == 1)
{
while (*head)
{
if ((*head)->data == value)
{
void *tmp = *head;
*head = (*head)->next;
free(tmp);
printf("Node deleted successfully!\n");
break;
}
head = &(*head)->next;
}
}
}
The caller, main in this case, needs to be modified as well:
delete_item(&head); // <== note passed by address now.

Address of a node in linked list changes automatically in c

I am learning pointers in c and wrote a program which inserts elements into linked list and prints them in the end.
// this is exercise 2 in chapter 11 on pointers
#include <stdio.h>
#include <stdbool.h>
typedef struct node
{
int value;
struct node * next;
}node;
/**
Insert into linked list
**/
bool insert(node * list, int n);
void printList(node *startNode);
int main(void)
{
node n1,n2;
n1.value = 0;
n2.value = 1;
n1.next = &n2;
n2.next = NULL;
// insert 2 into list
insert(&n1, 2);
// print the updated list
printList(&n1);
printf("Program Executed Successfully \n");
return 0;
}
bool insert(node * list, int n)
{
while(list->next != NULL)
{
if (list->value < n)
{
list = list->next;
}
else
{
node tempNode;
tempNode.value = n;
tempNode.next = list->next;
list->next = &tempNode ;
return true;
}
}
node tempNode;
tempNode.value = n;
tempNode.next = list->next;
list->next = &tempNode ;
return false;
}
void printList(node * startNode)
{
while(startNode->next != NULL)
{
printf("%i\n", startNode->value);
startNode = startNode->next;
}
}
Insertion seems to be fine. I have initially two nodes and then I added one more with a value of 2 but when I print, it just prints the first two elements correctly.
I used GDB debugger and tried to trace where the problem occurs, i saw that when it has printer first and second node, the address of the third node has automatically changed to
0x7ffff7dea560 <_dl_fini>
before at the start of the print function it was
0x7ffffe018
and the output of the complete program is
0
1
-777224576
-443987883
Segmentation fault
The insert function just looks wrong, but the worst offenders are these lines from the function:
else
{
node tempNode;
...
list->next = &tempNode ;
}
Here you declare a local variable `tempNode, and save a pointer to it in the list. The variable will go out of scope and cease to exist once the closing curly brace is reached, leaving you with a stray pointer. Attempting to dereference that stray pointer will lead to undefined behavior.
A little further down you do the same mistake again, saving a pointer to a local variable.

Singly linked list in C(Inserting a node)

I have this problem when I input. The program will freeze and a pop out window will open and says " .exe has stopped working. "
It is just a simple insert and display fuction of a singly linked list. I tried everything. I rewrote the code and find another way of inserting. I tried different compiler.. It works on turbo C but I am using devC++.
Is this a compiler error?
Here is the code:
#include <conio.h>
#include <stdio.h>
#include <stdlib.h>
#include<windows.h>
#include <string.h>
typedef struct process
{
int pNum;
struct process *next;
}node;
node *create_node(node x)
{
node *temp;
temp=(node *)malloc(sizeof(node));
if(temp==NULL)
{
return 0;
}
else
{
temp->pNum=x.pNum;
temp->next=NULL;
}
return temp;
}
node *insert_node(node *head,node *last,node x)
{
node *temp;
temp=create_node(x);
if(head==NULL && head==last)
{
head=temp;
last=temp;
head->next=NULL;
last->next=NULL;
}
else
{
last->next=temp;
last=temp;
last->next=NULL;
}
return head;
}
int main()
{
node *head=NULL,*last=NULL,*temp,input;
int i,x,y,num;
printf("INPUT NUMBER: ");
scanf("%d",&num);
x=0;
y=6;
for(i=0;i<num;i++)
{
gotoxy(39,y);
scanf("%d",&input.pNum);
head=insert_node(head, last, input);
y++;
}
getch();
return 0;
}
I think I have found out what line it stopped working.
On the function insert_node
The line last->next=temp;
It seems I can't find what I had done wrong.
You need this:
node *insert_node(node *head, node **last, node x)
{
node *temp;
temp=create_node(x);
if(head==NULL && head== *last)
{
head=temp;
*last=temp;
head->next=NULL;
(*last)->next=NULL;
}
else
{
(*last)->next=temp;
(*last)=temp;
(*last)->next=NULL;
}
return head;
}
Call like this:
head=insert_node(head, &last, input);
Your function needs to modify the last pointer. In C values including pointers are passed by value. So if you modify the function argument inside the function, the argument passed to the function won't be modified. That is what happens in your program.
In the modified we don't pas simpty the lastpointer but we pass a pointer to the last pointer which will allow us to modify the last pointer of the main function.
Simple Example:
int func1(int x)
{
x = 10;
return 2;
}
int func2(int *x)
{
*x = 10;
return 2;
}
...
int x = 3;
printf ("%d\n", func1(x));
printf ("%d\n", x);
printf ("%d\n", func2(&x));
printf ("%d\n", x);
Will print:
2
3
2
10
In your code, after the first entry head pointer will point to new value. Because of you are assigning the return value of that calling function. But last value will not be affect. Because of your are calling that as a pass by value. At
next time head == last will be fail.
It will go to else block, and you are accessing the
last->next=temp;
It is like accessing the null pointer this is the reason. If you need to avoid this you need to call last as pass by reference.

Simple stack program in C

I am in an OS class and I have to write a simple stack program (the main function just determines what the user is asking you to do). If this were not required to be in C, I would have had this done ages ago, but because I am not very good at C coding, it has "a bug"... The bug so far is that it just continues to "pop" the same value off. (It's not actually popping anything off). I think it's because I don't understand how structures and pointers really work. Or is it a not so obvious coding mistake?
#include <stdio.h>
struct node {
int data;
struct node *next;
struct node *prev;
} first;
void push(int);
void pop();
int main(void)
{
int command = 0;
while (command != 3)
{
printf("Enter your choice:\n1) Push integer\n2) Pop Integer\n3) Quit.\n");
scanf("%d",&command);
if (command == 1)
{
// push
int num;
scanf("%d",&num);
push(num);
}
else
{
if (command == 2)
{
pop();
}
else
{
if (command != 3)
{
printf("Command not understood.\n");
}
}
}
}
return 0;
}
void push (int x)
{
struct node newNode;
newNode.data = x;
newNode.prev = NULL;
newNode.next = &first;
first = newNode;
printf("%d was pushed onto the stack.\n", first.data);
}
void pop()
{
if (first.data == '\0')
{
printf("Error: Stack Empty.\n");
return;
}
printf("%d was popped off the stack.\n", first.data);
first = *(first.next);
first.prev = NULL;
}
first should be a pointer. change it to struct node *first;
in main initialize first=NULL;
change you push/pop operations as below,
void push (int x)
{
struct node *newNode;// It should be a pointer
newNode = (struct node *)malloc(sizeof(struct node));
newNode->data = x;
//newNode.prev = NULL; // You don't need this
newNode->next = first;
first = newNode;
printf("%d was pushed onto the stack.\n", first->data);
}
void pop()
{
struct node *prevPtr;
//if (first.data == '\0')
if (first == NULL) // check if stack is empty
{
printf("Error: Stack Empty.\n");
return;
}
printf("%d was popped off the stack.\n", first->data);
prevPtr = first;
first = first->next;
free(prevPtr);
}
The problem is that first is a single global node, and it's the only node you ever have (aside from a temporary local node inside your call to push).
This line:
first = newNode;
just copies the contents of newNode over into first; and since newNode.next is pointing to first, this means that now first.next is pointing to first, so you have a single-element circular linked list.
Similarly, this line:
first = *(first.next);
just copies the contents of *(first.next) over into first; which is a no-op, since (due to the above), *(first.next) is first.
To solve this problem, you actually need to dynamically create nodes, using malloc (and free). And your global first variable should be a pointer — a node * — that always points to the top element of the stack. (Better yet, your push and pop functions should take first as an argument, rather than having this as a global variable. There's no need for these functions to only allow a single stack to exist.)
What's the value of &first? Hint, it's always the same since first is statically allocated. Even if you change the contents of the structure, the address won't change. This might tell you why there's a bug in push. You'll need to use malloc and free if you are going to have a structure of varying size.
When you have to manage memory yourself, as C requires you to do, you need to know the difference between areas of memory known as the stack and the heap. (This "stack" is slightly different than the data structure you are creating in your program.)
Your push() function is creating a new node on the stack; when the function exits the stack is popped and the memory occupied by your new node is up for grabs. The fact that you see values you entered is due to the fact that your program is very simple. If it was calling other functions that did other things they would almost certainly overwrite that part of the stack and when you called pop(), you would see garbage.
As others have indicated, you need to use the functions malloc() and free(), which give you memory from the heap instead of the stack.
If you want to make a stack with a linked list, make first variable as a pointer. then, when you push a new node to the stack, make a new node by allocating on the heap memory by malloc(). I know that you intend to use it to point to the top of the stack. right?
In your code, first variable is overwritten by a new node since it is not a pointer variable but a value variable. That makes a result to lost a top node of the stack.
void pop()
{
struct node *prevPtr;
//if (first.data == '\0')
if (first == NULL)
{
printf("Error: Stack Empty.\n");
return;
}
printf("%d was popped off the stack.\n", first->data);
prevPtr = first;
first = first->next;
free(prevPtr);
}
#include<stdio.h>
# define max 10
int stack[max],top=-1,size=0;
void push()
{
if(top==(max-1))
{
printf("stack full\n");
}
else
{
top++;
printf("enter the value which you want to insert\n");
scanf("%d",&stack[top]);
}
}
void pop()
{
int str;
if(top==-1)
{
printf("stack empty\n");
}
else
{
str=stack[top];
top--;
printf("the removed element is %d\n",str);
}
}
void display()
{
int i;
for(i=0;i<top;i++)
{
printf("%d\n",stack[i]);
}
}
void main()
{
int enter,x;
do
{
printf("enter 1 for push the element in the array\n");
printf("enter 2 for pop the element in the array\n");
printf("enter 3 for display the element in the array\n");
scanf("%d",&enter);
switch(enter)
{
case 1:push();
break;
case 2:pop();
break;
case 3:display();
break;
default:
printf("invalid syntax");
}
printf("for continue press 0\n");
scanf("%d",&x);
}
while(x==0);
}

Trying to delete an element from a double linked list in c

Ι have a problem while trying to delete an element from a double linked list in c.
Nodes_t *remove_Nodes (Nodes_t *a, Nodes_t b){
Nodes_t *head;
head=a;
if ((a->i_pos==b.i_pos) && (a->j_pos==b.j_pos)){
if (a->next=NULL){
return NULL;
}
else {
head=a->next;
head->previous=NULL;
return head;
}
}
else if ((a->i_pos!=b.i_pos) || (a->j_pos!=b.j_pos)){
while ((a->next->i_pos!=b.i_pos)||(a->next->j_pos!=b.j_pos)){
a=a->next;
if (a->next=NULL){
return head;
}
}
a=a->next;
a->previous->next=a->next;
if (a->next=NULL){
return head;
}
else if (a->next!=NULL){
a->next->previous=a->previous;
return head;
}
}
return head;
}
It gets a double linked list, finds an element of type Nodes_t and then deletes it.
Although, as I have checked the list and its pointers work fine, when I try to call the function to delete my first element I get a seg fault.
More specifically, as I have checked, the function proceeds just fine until it gets to this point
else {
head=a->next;
head->previous=NULL;// HERE
return head;
}
The struct I use is this
typedef struct Nodes {
char position;
int i_pos, j_pos;
int g_distance;
int h_distance;
int F_estim;
struct Nodes *parent;
struct Nodes *next;
struct Nodes *previous;
}Nodes_t;
You have used an assignment = instead of a comparison == here:
if (a->next=NULL){
Which will evaluate to NULL, which is false, so will go to your else clause, where you do
head=a->next;
head->previous=NULL;
So head becomes NULL, then you are trying to dereference a NULL pointer to get its previous member.
Quick fix: Add the missing = to the first line I quoted.
Better fix: Refactor your code. It is too long and has unnecessary bits. And don't forget to check your equals operations.

Resources