Adding two integers represented by linked lists - c

The question I came across.
Here is what I have done so far
#include <stdio.h>
#include <stdlib.h>
struct node
{
int digit;
struct node *next;
};
struct node *make_node(int num, struct node *head);
struct node *newNode(int digit);
struct node *sum(struct node *num1, struct node *num2);
void print(struct node *node);
int main()
{
int a, b;
struct node *new_nodeA1 = NULL, *new_nodeA2 = NULL;
struct node *new_nodeB1 = NULL, *new_nodeB2 = NULL;
struct node *res = NULL;
printf("\nEnter no. of digits for your two numbers (separate with space) ");
scanf("%d %d", &a, &b);
int n1[a], n2[b];
printf("\n\nEnter first non-negative integer to add: ");
for (int j = 0; j < a; j++)
scanf("%1d", &n1[j]);
printf("Enter second non-negative integer to add: ");
for (int k = 0; k < b; k++)
scanf("%1d", &n2[k]);
/* for (int i = 0; i <= a - 1; i++)
printf("%d\n", n1[i]);
printf("%d\n", a); */
for (int z = 0; z < a - 1; z++)
{
new_nodeA2 = make_node(n1[z], new_nodeA1);
/*new_nodeA2 = newNode(n1[z]);*/
if (new_nodeA1 == NULL)
new_nodeA1 = new_nodeA2;
}
for (int y = 0; y < b - 1; y++)
{
new_nodeB2 = make_node(n2[y], new_nodeB1);
if (new_nodeB1 == NULL)
new_nodeB1 = new_nodeB2;
}
printf("\n");
print(new_nodeA1);
printf("\n");
print(new_nodeB1);
printf("\n")
res = sum(new_nodeA2, new_nodeB2);
printf("Result: ");
print(res);
return 0;
}
struct node *make_node(int num, struct node *head)
{
struct node *temp = malloc(sizeof(struct node));
if (temp == NULL)
{
fprintf(stderr, "Call of malloc() failed\n");
exit(1);
}
if (head != NULL)
head->next = temp;
temp->digit = num;
temp->next = NULL;
return temp;
}
struct node *newNode(int digit)
{
struct node *new_node = (struct node *) malloc(sizeof(struct node));
new_node->digit = digit;
new_node->next = NULL;
return new_node;
}
struct node *sum(struct node *num1, struct node *num2)
{
struct node *res = NULL;
struct node *temp, *prev = NULL;
int carry = 0, sum;
while (num1 != NULL || num2 != NULL)
{
sum = carry + (num1? num1->digit: 0) + (num2? num2->digit: 0);
carry = (sum >= 10)? 1 : 0;
sum = sum % 10;
temp = newNode(sum);
if(res == NULL)
res = temp;
else
prev->next = temp;
prev = temp;
if (num1)
num1 = num1->next;
if (num2)
num2 = num2->next;
}
if (carry > 0)
temp->next = newNode(carry);
return res;
}
void print(struct node *node)
{
while(node != NULL)
{
printf("%d->", node->digit);
node = node->next;
}
printf("\n");
}
My Output
My compiler does not give me any error. I tried debugging my make_node function but I cant catch the problem as to why my nodes are skipping certain digits.

Your linked list insert code is very broken. For this style of list, you need to walk down the list from head->next until a null is found and insert there. Instead, you are always replacing the head->next with your new temp node, thus breaking the list.
You can also add to the list backwards, making the newly added item the head each time and thus get around the traversal for add, but beware this will place your numbers in reverse order (which actually helps when you do your adding, so perhaps this is good too.)

Related

Segmentation fault issue while reversing linked list in c

