Can't Solve Infinite Loop - c

The program is supposed to take a user entered integer and convert it into binary through a stack of singly linked lists. I think it's either my toBin() function or my printStack() function that's causing the infinite loop.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
typedef struct node_def node;
struct node_def
{
int val;
node *next;
};
node *head;
void push(int val);
void pop(node *head);
int top();
void printStack();
int toBin(int val);
int main()
{
int num = 0;
printf("Enter an integer: ");
scanf("%d", &num);
push(num);
toBin(num);
printStack();
return 0;
}
void push(int val)
{
node *new;
new = malloc(sizeof(node));
if (head == NULL)
{
head = malloc(sizeof(node));
head->next = NULL;
head->val = val;
}
else
{
new->next = head;
new->val = val;
head = new;
}
return;
}
void pop(node *head)
{
node *tmp;
if(head == NULL)
{
printf("Stack is Empty\n");
return;
}
else
{
tmp = head;
head = head->next;
free(tmp);
}
return;
}
int top()
{
return(head->val);
}
void printStack()
{
node *tmp;
tmp = head;
if(head == NULL)
{
return;
}
while(head != NULL)
{
printf("%d ", head->val);
head = head->next;
}
printf("\n");
return;
}
int toBin(int val)
{
pop(head);
int i = 1, remainder, binary;
while(val != 0)
{
remainder = val % 2;
binary = binary + remainder * i;
val = val / 2;
i = i * 10;
push(binary);
}
return val;
}

You run into an infinite loop due to not properly initialising your variables. In particular, you have no guarantees that your node* head will be initialised to NULL, or that your int variables in toBin() will be initialised to zero.
Always, always, always initialise your variables when programming in C/C++.
Fixing these bugs and removing unused code leaves us with:
#include <stdio.h>
#include <stdlib.h>
typedef struct node_def node;
struct node_def
{
int val;
node *next;
};
/* Note that we are initialising the global variable to NULL. */
node *head = NULL;
void push(int val);
void printStack();
int toBin(int val);
int main()
{
int num = 0;
printf("Enter an integer: ");
scanf("%d", &num);
/* Removed push(num), as you're using parameters in the following call: */
toBin(num);
printStack();
return 0;
}
/* Changed printStack to use a tmp pointer to
traverse the stack without mutating it */
void printStack()
{
node* tmp = head;
while(tmp != NULL)
{
printf("%d ", tmp->val);
tmp = tmp->next;
}
printf("\n");
return;
}
int toBin(int val)
{
/* Removed pop() as you're getting val from parameters */
/* Also initialising remainder and binary variables */
int i = 1, remainder = 0, binary = 0;
while(val != 0)
{
remainder = val % 2;
binary = binary + remainder * i;
val = val / 2;
i = i * 10;
push(binary);
}
return val;
}
/* It's a stack so no if's are necessary for pushing */
void push(int val)
{
node *new = malloc(sizeof(node));
new->val = val;
new->next = head;
head = new;
return;
}

Related

Linked list unable to print all elements

