As a part of an assignment, I need to write two functions:
a function that sums up two natural numbers represented as a linked list
a functions that prints a number represented in the same way.
for some reason, both function work perfectly fine separately, but when I try to use the print function on the result of the sum function, it changes the value of the sum right in the beginning of the print function , and prints the wrong value. when I use printf to print the same value in the main, there is no problem. my code is detailed below. any ideas?
void main()
{
int a[1] = { 1 },
b[1] = { 2 };
int * *pa, **pb;
List lst1, lst2;
List sum;
pa = (int * *) malloc(sizeof(int * )); * pa = &a[0];
pb = (int * *) malloc(sizeof(int * )); * pb = &b[0];
lst1 = arrToList(pa, 1);
lst2 = arrToList(pb, 1);
addNumbers(lst1, lst2, &sum);
//printf("%d\n",*(sum.head->dataPtr));
printNumber(sum);
}
//a function that recieves a number represented ad a list and prints it
void printNumber(List num)
{
ListNode * curr;
int currData,
i,
number;
if (isEmptyList(num) == TRUE)
printf("the input was an empty list, nothing to print");
else
{
i = 0;
number = 0;
curr = num.head;
while (curr != NULL)
{
currData = *(curr - >dataPtr);
number = number + currData * ((int) pow(10, i));
curr = curr - >next;
i++;
}
printf("%d \n", number);
}
}
// a function that sums in list
// representation two numbers,
// each represented as a list
void addNumbers(List n1, List n2, List * sum)
{
ListNode * currN1;
ListNode * currN2;
ListNode * currSum;
int currN1N2Sum; //stores the sum of the current digits in n1 and n2
int carrier,
prevCarrier; //current and previous carriers that carries +1 to the
next digit of sum
if the lst sum was bigger then 9
if ((isEmptyList(n1) == TRUE) || (isEmptyList(n2) == TRUE))
printf("bad input =(");
else
{
currN1 = n1.head;
currN2 = n2.head; * sum = createEmptyList();
carrier = 0;
prevCarrier = 0;
while ((currN1 != NULL) && (currN2 != NULL))
{
currN1N2Sum = *(currN1->dataPtr) + *(currN2->dataPtr) + prevCarrier;
if (currN1N2Sum > 9)
{
carrier = 1;
currN1N2Sum = currN1N2Sum - 10;
}
currSum = creatNewListNode( & currN1N2Sum, NULL);
insertNodeToEnd(sum, currSum);
prevCarrier = carrier;
carrier = 0;
currN1 = currN1 - >next;
currN2 = currN2 - >next;
} //while ((currL1!=NULL)&&(currL2!=NULL))
while (currN1 != NULL)
{
currN1N2Sum = *(currN1 - >dataPtr) + prevCarrier;
currN1 = currN1 - >next;
if (prevCarrier != 0) prevCarrier = 0;
}
while (currN2 != NULL)
{
currN1N2Sum = *(currN2 - >dataPtr) + prevCarrier;
currN2 = currN2 - >next;
if (prevCarrier != 0) prevCarrier = 0;
}
} // ! ((isEmptyList(n1)==TRUE)||(isEmptyList(n2)==TRUE))
}
here is the rest of the code:
typedef struct listNode{
int* dataPtr;
struct listNode* next;
} ListNode;
typedef struct list
{
ListNode* head;
ListNode* tail;
} List;
List createEmptyList()//creates and returns an empty linked list
{
List res;
res.head = res.tail = NULL;
return res;
}
Bool isEmptyList ( List lst )//checks if a given list is empty or not
{
if (lst.head == NULL && lst.tail == NULL)
return TRUE;
else
return FALSE;
}
void insertDataToEnd ( List * lst, int *dataPtr ) //inserts new data to the end of an existing linked list
{
ListNode * newTail;
newTail = creatNewListNode ( dataPtr, NULL );
insertNodeToEnd(lst,newTail);
}
void insertNodeToEnd ( List * lst, ListNode * newTail )//insert an existing node to an existing linked list
{
if (isEmptyList(*lst) == TRUE )
insertNodeToStart ( lst,newTail );
else
{
(*lst).tail -> next = newTail;
newTail->next = NULL;
(*lst).tail = newTail;
}
}
ListNode * creatNewListNode ( int * dataPtr, ListNode * next )//inserts new node in an existing linked list
{
ListNode * res;
res = (ListNode *) malloc (sizeof(ListNode));
res -> dataPtr = dataPtr;
res -> next = next;
return res;
}
void insertNodeToStart ( List * lst, ListNode * newHead )//inserts node to the begining of a given linked list
{
if ( isEmptyList( *lst ) == TRUE )
{
(*lst).head = newHead;
(*lst).tail = newHead;
newHead -> next = NULL;
}
else
{
newHead -> next = (*lst).head;
(*lst).head = newHead;
}
}
The bug is in the function addNumbers.
When you add a node to store the sum you pass a pointer to the variable currN1N2Sum which is a local variable (stored on the stack). When the addNumbers function terminates, the storage of the local variable is set free. The value found at that location will remain unchanged and thus apparently valid as long as the storage is not reused.
This is why you had the impression the addNumbers function was correct. When calling the printNumber function the storage is overwritten and you find a different value in there.
This explain your bug.
There is another problem with addNumbers. When you will try to add two digit numbers, the content of the currN1N2Sum will be overwritten by a new value.
What you should do is allocate a buffer (malloc) and store the value contained into currN1N2Sum into it. Pass the pointer to the buffer into the new node.
BTW: you may change (*lst).head in lst->head. It will make your code more readable.
We need to see some more code: how you define the data structure for holding nodes, how you add nodes etc.
The following line is suspect:
number=number+currData*((int)pow(10,i));
Say, you have 123 stored as 1, 2, and 3 nodes:
number = 0;
number = 0 + 1 * 1 = 1;
number = 1 + 2 * 10 = 21;
number = 21 + 3 * 100 = 321;
But if you store is as 3, 2, and 1 nodes you'd get:
number = 0;
number = 0 + 3 * 1 = 3;
number = 3 + 2 * 10 = 23;
number = 23 + 1 * 100 = 123;
Is this your problem?
I'm not if this is an issue or not without seeing the implementation of createNewListNode(), but here's something to think about:
Where are the dataPtrs in the sum list pointing after you return from the addNumbers() call?
You've got a problem with createEmptyList. you declare there a list called res and return the structure but the minute this function returns that structure is not valid any more.
try using malloc (for the struct) and then return the pointer to the caller. You use this function in the beginning with *sum.
This is a similar bug to what chmike found so you better fix both.
I think you might be messing things up pointer-wise... The way you're allocating the list 'sum' in addNumbers seems very, very odd. (And I would not be surprised if it's breaking things...)
Try making these changes:
In main:
List *sum;
<...>
addNumbers(lst1,lst2,sum); //Note the absence of the reference operator &
printNumbers(*sum);
(Alternatively, change printNumbers to accept a (List *) instead of (List)).
Hope this helped XD
EDIT:
Try allocating 'sum' before making calls to addNumbers().
lst1 = arrToList(pa, 1);
lst2 = arrToList(pb, 1);
sum = createEmptyList();
I still think the way that your data structures are a little weird :S
Related
I have this struct:
typedef struct node {
struct node *m_Next;
int id;
} NODE;
And I need to split linked list in half. If it can't be split into two same halves, I want to remove the last one from the bigger list.
Example: The whole list: {1,2,3,4,5}; What I need: A:{1,2} B:{3,4} (The last one is discarded)
I have this function to separate the list:
void split(NODE *src, NODE **p1, NODE **p2) {
int len = get_length(src);
if (len < 2) {
*p1 = NULL;
*p2 = NULL;
return;
}
struct node *current = src;
int c = (len - 1) / 2;
for (int i = 0; i < c; i++) {
current = current->m_Next;
}
*p1 = src;
*p2 = current->m_Next;
current->m_Next = NULL;
}
It works fine with even lists, but when I try to separate something with 7 structs, I have two problems:
a) The last one doesn't point to NULL
b) It shuffles the data somehow (I expect: A:{1,2,3} B:{4,5,6} | I get: A:{1,2,3} B:{5,4,7} for example)
Could anyone please help me splitting the list correctly and adding the even/odd condition?
I already have the function to delete the last struct:
deleteNode(struct TSoldier *firstNode)
I just don't use it currently, because the split function is bugged.
Thanks :)
First of all, it is worth noting that the following code probably causes a memory leak:
if (len < 2) {
*p1 = NULL;
*p2 = NULL;
return;
}
If the number of nodes is equal to 1, then, unless you keep some other reference to this node, the memory will be leaked. You probably have such a reference outside the function, but you are probably discarding this reference and only keeping the values written to p1 and p2, which means the memory is leaked.
Therefore, assuming that you allocated the node with malloc, you will probably want to add the line
free( src );
in order to prevent the memory leak, or use your function deleteNode.
As already pointed out in the other answer, the line
int c = (len - 1) / 2;
is wrong. It should be:
int c = len / 2 - 1;
At the end of your function split, if the number of nodes is odd, you must add code to discard the final node, for example like this:
if ( len % 2 == 1 )
{
current = *p2;
for (int i = 0; i < c; i++) {
current = current->m_Next;
}
free( current->m_Next );
current->m_Next = NULL;
}
To determine the last node of the first half, instead of int c = (len - 1) / 2; you should use this formula that works for even and odd lengths:
int c = len / 2 - 1;
Similarly, to drop the last node if the length is odd and greater than 1:
if (len & 1) {
NODE *node = src;
for (int i = 2; i < len; i++) {
node = node->m_Next;
}
deleteNode(node->m_Next);
node->m_Next = NULL;
}
Here is an alternative approach using the fast and slow scan trick:
void split(NODE *src, NODE **p1, NODE **p2) {
NODE *last = src;
*p1 = *p2 = NULL;
if (src && src->m_Next) {
NODE *slow = src;
NODE *fast = src;
while (fast->m_Next && fast->m_Next->m_Next) {
slow = slow->m_Next;
fast = fast->m_Next->m_Next;
}
*p1 = src;
*p2 = slow->m_Next;
slow->m_Next = NULL;
last = fast->m_Next; // last will be non NULL if length is odd
fast->m_Next = NULL;
}
if (last) {
deleteNode(last); // drop the last node if required
}
}
I'm practicing code that can find redundancies in a linked list.
For example:
INPUT
777
OUTPUT
contains 2 redundancies
INPUT
32182
OUTPUT
contains 1 redundancies
I'm struggling to actually track redundancies in my code. I'v sorted the linked list, then I assume I would just create 2 pointers one that traverses the current location of the linked list and one that traverses the previous location of the linked list and if they're equal count++. But I always get 0 redundancies.
In the code below, I think my challenge is mainly in the countRedun() method.
struct digit * insertAtFront(struct digit *start, struct digit * newDig){
struct digit * ptr = start;
newDig = start;
return newDig;
}
struct digit * insertIntoSorted(struct digit *start, struct digit *newDig) {
struct digit *ptr = start;
struct digit *prev = NULL;
while ((ptr!=NULL) && (ptr->num < newDig->num)) {
prev = ptr;
ptr = ptr->next;
}
if (prev == NULL) {
start = insertAtFront(start, newDig);
} else {
prev->next = newDig;
newDig->next = ptr;
}
return(start);
}
struct digit * sortedCopy(struct digit * start) {
//! heap1=showMemory(start=348, cursors=[start, ptr, sortedStart, newDigit])
//! heap2=showMemory(start=519, cursors=[start, newDigit, ptr, prev])
struct digit *ptr = start;
struct digit *sortedStart = NULL;
struct digit *newDigit;
if (start!=NULL) {
sortedStart = createDigit(start->num);
ptr = ptr->next;
}
while (ptr!=NULL) {
newDigit = createDigit(ptr->num);
sortedStart = insertIntoSorted(sortedStart, newDigit);
ptr = ptr->next;
}
return(sortedStart);
}
int countRedun(struct digit * start){
struct digit *sorted, *ptr, *prev, * curr;
ptr = start;
prev = start;
//sort linked list
sorted = sortedCopy(start);
int count = 0;
while(ptr != NULL)
{
if(ptr->num == prev->num)
{
count++;
}
prev = ptr;
ptr = ptr->next;
}
}
I've excluded the code that asks user for input, as well as the linked list creator methods, assuming that the sorting, and counting methods are key for this question.
It looks like sortedCopy makes a whole new list, but sorted. If so, then you need to reorder:
ptr = start;
prev = start;
//sort linked list
sorted = sortedCopy(start);
with:
//sort linked list
sorted = sortedCopy(start);
ptr = sorted;
prev = sorted;
as a note, you would likely be better to:
prev = NULL;
while(ptr != NULL) {
count += (prev && ptr->num == prev->num);
prev = ptr;
ptr = ptr->next;
}
otherwise you count will always be off by one.
I think the issue is in insertAtFront
struct digit * insertAtFront(struct digit *start, struct digit * newDig){
struct digit * ptr = start;
newDig = start;
return newDig;
}
Remember that everything is passed by value. Your ptr variable isn't used at all, and in this function start and newDig are local variables. Really this is equivalent to:
struct digit * insertAtFront(struct digit *start, struct digit * newDig){
return start;
}
Have another look at that function. I'm not sure of your context but you can use a debugger or printf statements to see what's going on.
If you are sure that:
all you need to do is get the number of redundancies
your input is always going to be a digit between 0 and 9
Then you don't need to sort the data (which, by the way, you're doing in O(n^2) time complexity).
All you need to do is keep an array with 10 elements initialized to 0, increase the corresponding index to your element and count the elements with value greater than 1.
Something along the lines of this (beware: NOT tested):
int countRedun(struct digit * start){
int counter[10] = {0};
struct digit *ptr = start;
int total = 0;
while(ptr != NULL)
{
counter[ptr->num]++;
ptr = ptr->next;
}
for (int i = 0; i < 10; i++) {
if (counter[i] > 1) {
total += counter[i] - 1;
}
}
return total;
}
I have a linked list, which I wanted to populate up to a certain loop number. I have my code below is shows a Fibonacci series using a C Linked list.
Here is my code without any loop:
#include <stdio.h>
#include <stdlib.h>
typedef struct Node
{
int count;
int fibo;
struct Node* next;
}node;
int
fibo(int val){
if(val == 1 || val == 2) {
return 1;
}
return fibo(val - 1) + fibo(val - 2);
}
int
main (void)
{
node f1, f2, f3;
f1.count = 1;
f1.fibo = fibo(1);
f2.count = 2;
f2.fibo = fibo(2);
f3.count = 3;
f3.fibo = fibo(3);
f1.next = &f2;
f2.next = &f3;
f3.next = NULL;
printf("f1 fibo : %i\n", f1.fibo);
printf("f2 fibo : %i\n", f2.fibo);
printf("f3 fibo : %i\n", f3.fibo);
return (0);
}
Now I want to do this via a loop. How would I do that?
For this answer, I'm going to ignore the computational efficiency concerns that arise from recomputing all of the Fibonacci numbers up to the given number you are retrieving with each call to fibo(n).
Linked lists are not usually "random access" data structures that let you access an arbitrary element with an index. When using a linked list with pointers, you only need to have the pointer to the head (first element) of the linked list. You then traverse the list starting at the head using a loop going through each next link. If a list is empty, your head is usually NULL.
You can apply this here. One way (there are several) is to define a function to allocate and set a single entry:
node *set_fibo(int n)
{
node *fibo_entry = malloc(sizeof(node));
if ( fibo_entry == NULL ) {
// error
}
fibo_entry->count = n;
fibo_entry->fibo = fibo(n);
fibo_entry->next = NULL;
return fibo_entry;
}
And then in your main:
node *fibo_list = NULL;
node *last_fibo = NULL;
// Assume n_fibo is the number of Fibonacci numbers you want to store in order
for ( int n = 1; n <= n_fibo; n++ ) {
if ( n == 1 )
fibo_list = last_fibo = set_fibo(1);
else {
last_fibo->next = set_fibo(n);
last_fibo = last_fibo->next;
}
}
Although the question has already been answered, I would like to add something regarding the efficiency aspect of your code. As pointed out before, you do not have to calculate the fibo value by starting from the beginning, since you saved the latest results in the singly linked list.
So given you have the following list 1-1-2-3-5-, you can easily calculate the fibo value of the new node by simply adding the fibo value of the two lates elements (i.e. 3 and 5). Hence the value of the fibo value of the new node should be 8.
Given the pointer to the second last element, this function will add add a new node to the list and set the correct fibo value:
void addNode(struct Node* node){
struct Node* n = malloc(sizeof(struct Node));
n->next = NULL;
n->count = node->next->count + 1;
n->fibo = node->fibo + node->next->fibo;
node->next->next = n;
}
In order to use this function, you have to create the first two nodes in the list:
struct Node* n2 = malloc(sizeof(struct Node));
n2->count = 2;
n2->fibo = 1;
n2->next = NULL;
struct Node* n1 = malloc(sizeof(struct Node));
n1->count = 1;
n1->fibo = 1;
n1->next = n2;
If you now want to add - lets say 10 - new nodes, you simply do:
struct Node* ptr = n1;
int i;
for(i=0; i<10;i++) {
addNode(ptr);
ptr = ptr->next;
}
If you now want to print the entries of all nodes in the list, simply iterate over the list until you reach NULL.
ptr = n1;
while(ptr != NULL) {
printf("fib(%d) = %d\n ", ptr->count, ptr->fibo);
ptr = ptr->next;
}
Please keep in mind, that you have to manually free dynamically allocated items!
In your example, the nodes are automatic variables in main. They are not dynamically allocated and they live as long as you don't return from main. You can extend this concept with a automatic array of nodes:
#include <stdio.h>
#include <stdlib.h
typedef struct Node Node;
struct Node {
int count;
int fibo;
Node* next;
};
#define N 30
int main (void)
{
Node fibo[N];
Node *head = NULL;
Node **p = &head;
int f1 = 0;
int f2 = 0;
for (size_t i = 0; i < N; i++) {
Node *nd = &fibo[i];
nd->count = i + 1;
nd->fibo = f2 + f1 ? f2 + f1 : 1;
f1 = f2;
f2 = nd->fibo;
*p = nd;
p = &(*p)->next;
}
*p = NULL;
Node *nd = head;
while (nd) {
printf("fib(%d) == %d\n", nd->count, nd->fibo);
nd = nd->next;
}
return (0);
}
It's not clear, though, why you need the Fibonacci series as linked list. Also, a word of warning: Don't mix nodes on the stack (like here) and nodes on the heap (as in lurker's answer) in a list. This answer just extends your answer to many nodes, whereas lurker's answer shows a more general concept of linked lists.
Here is how I think you can do it. You can use an array for the nodes.
node f[3];
int i;
for ( i = 0 ; i < 3 ; i++ )
{
f[i].count = i+1;
f[i].fibo = fibo (i+1);
if ( i == 2 )
{
f[i].next = NULL;
}
else
{
f[i].next = &f[i+1];
}
}
Is it in general possible to store a sequence of inputs and print it out later without using arrays?
I am required to take integer inputs sequentially with -1 marking as the end of input without taking it as an input (call it xn). Output is supposed to be sequence an where
an:= xn-1 + xn, where n>1
Following is my code, but the output happens along with the input and not at one go as the problem really requires. Here is the code:
#include <stdio.h>
int main() {
int xo,a;
int sum =0;
int previous=0;
scanf("%d",&xo);
previous = xo;
while ((!scanf("%d",&a)==0) && (!(a==-1))) {
sum = previous+a;
previous = a;
printf("%d",sum);
}
return 0;
}
Input:
1
2
3
4
-1
Output:
3 5 7
I'm not entirely sure, but the purpose of your task could be to familiarise yourself with lists. Then you don't need an array to store the input values:
struct list {
int val;
struct list * next;
};
Handling lists should be abstracted into general functions:
struct list * list_add(struct list * lst, int val) {
struct list * node =
(struct list *) malloc(sizeof(struct list));
node->val = val;
node->next = lst;
return node;
}
void list_free(struct list * lst) {
while (lst) {
struct list * temp = lst;
lst = lst->next;
free(temp);
}
}
struct list * list_nreverse(struct list * lst) {
struct list * nlst = lst;
if (lst) {
lst = lst->next;
nlst->next = NULL;
while (lst) {
struct list * temp = lst;
lst = lst->next;
temp->next = nlst;
nlst = temp;
}
}
return nlst;
}
To use the list, you can either store your input values in the list or, to stay close to the code that you already have, calculate the output (the adjacent sum) on the fly and store that in a list, printing the entire list
at the end (in reverse order):
int current;
int previous;
struct list * output = NULL;
scanf("%d", &previous);
while ((!scanf("%d", ¤t) == 0) && (current != -1)) {
sum = previous + current;
previous = current;
output = list_add(output, sum);
}
output = list_nreverse(output);
struct list * iterator = output;
while (iterator) {
printf("%d ", iterator->val);
iterator = iterator->next;
}
list_free(output);
Note: Code is currently untested, but should give you an idea of how you can accomplish this.
Just keep appending to a string. At the end of the input, print the string.
a string can be considered as an array. maybe this invalidates this answer
Otherwise, no. You need an array to store either the input or the calculations.
Oops ... as Daniel Jour says in his answer you can use a list instead of an array.
integer inputs are sequentially taken with 'scan'. To find end of the input, checking the scan return value with -1 so to scan the null element.
Here is my code as given below, output happens according to your requirement. output happens at one go that your problem really requires #subrat. The code is as follows:
#include <stdio.h>
int main()
{
int xo,a;
int sum =0;
int diff=0;
int previous=0;
scanf("%d",&xo); //dont need xo here :: use previous only
previous = xo;
while ((scanf("%d",&a)!=-1)) //important to use sum=0
{
sum = previous+a;
previous = a;
printf("%d ",sum);
sum=0;
}
return 0;
}
INPUT : 1 2 3 4 -1
OUTPUT : 3 5 7 3
As you will see in the comments of the following program, I am supposed to create a list that stores all prime numbers from 1 to 1000 and free the node.
Only two of of the functions are my work. However, I haven't figured out for ages why this program does not compile. Do you guys see the mistake? This is an already handed in homework, so this is just for my personal reference.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
/* given data structure declaration */
struct record {
int data;
struct record * next;
};
typedef struct record RecordType;
/* DO NOT MODIFY */
/* print a list */
void print_list(RecordType * list)
{
RecordType * visitor = list;
int count = 0;
while (visitor != NULL)
{
printf("%d ", visitor->data);
visitor = visitor->next;
count++;
}
printf("\n");
printf("There are %d items in the list.\n", count);
}
/* MY WORK HERE */
/* free every node in the list */
void free_list(RecordType * list)
{
while (list->data != 2){
free(list->next);
list->next = list;
}
}
/* MY WORK HERE */
/* this function may call other functions created by students */
/* create a list storing all prime numbers in [1, 1000] in ascending order */
/* return a pointer to the starting point of the list */
RecordType * create_list_prime_in_1_to_1000()
{
RecordType * begin, *tail, *temp;
int i = 0;
begin = malloc(sizeof(RecordType));
begin->data = 0;
begin->next = NULL;
tail = begin;
while(i<1000){
temp = malloc(sizeof(RecordType));
temp -> data = ++i;
tail -> next = temp;
tail -> temp;
tail -> next = NULL;
}
}
int isPrime(int n){
int d;
for (d = 2; d < n; d = d + 1)
if (n % d == 0)
return 0;
return 1;
}
/* DO NOT MODIFY */
/* main program */
int main(void)
{
RecordType * start;
/* create a linked list to store all the prime numbers in 1 - 10 */
/* this is a naive way by hard-coding */
start = malloc(sizeof(RecordType));
start->data = 2;
start->next = malloc(sizeof(RecordType));
start->next->data = 3;
start->next->next = malloc(sizeof(RecordType));
start->next->next->data = 5;
start->next->next->next = malloc(sizeof(RecordType));
start->next->next->next->data = 7;
start->next->next->next->next = NULL;
print_list(start);
free_list(start);
/* i am expected to expected to build a list iteratively rather than hard-code */
start = create_list_prime_in_1_to_1000();
print_list(start);
free_list(start);
return 0;
}
You have tail declared as:
RecordType * begin, *tail, *temp;
and RecordType as:
struct record {
int data;
struct record * next;
};
typedef struct record RecordType;
Next you have:
tail -> temp;
which does not work as RecordType has no member named temp.
I think it should be:
tail = temp;
The cause for the runtime error seems to be because of:
void free_list(RecordType * list)
{
while (list->data != 2){
free(list->next);
list->next = list;
}
}
which is incorrect. You need something like:
void free_list(RecordType * list)
{
// keep going till there are nodes.
while (list){
// save the link to the rest of the nodes.
RecordType *temp = list->next;
// free the current node.
free(list);
// repeat the process starting at the next node.
list = temp;
}
}