#include <stdio.h>
#include <stdlib.h>
struct node {
int data;
struct node *next;
};
struct node *insert(struct node *link, int data) {
if (link == NULL) {
link = (struct node *)malloc(sizeof(struct node));
link->data = data;
link->next = NULL;
} else {
struct node *newlink = (struct node *)malloc(sizeof(struct node));
newlink->data = data;
newlink->next = link;
link = newlink;
}
return link;
}
void reverse(struct node *link) {
int i, j = 0;
int arr1[100], arr2[100];
struct node *current;
int count = 0;
current = link;
while (current != NULL) {
arr1[i] = current->data;
i = i + 1;
count = count + 1;
current = current->next;
}
printf("\n");
i = 0;
j = 0;
for (i = count - 1; i >= 0; i--) {
arr2[j] = arr1[i];
j = j + 1;
}
printf("The elements in the linked list are: ");
for (i = 0; i < count; i++) {
printf("%d ", arr1[i]);
}
printf("The elements in the reversed linked list are: ");
for (j = 0; j < count; i++) {
printf("%d ", arr2[j]);
}
}
void print(struct node *link) {
struct node *temp = link;
printf("The elements in the linked list are: ");
while (temp != NULL) {
printf("%d ", temp->data);
temp = temp->next;
}
}
void main() {
int value;
printf("Enter the value:\n");
scanf("%d", &value);
struct node *link = NULL;
link = insert(link, value);
char ans[3] = "yes";
while (ans[0] == 'y') {
printf("Do you want to add another node? Type Yes/No\n");
scanf("%s", ans);
if (ans[0] == 'y') {
printf("Enter the value:\n");
scanf("%d", &value);
link = insert(link, value);
} else {
reverse(link);
}
}
}
Here is the code I wrote to reverse a single linked list in C. I seem to try different combinations of the program but while doing it by array method, I am unable to get rid of the segmentation fault, and hence it doesn't give output.
There are some problems in your code:
i is uninitialized when used in the while loop in function reverse, causing undefined behavior which could explain the segmentation fault.
j is not modified in the loop at the end of the reverse function, causing an infinite loop:
for (j = 0; j < count; i++) {
printf("%d ", arr2[j]);
}
you are not reversing the list, you just print the list contents in reverse order, and assume its length is at most 100. This is probably not what you are expected to do.
in function main, the array ans should be made larger to accommodate at least the word yes, and you should prevent scanf() from storing more characters into it than would fit. Also reorganize the code to avoid duplication:
int main(void) {
struct node *link = NULL;
for (;;) {
char ans[80];
int value;
printf("Enter the value:\n");
if (scanf("%d", &value) != 1)
break;
link = insert(link, value);
printf("Do you want to add another node? Type Yes/No\n");
if (scanf("%79s", ans) != 1 || ans[0] != 'y') {
break;
}
}
reverse(link);
return 0;
}
Most of the above problems would have been spotted immediately by increasing the compiler warning level (for example gcc -Wall -Werror or clang -Weverything -Werror).
Here is a simpler version that reads numbers and allocates the list in the same order as you do, inserting each new element before the previous one, then reverses the list and finally prints it. As expected, the list is printed in the order of entry.
#include <stdio.h>
#include <stdlib.h>
struct node {
int data;
struct node *next;
};
struct node *insert(struct node *head, int data) {
struct node *newlink = malloc(sizeof(*newlink));
newlink->data = data;
newlink->next = head;
return newlink;
}
struct node *reverse(struct node *link) {
struct node *prev = NULL;
while (link) {
struct node *temp = link->next;
link->next = prev;
prev = link;
link = temp;
}
return prev;
}
void print(struct node *link) {
printf("The elements in the linked list are: ");
for (struct node *n = link; n; n = n->next) {
printf("%d ", n->data);
}
printf("\n");
}
int main(void) {
struct node *link = NULL;
int value;
printf("Enter the values, end the list with 0:\n");
while (scanf("%d", &value) == 1 && value != 0) {
link = insert(link, value);
}
link = reverse(link);
print(link);
return 0;
}

Linked List Pointer Without A Cast Error