I'm trying to print the linked list to which I prompt for user input.
This code below is not printing the whole list, only the last element at a time.
I don't seem to find the bug. Can you please take a look at it?
#include <stdio.h>
#include <stdlib.h>
struct Node {
int data;
struct Node *next;
};
struct Node *head;
void Insert(int x) {
struct Node *temp = (struct Node *)malloc(sizeof(struct Node));
temp->data = x;
temp->next = NULL;
head = temp;
};
void Print() {
struct Node *temp = head;
printf("Linked list is: ");
while (temp != NULL) {
printf("%d ", temp->data);
temp = temp->next;
}
printf("\n");
};
int main() {
head = NULL;
int i, x;
for (i = 1; i <= 10; i++) {
if (i == 1) {
printf("Enter 1st number: \n");
} else if (i == 2) {
printf("Enter 2nd number: \n");
} else {
printf("Enter %dth number: \n", i);
}
scanf("%d", &x);
Insert(x);
Print();
}
}
temp->next = NULL; is the culprit. It should be temp->next = head;.
Another (more cornercase) issue is that your code fails to check for errors in malloc and scanf.
Edit in response to comment:
If you want to append (as opposed to prepend), you'll need to keep a tail pointer for forward traversal and then either use a dummy first node (avoids a branch) or special-case an insert to an empty list.
Example of both (with simplistic error handling via exit(1)) in one piece of code:
#include <stdio.h>
#include <stdlib.h>
struct Node {
int data;
struct Node *next;
};
#define DUMMYFIRST 1 //change to 0 to compile the other variant
#if DUMMYFIRST
struct Node dummyfirst;
struct Node *head=&dummyfirst;
#else
struct Node *tail,*head=0;
#endif
void Insert(int x) {
struct Node *newnode = malloc(sizeof(struct Node));
//don't cast the result of malloc in C
//https://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc
if(!newnode) { perror("malloc"); exit(1); }
newnode->data = x;
newnode->next = 0;
#if !DUMMYFIRST
if(!tail) tail = head = newnode;
else head->next = newnode;
#else
head->next = newnode;
#endif
head = newnode;
};
void Print() {
#if DUMMYFIRST
struct Node *newnode = dummyfirst.next;
#else
struct Node *newnode = tail;
#endif
printf("Linked list is: ");
while (newnode != NULL) {
printf("%d ", newnode->data);
newnode = newnode->next;
}
printf("\n");
};
int main() {
int i, x;
for (i = 1; i <= 10; i++) {
if (i == 1) {
printf("Enter 1st number: \n");
} else if (i == 2) {
printf("Enter 2nd number: \n");
} else {
printf("Enter %dth number: \n", i);
}
if(1!=scanf("%d", &x)) exit(1);
Insert(x);
Print();
}
}
A more library friendly approach to handling errors would be to propagate the error to the caller, i.e., instead of exiting with an error message right away, you'd change the return value from void to something indicating the error, e.g. so that the caller could check and decide what to do (print it, print it in a localized version, try a different algorithm...)
E.g.:
struct Node *Insert(int x) {
struct Node *newnode = malloc(sizeof(struct Node));
//don't cast the result of malloc in c
//https://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc
if(!newnode) return NULL;
//...
};
//...
//calling code:
if(!Insert(x)) perror("Insert"),exit(1);
When you insert the new node, you do not link the rest of the list, instead of temp->next = NULL; you should write
temp->next = head;
To ensure defined behavior, you should check for memory allocation failure and invalid input.
Also remove the dummy ; after the function bodies.
Here is a modified version:
#include <stdio.h>
#include <stdlib.h>
struct Node {
int data;
struct Node *next;
};
struct Node *head;
int Insert(int x) {
struct Node *temp = malloc(sizeof(*temp));
if (temp) {
temp->data = x;
temp->next = head;
head = temp;
return 1;
} else {
return 0;
}
}
void Print(void) {
struct Node *temp = head;
printf("Linked list is: ");
while (temp != NULL) {
printf("%d ", temp->data);
temp = temp->next;
}
printf("\n");
}
int main() {
static char suffix[4][3] = { "th", "st", "nd", "rd" };
int i, x;
for (i = 1; i <= 10; i++) {
int suff = (i >= 1 && i <= 3) ? i : 0;
printf("Enter %d%s number:\n", i, suffix[suff]);
if (scanf("%d", &x) != 1) {
fprintf(stderr, "invalid or missing input\n");
break;
}
if (!Insert(x)) {
fprintf(stderr, "cannot allocate memory for Node\n");
return 1;
}
Print();
}
return 0;
}

Stack push function using c, implemented using doubly linked list

I am trying to implement Hierholzer's algorithm using C.
I have made a push function for a simple stack implemented using doubly linked list but the pointer always moves on to the else condition, even when the starting node is empty.
#include<stdio.h>
#include<malloc.h>
#include<stdlib.h>
#include<string.h>
#include<ctype.h>
#include<stddef.h>
typedef struct node
{
int source;
int num;
struct node *l, *r;
int done;
}node;
void push(int source, int num, struct node *head)
{
node *n = malloc(sizeof(node));
n->num = num;
n->l = NULL;
n->done = 0;
n->source = source;
if (*head == NULL)
{
head = n;
head -> r = NULL;
}
else
{
n -> r = head;
head->l = n;
head = n;
}
}
int pop(node *head)
{
if(head == NULL)
{
return -1;
}
else
{
node *temp = head;
head = head->r;
int num = temp->num;
free(temp);
return num;
}
}
void append(node *extra, node *head)
{
node *temp = extra;
while(temp->r != NULL)
{
temp = temp->r;
}
temp->r = head;
head->l = temp;
head = extra;
}
node** read(int num)
{
char a[2000] = "Assignment1.txt" ,c[1000];
FILE *f = fopen(a,"r");
printf("Got file\n");
node *adj[num];
int i=0;
node *l;
printf("l: %d\n", l);
while(fscanf(f,"%s",c))
{
char *p = strtok(c, ",");
while(p!=NULL)
{
push(i, atoi(p), l);
p = strtok (NULL, ",");
}
adj[i++] = l;
}
printf("Adjacency list created\n");
return adj;
}
node* euler(node *adj[],int n, int i)
{
node *cpath = NULL;
node *fin = NULL;
node *extra;
node *temp = adj[i];
node *tempi;
while(temp!=NULL)
{
if(temp->r->r == NULL)
{
tempi = temp;
}
if(temp->done == 0)
{
temp->done = 1;
push(i, temp->num, cpath);
extra = euler(adj, n, temp->num);
append(extra, cpath);
}
else
{
temp = temp->r;
}
}
while(tempi->l != NULL)
{
push(i,tempi->num, fin);
extra = euler(adj, n, tempi->num);
append(tempi, fin);
tempi = tempi->l;
}
if(tempi != NULL)
{
push(i,tempi->num, fin);
extra = euler(adj, n, tempi->num);
append(tempi, fin);
}
return fin;
}
int main()
{
int n;
printf("Enter the number of vertices: ");
scanf("%d", &n);
node **adj = read(n);
node *fin = euler(adj, n, 0);
node *temp = fin;
while(temp!=NULL)
{
printf("%d ", temp->num);
temp = temp->r;
}
return 0;
}
I am yet to debug the entire code but I am getting stuck at the read() function where the input is an Assignment1.txt which includes:
2,3
3,1
1,2
I am not able to understand why I am getting a segmentation fault.
The function deals with a copy of the value of the passed to it pointer to the head node. So the original pointer itself is not changed in the function. It is the copy of the value of the passed pointer that is changed within the function.
You need to pass the pointer by reference that is indirectly through pointer to the pointer.
The function can be declared and defined the following way.
int push( struct node **head, int source, int num )
{
node *n = malloc(sizeof(node));
int success = n != NULL;
if ( success )
{
n->source = source;
n->num = num;
n->done = 0;
n->l = NULL;
n->r = *head;
if ( *head != NULL ) ( *head )->l = n;
*head = n;
}
return success;
}
In read function you are returning adj. However, it is a local variable. You are not using malloc type function. So, local variables destroy after function returned. Therefore, you are trying to access a random place when you try to access adj in main. I guess the problem is caused by this reason.

How to overcome segmentation error while performing addition of 2 singly-linked lists?