I'm getting assignment makes pointer from integer without a cast errors on lines 46 and 53, the two lines with double asterisks on either side, and for the life of me, I cannot figure out why. Linked lists are very new to me, I don't know how they work completely yet.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
struct node_def
{
int data;
struct node_def *next;
};
typedef struct node_def node;
node *makeNode (int a);
node *insertFront(node *head,node *new);
void printList(node *head);
int numNodes = 0;
int main()
{
srand(time(0));
int r = rand() % 10000;
int i = 0;
node *head = NULL;
node *tmp = NULL;
printf("How many nodes? ", numNodes);
scanf("%d", numNodes);
printf("\n");
head = insertFront(head, tmp);
for(i = 0; i < numNodes; i++)
{
makeNode(r);
printList(head);
}
printf("\n");
return 0;
}
node *makeNode (int a)
{
node *new = malloc(sizeof(node));
**new = a;**
return new;
}
node *insertFront(node *head, node *new)
{
**new->data = head;**
new->next = new;
return 0;
}
void printList(node *head)
{
int j = 0;
for(j = 0; j < numNodes; ++j)
{
while (head != NULL)
{
printf(" %4d", head->data);
head = head->next;
}
if(j % 10 == 0)
printf("\n");
}
return;
}
new = a is meant to make new nodes and assign them a random number from 0 - 9999.
You try to assign r to new, but new is a struct.
You make a pointer to struct : node *new
What you want to do is assigning r to new->data, which is an int.
node *insertFront(node *head, node *new)
{
**new->data = head;** // ** is meaningless
new->next = new; // new is a reserved key word, don't use it this way
return 0;
}
What you try to do is to put a NULL pointer as the head of your list.
Just push element into it within your makeNode function.
insert like this :
void createNode(node *head)
{
Node *new_node = malloc(sizeof(Node*));
new_node->data = rand() % 100000;
new_node->next = NULL;
if(head == NULL)
head = new_node;
else if(head != NULL)
//Here you have to adapt your list, search (linked list crud functions)
}
You have a bad understanding about what pointers are.
Hope it helps bro

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);
}

Exception thrown in linked list

I need to write a function that returns the size of a linked list. It seems simple enough, but I get an exception when I try to advance my pointer.
This is the code:
int List_size(List *list)
{
List_node *p;
int counter = 0;
p = list->head;
while (p != NULL)
{
p = p->next;
counter = counter + 1;
}
return counter;
}
This is the code that defines the linked list:
typedef struct List_node
{
int data;
struct List_node *next;
struct List_node *prev;
}List_node;
typedef struct List
{
List_node *head;
}List;
And this is the code that creates the list:
List *create_list(int n)
{
List *list = (List*) calloc(n,sizeof(List));
list->head = NULL;
return list;
}
Lastly, I have inserted data (numbers) into the list using these two functions: (so don't think the lists are empty).
void insert_first(List_node *x, List *list)
{
x->next = list->head;
list->head = x;
}
void insert(List_node *x, List_node *y)
{
x->next = y->next;
y->next = x;
}
List_node *mk_node(int data, int n)
{
List_node *node = (List_node *)calloc(n, sizeof(List_node));
node->data = data;
return node;
}
Using a breakpoint I discovered that the problem lies in p = p->next, but I don't understand why.
Thank you very much.
edit - I did not think the full code is necessary, but here it is:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include "List.h"
void merge(List *small_list, List *big_list)
{
List_node *x, *y;
y = small_list->head;
x = big_list->head;
t = x->prev;
// while (y < x) //If there are smaller numbers on the small list, insert them first
// {
// insert(y,t)
// t = t->next;
// y = y->next;
// }
while (y != NULL && x->next != NULL)
{
if (x <= y && x->next >= y)
{
insert(y, x);
y = y->next;
}
else
x = x->next;
}
while (y != NULL)
{
insert(y, x);
y = y->next;
}
}
void main()
{
List *L1, *L2, *big_list, *small_list;
int num1, num2;
int i;
int a, b;
create_list(5,&L1);
create_list(3,&L2);
printf("Insert first number into L1\n");
scanf("%d", &num1);
node = mk_node(0,5);
insert_first(node, &L1);
for (i = 0; i<5; i++)
{
printf("Now insert the rest of the numbers\n");
scanf("%d", &num1);
next = mk_node(&num1,5);
insert(next, node);
node = next;
}
printf("Insert first number into L2\n");
scanf("%d", &num2);
node = mk_node(0,3);
insert_first(node, &L2);
for (i = 0; i<3; i++)
{
printf("Now insert the rest of the numbers\n");
scanf("%d", &num2);
next = mk_node(&num2,3);
insert(next, node);
node = next;
}
//If lists are in descending order, reverse them to ascending order
//if (L1->head > L1->head->next)
// reverse(L1);
// if (L2->head > L2->head->next)
// reverse(L2);
int size_L1 = List_size(L1);
int size_L2 = List_size(L2);
if (size_L1 <= size_L2)
{
big_list = L2;
small_list = L1;
}
else
{
big_list = L1;
small_list = L2;
}
merge(small_list, big_list);
print_list(L3);
getchar(); getchar();
}
As you can see, I inserted the numbers using the function insert(). I hope it is okay.
The function reverse is: (I really hope it works, I translated it from pseudo-code)
List reverse(List *list)
{
List_node *x, *y, *z;
if (list->head == NULL || list->head->next == NULL)
{
return *list;
}
x = list->head;
y = list->head->next;
z = list->head->next->next;
x->next = NULL;
while (z != NULL)
{
y->next = x;
x = y;
y = z;
z = z->next;
}
y->next = x;
list->head = y;
}
Basically, this is an assignment that says I have two 2-directional sorted linked lists, and I'm supposed to merge them into one big sorted linked list.
As for the exception - Unhandled exception at 0x00E21766 in Lists.exe: 0xC0000005: Access violation reading location 0xCCCCCCD0.
Edit - the print_list function:
void print_list(List *list)
{
List_node *p;
p = list->head;
printf("The linked list consists of: ");
while (p != NULL)
{
printf("%d ", p->data);
p = p->next;
}
printf("\n");
}
The problem is in code you did not show, because all the code you give is fine (*).
I could use your structs and functions to :
create a List
add a first node (with insert_first)
add other nodes (with insert)
get the size (using List_size)
display the data value of every node
free the nodes and the list
Here's the full code :
#include <stdio.h>
#include <malloc.h>
typedef struct List_node
{
int data;
struct List_node *next;
struct List_node *prev;
}List_node;
typedef struct List
{
List_node *head;
}List;
List *create_list()
{
List *list = (List*) malloc(sizeof(List));
list->head = NULL;
return list;
}
int List_size(List *list)
{
List_node *p;
int counter = 0;
p = list->head;
while (p != NULL)
{
p = p->next;
counter = counter + 1;
}
return counter;
}
void insert_first(List_node *x, List *list)
{
x->next = list->head;
list->head = x;
}
void insert(List_node *x, List_node *y)
{
x->next = y->next;
y->next = x;
}
/* my own additions */
List_node *mk_node(int data) {
List_node *node = (List_node *) malloc(sizeof(List_node));
node->data = data;
return node;
}
void delete_list(List *list) {
List_node *node = list->head;
while (node != NULL) {
List_node *next = node ->next;
free(node);
node = next;
}
free(list);
}
int main() {
List* list = create_list();
List_node *node, *next;
int i;
node = mk_node(0);
insert_first(node, list);
for (i=1; i<5; i++) {
next = mk_node(i);
insert(next, node);
node = next;
}
int n = List_size(list);
printf("size : %d\n", n);
node = list->head;
while (node != NULL) {
printf("node val : %d\n", node->data);
node = node->next;
}
delete_list(list);
return 0;
}
(*) Your code is not perfect because List_node struct contains a pointer prev that is never used, so you end with a single-linked list with every third value unused.
I added a comment above that I copied your code into my compiler and that it doesn't compile, so it won't run: the calls to create_list don't compile: they return a value as function return, not in a parameter; there are undeclared variables. Further, it is useless to give create_list and mk_node a parameter: they will allocate an array, not create a single list element. A call of calloc(1, sizeof(your_thing)) would suffice. After fixing these erors, several bugs became apparent:
in insert_first(node, &L2); you give it the address of the list, which is already a pointer. Remove the '&' (the compiler should have complained!).
same for List_size(&L1); L1 is already a pointer. Remove the '&'.
in: if (x <= y ...) you compare memory addresses. Change to: if (x->data <= y->data...)
in that statement the part "x->next >= y" also compares memory address, and I don't see why it is needed. I removed it.
The real problem seems to be in merge. You should either merge the lists into L1, or into L2, and preferably should create a result list. But you "randomly" insert an element into L1, then into L2, then again into L1, etcetera. In my test it ran indefinitly. The following merge works fine:
List *merge(List *small_list, List *big_list)
{
List_node *x, *y, *r;
List *result= create_list();
y = small_list->head;
x = big_list->head;
if (x->data < y->data)
{result->head= x; x= x->next;}
else {result->head= y; y= y->next;}
r= result->head;
while (y != NULL && x != NULL)
{
if (x->data < y->data)
{
r->next= x;
x = x->next;
}
else {
r->next= y;
y = y->next;
}
r= r->next;
}
while (y != NULL)
{
r->next= y;
y = y->next;
r= r->next;
}
while (x != NULL)
{
r->next= x;
x = x->next;
r= r->next;
}
r->next= 0;
return (result);
}
So the problem is that you allocate the list head, but never allocate memory for the list elements. Serge added mk_node which does the allocation (so Serge solved it).

C - what is wrong with my mergesort on linked list?

I got to the point where my program compiles (through vim, if that matters), but returns garbage. Here's the code:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
struct node {
int *val;
struct node *next;
};
struct node *addnode(int *val, struct node *next, int columns);
struct node *mergesort(struct node *head, int column);
struct node *merge(struct node *head_one, struct node *head_two, int column);
int main(int argc, char *argv[])
{
struct node *head;
struct node *current;
struct node *next;
int symbol = 0;
int columns = 0;
int rows = 0;
head = NULL;
int column = atoi(argv[1])-1;
int lastSpace = 0;
do {
symbol = fgetc(stdin);
if (rows == 0 && (lastSpace == 0 && (isspace(symbol) || feof(stdin)))) {
columns++;
lastSpace = 1;
} else if (!isspace(symbol)) {
lastSpace = 0;
}
if (symbol == '\n' || feof(stdin)) {
rows++;
};
} while (symbol != EOF);
if (ferror(stdin)) {
printf("Error on reading from file.\n");
} else {
printf("The file contains %d row(s) and %d column(s).\n", rows, columns);
};
rewind(stdin); //ignore it - it works in this case
int table[rows][columns], i, j;
puts("Original file:\n");
for (i = 0; i < rows; i++) {
head = addnode(*table, head, columns);
for (j = 0; j < columns; j++) {
scanf("%d",&table[i][j]);
head->val[j] = table[i][j];
printf("%d ",head->val[j]);
};
puts("\n");
};
/* Up to this point everything works */
head = mergesort(head, column);
printf("Sorted by %d column:\n", column+1);
for(current = head; current != NULL; current = current->next) {
for (j = 0; j < columns; j++) {
printf("%d ", current->val[j]); //suspect number 1 - printing loop prints only last node, instead node-by-node
};//I removed a }; in this area
puts("\n");
};
for(current = head; current != NULL; current = next)
next = current->next, free(current);
return 0;
};
struct node *addnode(int *val, struct node *next, int columns)
{
struct node *tnode;
tnode = (struct node*)malloc(sizeof(*tnode));
if(tnode != NULL) {
tnode->val = malloc(sizeof(int) * columns); //suspect number 2 - I'm not sure I allocated memory correctly, it should allocate array of integers
memcpy(tnode->val, val, sizeof(int) * columns);
tnode->val = val;
tnode->next = next;
};
return tnode;
}
struct node *mergesort(struct node *head, int column) //suspect number 3 - my modified mergesort duplicates last node
{
struct node *head_one;
struct node *head_two;
if((head == NULL) || (head->next == NULL))
return head;
head_one = head;
head_two = head->next;
while((head_two != NULL) && (head_two->next != NULL)) {
head = head->next;
head_two = head->next->next;
};
head_two = head->next;
head->next = NULL;
return merge(mergesort(head_one, column), mergesort(head_two, column), column);
}
struct node *merge(struct node *head_one, struct node *head_two, int column) //suspect number 4 - instead of merging, it duplicates nodes
{
struct node *head_combined;
if(head_one == NULL)
return head_two;
if(head_two == NULL)
return head_one;
if(head_one->val[column] < head_two->val[column]) {
head_combined = head_one;
head_combined->next = merge(head_one->next, head_two, column);
} else {
head_combined = head_two;
head_combined->next = merge(head_one, head_two->next, column);
};
return head_combined;
}
I run it from a command line like so:
name_of_program column < test.txt
test.txt looks like this
1 4 100 34 12
12 2 45 6 7
5 8 1 87 101
5 4 10 12 33
And instead of list sorted by column column, I get array from last node from test.txt 4 times. I have no idea how to analyse it step-by-step in vim, and I think that would help me pinpoint the problem.
I don't understand why you're passing table into addNode. The way you're calling it, the row you want to put into the node you're adding hasn't been read from the file yet.
These two lines need to go, but what did you intend with the second line ?
By that point, you've already allocated space for tnode->val and copied data from val to it.
memcpy(tnode->val, val, sizeof(int) * columns);
tnode->val = val; /// What's this for ???
I think this
head_two = head->next->next;
should be
head_two = head_two->next->next;
It seems like you're trying to find the midpoint here, so head_two needs to walk twice as fast as head.

Resources