In this code below ,i have got numerals as input,and send the odd numbers to list1 and sent the even numbers to list2.Finally,i have added the values in list1 & list2 and stored them in list3.But i am getting segmentation error.please help me
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
struct node//list creation
{
int data;
struct node *next;
};
struct node *list1;
struct node *list2;
struct node *list3;
/*creating list*/
void create(struct node *l, int x)
{
l->data = x;
l->next = NULL;
}
/* adding elements to list*/
void addlast(struct node *li, int x)
{
struct node *temp = NULL;
temp = (struct node *) malloc(sizeof(struct node));
temp->data = x;
while (li->next != NULL)
li = li->next;
li->next = temp;
temp->next = NULL;
}
/* printing values */
void print(struct node *lb)
{
if (lb == NULL)
printf("empty");
else
{
while (lb->next != NULL)
{
printf(" % d->", lb->data);
lb = lb->next;
}
printf(" % d->", lb->data);
}
}
/* performing addition */
void add(struct node *l1, struct node *l2)
{
int value, c = 0;
while (l1->next != NULL || l2->next != NULL)
{
value = l1->data+l2->data;
if (c == 0)
{
create(list3, value);
c++;
}
else
{
addlast(list3, value);
}
l1 = l1->next;
l2 = l2->next;
}
printf("list3");
print(list3);
}
int main()
{
int i, n, a[20], c1 = 0, c2 = 0;
list1 = (struct node *) malloc(sizeof(struct node));
list2 = (struct node *) malloc(sizeof(struct node));
list3 = (struct node *) malloc(sizeof(struct node));
printf("\n Enter the number of numbers");
scanf("%d", &n);
for (i = 0; i < n; i++)
{
scanf("%d", &a[i]);
if (a[i] % 2 == 0)
{
if (c1 == 0)
{
create(list1, a[i]);
c1++;
}
else
addlast(list1, a[i]);
}
if (a[i] % 2 != 0)
{
if (c2 == 0)
{
create(list2, a[i]);
c2++;
}
else
addlast(list2, a[i]);
}
}
printf("list1");
print(list1);
printf("\n");
printf("list2");
print(list2);
add(list1, list2);
return 0;
}
The problem is your while loop condition in the add. You should check if either l1->next or l2->next is null. Here is the corrected version.
/* performing addition */
void add(struct node *l1, struct node *l2)
{
int value, c = 0;
//you can only add if the two lists have same number of elems
while (l1->next != NULL && l2->next != NULL)
{
value = l1->data + l2->data;
if (c == 0)
{
create(list3, value);
c++;
}
else
{
addlast(list3, value);
}
l1 = l1->next;
l2 = l2->next;
}
//if lists dont have equal number of elements
//find the list which is not empty and append the
//elems to l3 here
printf("list3");
print(list3);
}

C program reversed linked list

Im trying to write a program in c that adds big numbers with linked list. I used reverse to add the numbers, but i cant get it to reverse again. It should be used several times(iow, looped to ask numbers until exit)
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "function.c"
int main()
{
char n1[500];
int lenSum, len;
printf("Welcome! \nThis program performs addition of big whole numbers that can contain upto a maximum of 500 digits.");
printf("\nEnter first number: ");
scanf("%s", n1);
len = strlen(n1);
node *root = create(n1[0]);
node *head = root;
root, head = createList(n1,root,head,len);
root=head;
printf("Enter second number: ");
scanf("%s", n1);
len = strlen(n1);
node *root2 = create(n1[0]);
node *head2 = root2;
root2, head2 = createList(n1,root2,head2,len);
root2=head2;
root=head;
printf("\nYour first number is:\t ");
while(root!=NULL){
printf("%d\t",root->digit);
root=root->next;
}
root2=head2;
printf("\nYour second number is: ");
while(root2!=NULL){
printf("%d\t",root2->digit);
root2=root2->next;
}
printf("\nCalculating sum:\n");
root=head;
root2=head2;
node *sum = create('0');
node *headSum = sum;
sum,headSum = addIntegers(root, root2, sum, headSum);
printf("\nThe sum is : ");
sum=headSum;
while(sum->next!=NULL){
printf("%d",sum->digit);
sum=sum->next;
}
printf("\n");
sum = headSum;
printf("\nThe number ");
saveResult(sum);
printf("has been saved in the file 'results.txt'\n");
root, head = reverseLinkedList(sum, headSum);
printDigit(root);
root=head;
printf("\n\n\t ");
while(root!=NULL){
printf("%d\t",root->digit);
root=root->next;
}
free(root);
free(root2);
//free(sumDigit);//
return 0;
}
function.h:
#ifndef function.h
#define function.h
typedef struct node {
int digit;
struct node *next;
}node;
node* create(char digit);
node* createList(char number[500], node* root,node* head, int length);
node* addIntegers(node* root, node* root2, node* sum, node* headSum);
#endif
function.c:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "function.h"
node* createList(char number[500], node* root,node* head, int length){
int i;
i=0;
for(i=1;i<=length-1;i++) {
root = (node *)malloc(sizeof(node));
root->digit = number[i]-'0';
root->next = head;
head = root;
}
return root, head;
}
void printDigit(node* root){
while(root!=NULL){
printf("%d",root->digit);
root=root->next;
}
}
node* addIntegers(node* root, node* root2, node* sum, node* headSum){
int carry = 0;
int sumDigit = 0;
while((root!=NULL || root2!=NULL)) {
if (root==NULL || root2==NULL){
if (root == NULL){
sumDigit=root2->digit +carry;
root2=root2->next;
goto add;}
if (root2 == NULL){
sumDigit = root->digit + carry;
root=root->next;
goto add;
}
}
else{
sumDigit = root->digit + root2-> digit + carry;
}
root2 = root2->next;
root = root->next;
add:
sum = (node *)malloc(sizeof(node));
sum->digit = sumDigit%10;
sum->next = headSum;
headSum = sum;
if (sumDigit > 9){
carry = 1;}
else{
carry = 0;
}
}
if (carry == 1){
sum = (node *)malloc(sizeof(node));
sum->digit = 1;
sum->next = headSum;
headSum = sum;
}
return sum, headSum;
}
node* create(char digit)
{
node *root = (node *) malloc( sizeof(node));
if (root == NULL){
printf("ERROR\n");
exit(1);
}
root->digit = digit-'0';
root->next = NULL; //default is null
return root;
}
void saveResult(struct node *sum)
{
FILE * fp = fopen ("result.txt", "w+");
while(sum->next != NULL)
{
printf("%d", sum->digit);
fprintf(fp, "%d", sum->digit);
sum = sum->next;
}
fclose(fp);
printf(" ");
}
node* reverseLinkedList(node *root, node* head){
node* reversed = create(root->digit);
node* reversedTail = reversed;
while(root!=NULL){
//printf("%d", root->digit);
root = root->next;
reversed->digit = root;
reversed->next =head->next;
reversed = reversed->next;
head = root;
}
reversed = reversedTail;
return reversed, reversedTail;
}
As the question is not very specific with the issue you're are facing, below are some points to be taken care,
In function reverse(),
return reversed, reversedTail; will always return reversedTail.
You are trying to call this function from main() as
root, head = reverseLinkedList(sum, headSum); which again head will get the return values. This is incorrect. Usually you should be using a assignment to one member at a time.
link list reverse sample like this
#include <stdio.h>
#include <stdlib.h>
typedef struct node {
int digit;
struct node *next;
} node;
node *reverse_copy(node *list){
node *new_list = NULL;
while(list){
node *new_node = malloc(sizeof(node));
new_node->digit = list->digit;
new_node->next = new_list;
new_list = new_node;
list = list->next;
}
return new_list;
}
void reverse_not_copy(node **header){
node *tmp, *list, *newList = NULL;
if (header==NULL || *header == NULL) return;
list = *header;
while(list != NULL){
tmp = list;
list = list->next;
tmp->next = newList;
newList = tmp;
}
*header = newList;
}
void print(node *head){
while(head){
printf("%d ", head->digit);
head = head->next;
}
printf("\n");
}
int main(void){
node *np;
node n[3] = { {1,NULL}, {2, NULL}, {3, NULL}};
n[0].next = &n[1];
n[1].next = &n[2];
print(&n[0]);//1 2 3
np=reverse_copy(&n[0]);
print(np);//3 2 1
reverse_not_copy(&np);
print(np);//1 2 3
return 0;
}

Popping & Getting Value From Multi-Type Stack

I have a Stack (implemented using a linked list structure) that contains two types: char * (holds values of the strings) & double (holds values of the numbers).
I have a Pop function which is void that pops the top value off the stack. But I want to also have access to that value.
But I can't figure out how to do that since I cant do a function overload in C which will allow me to have two Pop functions (one of type char * & the other of type double) that return their respective types. Does anybody know of another way to go about this?
Here's My Code Thus Far:
#include <stdio.h>
#include <conio.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
#include <ctype.h>
typedef struct stack
{
char *valC;
double valNum;
struct stack *next;
}node;
node *head = NULL;
int isnumber(char *str)
{
int i;
for (i = 0; str[i] != '\0'; i++)
{
if (!isdigit(str[i]))
return (0);
}
return (1);
}
node *get_node(void *item)
{
node *temp;
temp = (node*)malloc(sizeof(node));
if (temp == NULL) printf("Memory Cannot Be Allocated");
temp->valC = item;
temp->next = NULL;
return (temp);
}
void Push (char *Item, double num, node **head)
{
node *New = (node*)malloc(sizeof(node));
if (New == NULL) printf("Memory Cannot Be Allocated");
New->valNum = num;
New->valC = Item;
//node *get_node(void*);
//New = get_node(Item);
New->next = *head;
*head = New;
}
int Sempty (node *temp)
{
if(temp == NULL)
return 1;
else
return 0;
}
void Pop (node **head)
{
char *item;
double itemN;
node *temp;
node *prev = (node*)malloc(sizeof(node));
//item = (*head)->valC;
//itemN = (*head)->valNum;
temp = *head;
prev->next = temp;
*head = (*head)->next;
free(temp);
if (prev->valC != NULL)
{
return (prev->valC);
}
else if (prev->valNum > 0)
{
return (prev->valNum);
}
}
double PopN (node **head)
{
double itemN;
node *temp;
itemN = (*head)->valNum;
temp = *head;
*head = (*head)->next;
free(temp);
return(itemN);
}
void Display (node **head)
{
node *temp;
temp = *head;
char *error;
if(Sempty(temp)) {
printf("Empty Stack!\n");
error = "::error::\n";
Push(error, 0, &temp);
}
else
{
while (temp != NULL)
{
if (temp->valC != NULL) printf("%s\n", temp->valC);
if (temp->valNum > 0) printf("%f\n", temp->valNum);
temp = temp->next;
}
}
}
void main()
{
node *inp = (node*)malloc(sizeof(node));;
while(1)
{
printf("repl> ");
char *storage [30];
char *tok;
double my_double;
char buffer[50];
int pos = 0;
fgets(buffer,sizeof(buffer),stdin);
tok = strtok(buffer," ");
while (tok != NULL)
{
if (strcmp(tok, "add") == 0) printf("YES!!");
else if (strcmp(tok, "add\n") == 0) printf("YELZZ!!!");
if (strcmp(tok, "quit") == 0) exit(1);
else if (strcmp(tok, "quit\n") == 0) exit(1);
if (strcmp(tok, "pop") == 0)
{
Pop(&head);
break;
}
else if (strcmp(tok, "pop\n") == 0)
{
Pop(&head);
break;
}
if (sscanf(tok, "%lf", &my_double) > 0)
{
Push(NULL, my_double, &head);
}
else
Push(strdup(tok), 0, &head);
//if(Sempty(head)) Push("::error::", 0, &head);
tok = strtok(NULL," ");
}
Display(&head);
}
}
You cannot overload functions in C. You already have a Pop function that pops the topmost node from the stack. The node can either contain a number or a string. Your Display function displays the content of the node and tests correctly what kind of data is in the node.
You should write a function that takes a node as argument and return say false if it's a number and true if it's a string:
bool IsString(node *inp)
{
return temp->valC != NULL ;
}
But even if you could overload functions in C, you don't know what type of node (number or string) is on the top of the stack. What would happen if the you call Pop function that returns a string and the topmost node contains a number ?
Just do the pop, and then find out if the node is a string or a number and act accordingly.
one thing you can do is to written a pointer, of type void * then you can type cast it to your required type later.
i'll give an example, you can get idea from it to implement pop()
void *check(int x)
{
static void *p;
int a=5;
char *c="abcd";
if(x==1)
return p=&a;
else
return p=c;
}
int main()
{
int * a;
char * b;
a=(int *)check(1);
b=(char *)check(2);
printf("%d %s",*a,b);
}
for your pop() you can even add as flag as parameter to know the type of returned pointer to type cast in calling function. as
void * pop(node **head, int &flag)
set flag to indicate type of returned pointer.

Resources