I'm working on a homework assignment for CS1, and I almost have it finished but errors keep popping up in relation to a few functions I've tried to implement. The assignment is the classic addition and subtraction of big integers using linked lists. My issue isn't with any of mathematical functionality of the program, but rather getting the linked lists to print properly when finished. I'm pretty sure most of the problems reside within stripLeadingZeros(); the functions are as follows.
/*
* Function stripLeadingZeros
*
* #Parameter STRUCT** Integer
*
* Step through a linked list, recursively unlinking
* all leading zeros and making the first
* non-zero integer the head of the list.
*/
struct integer* stripLeadingZeros( struct integer *p )
{
// Are we at the end of the list?
if( p == NULL ) return NULL;
// Are we deleting the current node?
if( p->digit == 0 )
{
struct integer *pNext;
pNext = p->next;
// Deallocate the node
free( p );
// Return the pointer to the next node
return pNext;
}
// Recurse to make sure next node is not 0
p->next = stripLeadingZeros( p->next );
return p;
}
---///---
/*
* Function print
*
* #Parameter STRUCT* Integer
*
* Given a linked list, will traverse through
* the nodes and print out, one at a time,
* the digits comprising the struct integer that the
* linked list represents.
*
* TODO: Print to file
*/
void print( struct integer *p )
{
struct integer *head = p;
reverse( &p );
p = stripLeadingZeros( p );
while( p )
{
fprintf(outFile, "%d", p->digit);
p = p->next;
}
reverse( &head );
}
---///---
/*
* Function reverse
*
* #Parameter STRUCT** Integer
*
* Recursively reverses a linked list by
* finding the tail each time, and linking the
* tail to the node before it.
*/
void reverse (struct integer **p)
{
/*
* Example p: 1->2->3->4->NULL
*/
if( (*p)->next == NULL ) return;
struct integer *pCurr = *p, *i, *pTail;
// Make pCurr into the tail
while( pCurr->next )
{
i = pCurr;
pCurr = pCurr->next;
}
// Syntactic Sugar
pTail = pCurr;
pTail->next = i;
/*
* p now looks like:
* 1->2->3<->4
*/
i->next = NULL;
/*
* p now looks like:
* 1 -> 2 -> 3 <- 4
* |
* v
* NULL
*/
reverse( p ); // Recurse using p: 1 -> 2 -> 3;
*p = i;
}
The output I am currently getting for the whole program is:
888888888 + 222222222 = 11111111
000000000 - 999999999 = 000000001
000000000 - 999999999 = 000000001
whereas the expected output is
8888888888 + 2222222222 = 11111111110
10000000000 – 9999999999 = 1
10000000000 – 9999999999 = 1
Any help anyone could give would just be awesome; I've been working on this for so long that if I had any hair I'd have pulled it out by now.
EDIT My read_integer function is as follows:
/*
* Function read_integer
*
* #Parameter CHAR* stringInt
*
* Parameter contains a string representing a struct integer.
* Tokenizes the string by each character, converts each char
* into an integer, and constructs a backwards linked list out
* of the digits.
*
* #Return STRUCT* Integer
*/
struct integer* read_integer( char* stringInt )
{
int i, n;
struct integer *curr, *head;
int numDigits = strlen( stringInt ); // Find the length of the struct integer
head = NULL;
for( i = 0; i < numDigits; i++ )
{
n = stringInt[i] - '0'; // Convert char to an integer
curr = (struct integer *) malloc (sizeof( struct integer )); // Allocate memory for node
curr->digit = n; // Digit of current node is assigned to n
curr->next = head; // Move to the next node in the list.
head = curr; // Move head up to the front of the list.
}
return head; // Return a pointer to the first node in the list.
}
Simulate stripLeadingZeros() on "0004".
It does not work. Also you ignored an edge case: what if it is only "0". You must not strip the only 0 in that case.
Correct code:
struct integer* stripLeadingZeros( struct integer *p )
{
// Are we at the end of the list?
if( p == NULL ) return NULL;
// Are we deleting the current node? Also it should not strip last 0
if( p->digit == 0 && p->next != NULL)
{
struct integer *pNext;
pNext = p->next;
// Deallocate the node
free( p );
// Try to strip zeros on pointer to the next node and return that pointer
return stripLeadingZeros(pNext);
}
return p;
}
Consider the control flow of this function:
struct integer* stripLeadingZeros( struct integer *p )
{
// Are we at the end of the list?
if( p == NULL ) return NULL;
// Are we deleting the current node?
if( p->digit == 0 )
{
struct integer *pNext;
pNext = p->next;
// Deallocate the node
free( p );
// Return the pointer to the next node
return pNext;
}
// Recurse to make sure next node is not 0
p->next = stripLeadingZeros( p->next );
return p;
}
What happens when p starts with a zero? It enters the if statement, removes the one leading zero, and returns. It does not recurse because you've already returned within the if statement. This means that stripLeadingZeros will remove at most one zero.
Now what happens when p starts with a one? It skips the if statement, but it does recurse. This is also wrong, because once have seen a one, you want to stop removing zeroes, as they are no longer leading.
So what this function is actually doing is removing the first zero it encounters, leading or not, and then stopping. That's not what you want it to do.
You want to recurse after you have removed a zero, and only after you have removed a zero, so move the recursive call into the if statement. In other words, replace return pNext; with return stripLeadingZeros(pNext);, and remove the recursion from outside the loop.
You can improve your reverse function by reversing your original list into another list:
void reverse(struct integer** p)
{
struct integer* old = *p;
struct integer* new = NULL;
while(old != NULL)
{
struct integer* oldNext = old->next;
old->next = new;
new = old;
old = oldNext;
}
*p = new;
}
stripLeadingZeros( nodeptr s )
{
if(s!=NULL)
stripLeadingZeros(s->next);
if((s!=NULL)&&s->data==0&&on)
flg=1;
if((s!=NULL)&&(s->data!=0)&&flg)
on=0,flg=0,s->next=NULL;
if(flg)
s->next=NULL;
}
here's my code to strip leading zeros initial values of on and flg are 1 and 0 respectively .
http://programmingconsole.blogspot.in/2013/10/all-basic-calculator-functions-on-large.html
in your current version of stripLeadingZeros you can replace the while loop with an if statement that the result will be the same. Maybe that is the problem.
while (1) {
/* ... */
return 0; /* this "infinite loop" only runs once */
}
compare with
if (1) {
/* ... */
return 0;
}
Related
I have this code that gets equations from a .txt file and stores them in a stack, the problem is that when I print them to see the content of the stack, the equations are inverted.
the code is:
// C program to Implement a stack
// using singly linked list
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// Declare linked list node
struct Node
{
char data;
struct Node *next;
};
int nodesCount;
// Utility function to add an element `x` to the stack
void push(struct Node **top) // insert at the beginning
{
FILE *myFile;
myFile = fopen("equations.txt", "r");
if (myFile == 0)
{
printf("file not opened\n");
}
else
{
printf("file opened \n");
}
// allocate a new node in a heap
struct Node *node = NULL;
node = (struct Node *)malloc(sizeof(struct Node));
// check if stack (heap) is full. Then inserting an element would
// lead to stack overflow
if (!node)
{
printf("Heap Overflow\n");
exit(-1);
}
char equation; //to store the current character in the file
/*
* initialize the count to 1
*/
nodesCount = 0;
while (!feof(myFile))
{
/*
* Use fgetc to read the file by character
*/
equation = (char)fgetc(myFile);
// set data in the allocated node
node->data = equation;
// set the .next pointer of the new node to point to the current
// top node of the list
node->next = *top;
// update top pointer
*top = node;
/*
* Each time a node is added, it should be allocated new memory
*/
node = (struct Node *)malloc(sizeof(struct Node)); // allocate the memory to new node
// increase stack's size by 1
nodesCount += 1;
}
}
// Utility function to check if the stack is empty or not
int isEmpty(struct Node *top)
{
return top == NULL;
}
// Utility function to return the top element of the stack
int peek(struct Node *top)
{
// check for an empty stack
if (!isEmpty(top))
{
return top->data;
}
else
{
printf("The stack is empty\n");
exit(EXIT_FAILURE);
}
}
// Utility function to pop a top element from the stack
int pop(struct Node **top) // remove at the beginning
{
struct Node *node;
// check for stack underflow
if (*top == NULL)
{
printf("Stack Underflow\n");
exit(EXIT_FAILURE);
}
// take note of the top node's data
int x = peek(*top);
printf("Removing %d\n", x);
node = *top;
// update the top pointer to point to the next node
*top = (*top)->next;
// decrease stack's size by 1
nodesCount -= 1;
// free allocated memory
free(node);
return x;
}
// Utility function to return the nodesCount of the stack
int size()
{
return nodesCount;
}
int main(void)
{
struct Node *top = NULL;
push(&top);
if (isEmpty(top))
{
printf("The stack is empty\n");
}
else
{
printf("The stack is not empty\n");
}
//Uncomment to check the output :
struct Node *curr = top;
while (curr)
{
printf("%c", curr->data);
curr = curr->next;
}
return 0;
}
the equation.txt file contains:
a = ((c+d)*a)/(b/(d-a))
b = 4*[x + 3*(2*x + 1)]
c = -5*{3 - 2*[1 - 4*(3 - 22)]}
d = 5 + 2*{[3 + (2*x - 1) + x] - 2}
e = 5 + 9 * 3
(5 + 9)*3
f (5 + 9)*3
g = 5 + 2*{[3 + (2*x - 1) + x - 2}
h = 5 + 9 * 3)
i = 5 + (9 * 3
the output is:
�
3 * 9( + 5 = i
)3 * 9 + 5 = h
}2 - x + )1 - x*2( + 3[{*2 + 5 = g
3*)9 + 5( f
3*)9 + 5(
3 * 9 + 5 = e
}2 - ]x + )1 - x*2( + 3[{*2 + 5 = d
}])22 - 3(*4 - 1[*2 - 3{*5- = c
])1 + x*2(*3 + x[*4 = b
))a-d(/b(/)a*)d+c(( = a
is there a way to make the output look like the equation.txt file or at least make the parenthesis and other braces look in the correct direction?
As already pointed out by someone else in the comments section, a stack is last-in first-out (LIFO). Therefore, it is expected behavior for the data to be inverted.
As far as I can tell, the only bug in your code is the garbage character at the start of the output. The reason for this is is probably that the loop condition
while (!feof(myFile))
is wrong. You may want to read this for further information:
Why is “while ( !feof (file) )” always wrong?
In that loop, you are using the return value of fgetc without first checking whether it is EOF. This check should be performed before casting the int return value to char, because the value EOF is not guaranteed to be representable as a char (it depends on the compiler), and in cases where it is, it would no longer be distinguishable from an actual character after casting it to char.
In the final loop iteration, the function fgetc will probably return EOF. You are casting this value to a char and interpreting it as a character code (although EOF is not a character code). This is probably why the last character pushed onto the stack is a garbage character. Consequently, the first character extracted from the stack will be this garbage character (because a stack is LIFO). This explains why the first character in your posted output is a garbage character.
In order to fix this, I recommend that you don't use
while (!feof(myFile))
as your loop condition, but rather move the fgetc function call into the loop condition, like this:
while ( ( equation = fgetc(myFile) ) != EOF )
However, to ensure that the variable equation is able to represent the value EOF, you must also change its type from char to int. Note that the return value of fgetc is of type int, not char, so it should not be converted to char until you have verified that it does not have the value EOF. Only after that can you be sure that it represents an actual character, and may convert the value to char.
Also note that the additional parentheses are necessary, because != has a higher operator precedence than =.
I was trying to write a function to swap nodes by value in a linked list. It actually works when nodes are not consecutive. But I get an infinite loop when I attempt to swap consecutive nodes. How can I solve this exceptional problem in my code?
#include <stdio.h>
#include <stdlib.h>
/* self-referential structure */
struct listNode {
char data; /* each listNode contains a character */
struct listNode *nextPtr; /* pointer to next node*/
};
typedef struct listNode ListNode; /* synonym for struct listNode */
typedef ListNode *ListNodePtr; /* synonym for ListNode* */
void swap( ListNodePtr *sPtr, char value1, char value2 )
{
ListNodePtr previousPtr1; /* pointer to previous node whose data is value1 */
ListNodePtr currentPtr1; /* pointer to node whose data is value1 */
ListNodePtr previousPtr2; /* pointer to previous node whose data is value2 */
ListNodePtr currentPtr2; /* pointer to node whose data is value2 */
previousPtr1 = NULL;
previousPtr2 = NULL;
currentPtr1 = *sPtr;
currentPtr2 = *sPtr;
/* attempt to find the node that contains value1 */
while( currentPtr1 != NULL && currentPtr1->data != value1 ) {
previousPtr1 = currentPtr1;
currentPtr1 = currentPtr1->nextPtr;
}
/* attempt to find the node that contains value2 */
while( currentPtr2 != NULL && currentPtr2->data != value2 ) {
previousPtr2 = currentPtr2;
currentPtr2 = currentPtr2->nextPtr;
}
if( currentPtr1 != NULL && currentPtr2 != NULL ) { /* both of the values are found */
if( previousPtr1 == NULL ) {
ListNodePtr tmpPtr = currentPtr1->nextPtr;
*sPtr = currentPtr2;
previousPtr2->nextPtr = currentPtr1;
currentPtr1->nextPtr = currentPtr2->nextPtr;
currentPtr2->nextPtr = tmpPtr;
}
else if ( previousPtr2 == NULL ) {
ListNodePtr tmpPtr = currentPtr2->nextPtr;
*sPtr = currentPtr1;
previousPtr1->nextPtr = currentPtr2;
currentPtr2->nextPtr = currentPtr1->nextPtr;
currentPtr1->nextPtr = tmpPtr;
}
else {
ListNodePtr tmpPtr = currentPtr2->nextPtr;
previousPtr1->nextPtr = currentPtr2;
currentPtr2->nextPtr = currentPtr1->nextPtr;
previousPtr2->nextPtr = currentPtr1;
currentPtr1->nextPtr = tmpPtr;
}
}
else { /* at least one of the values is not found */
printf("Not found!\n");
}
}
int main( void )
{
ListNodePtr startPtr = NULL; /* initially there are no nodes */
}
Obviously it's not all of the main function, there are little piece of codes that take input for this function and for lots of other functions such as like reverse in this code, but I don't have problem with them.
EDIT: I don't want to swap the values inside of the nodes. I want to swap actual nodes.
Your problem seems to be compounded by the declaration of unnecessary variables and the use of unnecessary values causing your code to become unnecessarily complex. If you consider that you're starting with the ListNodePtr *sPtr, and both of your loops are changing based on ListNodePtr * values, then you might realise that this algorithm can be better expressed using two variables initialised to sPtr, rather than four, two of which are initialised to NULL and the other two *sPtr.
ListNodePtr *x = sPtr,
*y = sPtr;
while (*x != NULL && (*x)->data != value1) {
x = &(*x)->nextPtr;
}
while (*y != NULL && (*y)->data != value2) {
y = &(*y)->nextPtr;
}
The benefit is two-fold:
Because of the initialisation to sPtr rather than NULL, you won't need to check if any of the variables are NULL later on (which seems to be contributing to the fogginess of deciding which values you need to swap).
It should be much clearer which values you need to swap, now, but in case it isn't: Swap *x and *y, swap (*x)->nextPtr and (*y)->nextPtr.
After finding the positions of the node to be swapped just write a simple swap routine like this-
void swap(struct listNode *a,struct listNode *b)
{
char t=a->data;
a->data=b->data;
b->data=t;
}
If you are swapping nodes by value then get the benefit out of it. Just swap the values.
Now in case you want to swap nodes-(not by value)
//p-first node to be swapped
//p1-prev node of p
//r-second node to be swapped
//r1-prev node of r
// a temporay listNode *
temp=r->link;
r->link=p->link;
p->link=temp;
if(p1!=NULL)
p1->link=r;
else
startpointer=r;
r1->link=p;
}
you should also consider using a premetive iterator instead of while loop.
ill give you an example:
/**
* Macro for iterating over a list.
*
* Declares a new variable to hold each element of the list.
* Use this macro for iterating through the list conveniently.
* Note that this mcaro modifies the internal iterator.
* For example, the following code will go through a list of strings and print
* them to the standard output:
* #code
* void printList(List listOfStrings) {
* LIST_FOREACH(char*, str, listOfStrings) {
* printf("%s\\n", str);
* }
* }
* #endcode
* #param type The type of the elements in the list
* #param iterator The name of the variable to hold the next list element
* #param list the list to iterate over
*/
#define LIST_FOREACH(type,iterator,list) \
for(type iterator = listGetFirst(list) ; \
iterator ;\
iterator = listGetNext(list))
listGetNext and listGetFirst are standart list getters functions.
it is a very premetive iterator, but for this kind of "heavy duty" works, i think it is a sufficent technique.
You Already find the two values corresponding address, in the linked list.
if ( cur_ptr1!=NULL && cur_ptr2!=NULL){
int temp_val=cur_ptr1->data ;
cur_ptr1->data=cur_ptr2->data ;
cur_ptr2->data = temp_val
}
Now the two values in the linked list are swapped.
Consider you have a nodes like
|1|->|2|->|3|->|4|->|5|->|6|->NULL
Now your going to swap the node 2 and 5. then we can just change the values like this
|1|->|5|->|3|->|4|->|2|->|6|->NULL
I'm almost done with this assignment, and it's killing me. This is my THIRD post about three different sections of this, and I'm honestly embarrassed that I'm struggling this much with the assignment.
The assignment itself is to make a program that performs addition and subtraction of big integers using linked lists (and I'm slowly starting to hate linked lists, outside of Lisp). Everything seems to be working now, save for the actual addition and subtraction. I'm not sure if it is the arithmetic functions, because they were sort of working before (but never 100%), but it doesn't hurt to check with the S/O community (normally I wouldn't ask for this much help on an assignment because I prefer to figure things out on my own, but this has been an awful and hectic week, and the deadline is fast approaching).
The arithmetic functions I've written are as follows, can anyone help me pick out what is wrong?
/*
* Function add
*
* #Paramater STRUCT* Integer
* #Parameter STRUCT* Integer
*
* Takes two linked lists representing
* big integers stored in reversed order,
* and returns a linked list containing
* the sum of the two integers.
*
* #Return STRUCT* Integer
*
* TODO Comment me
*/
struct integer* add( struct integer *p, struct integer *q )
{
int carry = 0;
struct integer *sHead, *sCurr;
struct integer *pHead, *qHead;
pHead = p;
qHead = q;
sHead = NULL;
while( p )
{
sCurr = ( struct integer* ) malloc (sizeof(struct integer));
sCurr->digit = p->digit + q->digit + carry;
sCurr->next = sHead;
sHead = sCurr;
carry = 0;
/*
* If the current digits sum to greater than 9,
* create a carry value and replace the current
* value with value mod 10.
*/
if( sCurr->digit > 9 )
{
carry = 1;
sCurr->digit = sCurr->digit % 10;
}
/*
* If the most significant digits of the numbers
* sum to 10 or greater, create an extra node
* at the end of the sum list and assign it the
* value of 1.
*/
if( carry == 1 && sCurr->next == NULL )
{
struct integer *sCarry = ( struct integer* ) malloc (sizeof(struct integer));
sCarry->digit = 1;
sCarry->next = NULL;
reverse( &sCurr );
sCurr->next = sCarry;
reverse( &sCurr );
}
p = p->next;
if( q->next ) q = q->next;
else q->digit = 0;
}
return sHead;
}
/*
* Function subtract
*
* #Parameter STRUCT* Integer
* #Parameter STRUCT* Integer
*
* Takes two linked lists representing struct integers.
* Traverses through the lists, subtracting each
* digits from the subsequent nodes to form a new
* struct integer, and then returns the newly formed
* linked list.
*
* #Return STRUCT* Integer
*
* TODO Comment me
*/
struct integer* subtract( struct integer *p, struct integer *q )
{
int borrow = 0;
struct integer *dHead, *dCurr;
struct integer *pHead, *qHead;
pHead = p;
qHead = q;
dHead = NULL;
while( p )
{
dCurr = (struct integer*) malloc (sizeof(struct integer));
if( q )
{
dCurr->digit = p->digit - q->digit - borrow;
}
else
{
dCurr->digit = p->digit - borrow;
}
dCurr->next = dHead;
if( dCurr->digit < 0 )
{
dCurr->digit += 10;
borrow = 1;
}
dHead = dCurr;
p = p->next;
if( q->next) q = q->next;
}
return dHead;
}
The sample output should look like this:
8888888888 + 2222222222 = 11111111110
10000000000 – 9999999999 = 1
10000000000 – 9999999999 = 1
but instead, it looks like this:
8888888888 + 2222222222 = 1111111110
10000000000 - 9999999999 = 10000000001
10000000000 - 9999999999 = 10000000001
EDIT The entire program, in its current form as of 3:30PM EST, is available here for reference, or in case these functions are not the issue.
else q->digit = 0;
You are changing the argument inside the function.
Try changing your functions to accept const arguments and recompile.
struct integer* add( const struct integer *p, const struct integer *q )
struct integer* subtract( const struct integer *p, const struct integer *q )
The part that reads
if( dCurr->next == NULL && carry == 1 )
{
struct integer *dCarry = (struct integer*) malloc (sizeof(struct integer));
dCarry->digit = -1;
dCarry->next = NULL;
dCurr->next = dCarry;
}
looks a bit out of place. From the code above, dCurr->next is set to be the digits we've already calculated in earlier loops, so it is only NULL on the first digit. I think you meant to check p->next instead.
I am assuming that the condition len(p) >= len(q) holds for this function. If not, you will have to do something about handling where it doesn't hold (running out of p nodes before you run out of q nodes). I also assume the digits are in the list from least significant digit to most significant one. If not, you may need to reverse p and q before you process them.
One other thing I can't figure out is how you handle negative numbers. Or even if you are supposed to handle them. It is not easy to add to a structure like this, because a naive approach of adding something to the end would not work when subtracting: when q is negative, you will go to all the trouble of subtracting q from p, and then discover that you should have added instead.
In function compare() you "walk" p and afterwards try to walk it again.
int compare( struct integer *p, struct integer *q )
{
/* ... */
while( p )
{
pCount++;
p = p->next;
}
p is now NULL
/* ... */
while( p )
{
/* ... */
}
The while loop never runs.
When compiling a program containing this particular function,
/*
* Function read_integer
*
* #Parameter CHAR* stringInt
*
* Parameter contains a string representing a struct integer.
* Tokenizes the string by each character, converts each char
* into an integer, and constructs a backwards linked list out
* of the digits.
*
* #Return STRUCT* Integer
*/
struct integer* read_integer( char* stringInt )
{
int i, n;
struct integer *curr, *head;
int numDigits = strlen( stringInt ); // Find the length of the struct integer
char *tok;
head = NULL;
for( i = 0; i < numDigits; i++ )
{
tok = strtok( stringInt, NULL ); // Tokenize the string by each char
n = atoi( tok[i] ); // Convert char to an integer
curr = (struct integer *) malloc (sizeof( struct integer )); // Allocate memory for node
curr->digit = n; // Digit of current node is assigned to n
curr->next = head; // Move to the next node in the list.
head = curr; // Move head up to the front of the list.
}
return head; // Return a pointer to the first node in the list.
}
I get the warning:
bigintII.c: In function ‘read_integer’:
bigintII.c:167: warning: passing argument 1 of ‘atoi’ makes pointer from integer without a cast
//usr/include/stdlib.h:148: note: expected ‘const char *’ but argument is of type ‘char’
I've tried a couple of different ways (that were mostly shots in the dark) to get rid of the warning, but to no avail. Can anybody point me in the right direction?
---///---
Original, dumb question below here, left because I don't want to be that guy.---
I'm trying to debug my assignment for CS1 so I can finish it and move onto something interesting (like working on my CLisp studies), but I've run into an error I can't get past. Now, I know the assignment isn't complete yet (i.e., it isn't going to do what I want it to even if I get it to run) but I don't want help with that (besides, what fun would that be?). If someone could just help me figure out why the following code, when compiled and executed, produces the useless (to me) Segmentation fault (core dumped), well, that'd be awesome.
/*
* File: struct integer.c
* Description: Assignment in using Linked Lists
* in order to perform struct integer addition and subtraction.
*
* Created on September 1, 2010, 11:38 AM
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// Constant Definitions
#define ADD 1
#define SUB 2
// Output file
char *fName = "out.txt";
FILE *outFile;
/*
* Create a prototype of a single
* node in the Linked List.
* Each node will represent a single
* integer comprising one part of a struct integer.
*/
struct integer
{
int digit;
struct integer *next;
};
// Function Prototypes
struct integer* read_integer( char *stringInt );
struct integer* add( struct integer *p, struct integer *q );
struct integer* subtract( struct integer *p, struct integer *q);
int compare( struct integer *p, struct integer *q );
void print( struct integer *p );
// Main function
int main( )
{
//Variable initialization
/*
* Initialize pointers to the linked lists.
* One, *head, will always point to the
* first element, the head, of the list.
* The other element, *curr, will point to the
* node currently being accessed, and will be
* used to traverse the list.
*/
struct integer* pHead;
struct integer* qHead;
struct integer* tHead; // Used to contain the total
int numOps, oper, i;
const char *fileName = "struct integer.txt";
char bigintstr[200];
FILE *inputFile;
// Open output file
outFile = fopen(fName, "a+");
// Open up the input file for reading
inputFile = fopen(fileName, "r");
// Read in the number of operations to be performed
fscanf(inputFile, "%d", &numOps);
/*
* For each operation that must be performed,
* construct a linked list for each of the
* struct integers in the file. Then, perform the operation
* indicated by the digit preceding them.
*/
for( i = 0; i < numOps; i++ )
{
// Read in the number that dictates operation
fscanf(inputFile, "%d", &oper);
// Read in the first struct integer into a string
fscanf(inputFile, "%s", bigintstr);
/*
* Pass the struct integer string to read_integer()
* in order to construct a linked list out of it.
*/
pHead = read_integer( bigintstr );
// Read in second struct integer into a string
fscanf(inputFile, "%s", bigintstr);
/*
* Pass the struct integer str to read_integer()
* in order to construct a linked list out of it.
*/
qHead = read_integer( bigintstr );
/*
* Depending on the operation to be performed,
* call the corresponding function.
*/
switch( oper )
{
case ADD:
tHead = add( pHead, qHead );
break;
case SUB:
tHead = subtract( pHead, qHead );
break;
default:
printf("Invalid operation parameter.\n");
}
print( pHead ); // Print out the first struct integer
fprintf(outFile, " + ");
print( qHead ); // Print out the second struct integer
fprintf(outFile, " = ");
print( tHead ); // Print out the sum/difference struct integer
fprintf(outFile, "\n"); // Move to next line for next instruction set
}
fclose(inputFile);
//system(PAUSE);
return 0;
}
// Function Definitions
/*
* Function read_integer
*
* #Parameter CHAR* stringInt
*
* Parameter contains a string representing a struct integer.
* Tokenizes the string by each character, converts each char
* into an integer, and constructs a backwards linked list out
* of the digits.
*
* #Return STRUCT* Integer
*/
struct integer* read_integer( char* stringInt )
{
int i, n;
struct integer *curr, *head;
int numDigits = strlen( stringInt ); // Find the length of the struct integer
char *tok;
head = NULL;
for( i = 0; i < numDigits; i++ )
{
tok = strtok( stringInt, NULL ); // Tokenize the string by each char
n = atoi( tok[i] ); // Convert char to an integer
curr = (struct integer *) malloc (sizeof( struct integer )); // Allocate memory for node
curr->digit = n; // Digit of current node is assigned to n
curr->next = head; // Move to the next node in the list.
head = curr; // Move head up to the front of the list.
}
return head; // Return a pointer to the first node in the list.
}
/*
* Function print
*
* #Parameter STRUCT* Integer
*
* Given a linked list, will traverse through
* the nodes and print out, one at a time,
* the digits comprising the struct integer that the
* linked list represents.
*
* TODO: Print to file
*/
void print( struct integer *p )
{
while( p )
{
fprintf(outFile, "%d", p->digit);
p = p->next;
}
}
/*
* Function add
*
* #Paramater STRUCT* Integer
* #Parameter STRUCT* Integer
*
* Takes two linked lists representing
* big integers stored in reversed order,
* and returns a linked list containing
* the sum of the two integers.
*
* #Return STRUCT* Integer
*
* TODO Comment me
*/
struct integer* add( struct integer *p, struct integer *q )
{
int carry = 0;
struct integer *sHead, *sCurr;
struct integer *pHead, *qHead;
pHead = p;
qHead = q;
sHead = NULL;
while( p )
{
sCurr = ( struct integer* ) malloc (sizeof(struct integer));
sCurr->digit = p->digit + q->digit + carry;
sCurr->next = sHead;
sHead = sCurr;
carry = 0;
/*
* If the current digits sum to greater than 9,
* create a carry value and replace the current
* value with value mod 10.
*/
if( sCurr->digit > 9 )
{
carry = 1;
sCurr->digit = sCurr->digit % 10;
}
/*
* If the most significant digits of the numbers
* sum to 10 or greater, create an extra node
* at the end of the sum list and assign it the
* value of 1.
*/
if( carry == 1 && sCurr->next == NULL )
{
struct integer *sCarry = ( struct integer* ) malloc (sizeof(struct integer));
sCarry->digit = 1;
sCarry->next = NULL;
sCurr->next = sCarry;
}
p = p->next;
q = q->next;
}
return sHead;
}
/*
* Function subtract
*
* #Parameter STRUCT* Integer
* #Parameter STRUCT* Integer
*
* Takes two linked lists representing struct integers.
* Traverses through the lists, subtracting each
* digits from the subsequent nodes to form a new
* struct integer, and then returns the newly formed
* linked list.
*
* #Return STRUCT* Integer
*
* TODO Comment me
*/
struct integer* subtract( struct integer *p, struct integer *q )
{
int carry = 0;
struct integer *dHead, *dCurr;
struct integer *pHead, *qHead;
pHead = p;
qHead = q;
dHead = NULL;
while( p )
{
dCurr = (struct integer*) malloc (sizeof(struct integer));
dCurr->digit = p->digit - q->digit - carry;
dCurr->next = dHead;
dHead = dCurr;
if( dCurr->digit < 0 )
{
dCurr->digit += 10;
carry = 1;
}
if( dCurr->next == NULL && carry == 1 )
{
struct integer *dCarry = (struct integer*) malloc (sizeof(struct integer));
dCarry->digit = -1;
dCarry->next = NULL;
dCurr->next = dCarry;
}
p = p->next;
q = q->next;
}
return dHead;
}
/*
* Function compare
*
* #Parameter STRUCT* Integer
* #Parameter STRUCT* Integer
*
* Takes in two linked lists representing struct integers.
* Traverses the lists one at a time, comparing the
* digits.
*
* Case: p < q
* #Return -1
*
* Case: p == q
* #Return 0
*
* Case: p > q
* #Return 1
*
* TODO Comment me
*/
int compare( struct integer *p, struct integer *q )
{
struct integer *pHead, *qHead;
int comp = 0;
pHead = p;
qHead = q;
while( p )
{
if( p->digit > q->digit )
{
comp = 1;
}
if( p->digit < q->digit )
{
comp = -1;
}
p = p->next;
q = q->next;
}
return comp;
}
I'm sorry that there's a lot to wade through, I'm just trying to get in the habit of over-documenting my code because I like to go back and read through stuff I've written to review concepts. The actual program itself is fairly straightforward, though (if not broken, haha).
compiling it with gcc gives this:
test.c: In function ‘read_integer’:
test.c:165: warning: passing argument 1 of ‘atoi’ makes pointer from integer without a cast
/usr/include/stdlib.h:148: note: expected ‘const char *’ but argument is of type ‘char’
this is 164/165
tok = strtok( stringInt, NULL ); // Tokenize the string by each char
n = atoi( tok[i] ); // Convert char to an integer
should be
n = stringInt - '0'; // Convert char to an integer
the tok variable is now pointless. it doesn't crash anymore with me, and it does find the correct answer(1 + 1 = 2),
furthermore you forgot to close outputFile at the end of your program.
and you apparently open the outfile in append mode(wich isn't bad, it just caught me by surprise)
then there's another inconsistency, your add function reverses the order in which your numbers are stored wich means that the input numbers are printed in reverse order whilst the anwer is printed in the correct order.
I fixed those now:
/*
* File: struct integer.c
* Description: Assignment in using Linked Lists
* in order to perform struct integer addition and subtraction.
*
* Created on September 1, 2010, 11:38 AM
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// Constant Definitions
#define ADD 1
#define SUB 2
// Output file
char *fName = "out.txt";
FILE *outFile;
/*
* Create a prototype of a single
* node in the Linked List.
* Each node will represent a single
* integer comprising one part of a struct integer.
*/
struct integer
{
int digit;
struct integer *next;
};
// Function Prototypes
struct integer* read_integer( char *stringInt );
struct integer* add( struct integer *p, struct integer *q );
struct integer* subtract( struct integer *p, struct integer *q);
int compare( struct integer *p, struct integer *q );
void print( struct integer *p );
// Main function
int main( )
{
//Variable initialization
/*
* Initialize pointers to the linked lists.
* One, *head, will always point to the
* first element, the head, of the list.
* The other element, *curr, will point to the
* node currently being accessed, and will be
* used to traverse the list.
*/
struct integer* pHead;
struct integer* qHead;
struct integer* tHead; // Used to contain the total
int numOps, oper, i;
const char *fileName = "struct_integer.txt";
char bigintstr[200];
FILE *inputFile;
// Open output file
outFile = fopen(fName, "a+");
// Open up the input file for reading
inputFile = fopen(fileName, "r");
// Read in the number of operations to be performed
fscanf(inputFile, "%d", &numOps);
/*
* For each operation that must be performed,
* construct a linked list for each of the
* struct integers in the file. Then, perform the operation
* indicated by the digit preceding them.
*/
for( i = 0; i < numOps; i++ )
{
// Read in the number that dictates operation
fscanf(inputFile, "%d", &oper);
// Read in the first struct integer into a string
fscanf(inputFile, "%s", bigintstr);
/*
* Pass the struct integer string to read_integer()
* in order to construct a linked list out of it.
*/
pHead = read_integer( bigintstr );
// Read in second struct integer into a string
fscanf(inputFile, "%s", bigintstr);
/*
* Pass the struct integer str to read_integer()
* in order to construct a linked list out of it.
*/
qHead = read_integer( bigintstr );
/*
* Depending on the operation to be performed,
* call the corresponding function.
*/
switch( oper )
{
case ADD:
tHead = add( pHead, qHead );
break;
case SUB:
tHead = subtract( pHead, qHead );
break;
default:
printf("Invalid operation parameter.\n");
}
print( pHead ); // Print out the first struct integer
fprintf(outFile, " + ");
print( qHead ); // Print out the second struct integer
fprintf(outFile, " = ");
print( tHead ); // Print out the sum/difference struct integer
fprintf(outFile, "\n"); // Move to next line for next instruction set
}
fclose(inputFile);
fclose(outFile);
//system(PAUSE);
return 0;
}
// Function Definitions
/*
* Function read_integer
*
* #Parameter CHAR* stringInt
*
* Parameter contains a string representing a struct integer.
* Tokenizes the string by each character, converts each char
* into an integer, and constructs a backwards linked list out
* of the digits.
*
* #Return STRUCT* Integer
*/
struct integer* read_integer( char* stringInt )
{
int i, n;
struct integer *curr, *head;
int numDigits = strlen( stringInt ); // Find the length of the struct integer
char *tok;
head = NULL;
for( i = 0; i < numDigits; i++ )
{
n = stringInt[i] - '0'; // Convert char to an integer
curr = (struct integer *) malloc (sizeof( struct integer )); // Allocate memory for node
curr->digit = n; // Digit of current node is assigned to n
curr->next = head; // Move to the next node in the list.
head = curr; // Move head up to the front of the list.
}
return head; // Return a pointer to the first node in the list.
}
void reverse (struct integer **p){
if((*p)->next==0) return;
struct integer *i=*p,*j;
while(i->next){
j=i;
i=i->next;
}//i is now the tail;
i->next=j;
j->next=0;
reverse(p);
*p=i;
}
/*
* Function print
*
* #Parameter STRUCT* Integer
*
* Given a linked list, will traverse through
* the nodes and print out, one at a time,
* the digits comprising the struct integer that the
* linked list represents.
*
* TODO: Print to file
*/
void print( struct integer *p )
{
struct integer *head=p;
reverse(&p);
while( p )
{
fprintf(outFile, "%d", p->digit);
p = p->next;
}
reverse(&head);
}
/*
* Function add
*
* #Paramater STRUCT* Integer
* #Parameter STRUCT* Integer
*
* Takes two linked lists representing
* big integers stored in reversed order,
* and returns a linked list containing
* the sum of the two integers.
*
* #Return STRUCT* Integer
*
* TODO Comment me
*/
struct integer* add( struct integer *p, struct integer *q )
{
int carry = 0;
struct integer *sHead, *sCurr;
struct integer *pHead, *qHead;
pHead = p;
qHead = q;
sHead = NULL;
while( p )
{
sCurr = ( struct integer* ) malloc (sizeof(struct integer));
sCurr->digit = p->digit + q->digit + carry;
sCurr->next = sHead;
sHead = sCurr;
carry = 0;
/*
* If the current digits sum to greater than 9,
* create a carry value and replace the current
* value with value mod 10.
*/
if( sCurr->digit > 9 )
{
carry = 1;
sCurr->digit = sCurr->digit % 10;
}
/*
* If the most significant digits of the numbers
* sum to 10 or greater, create an extra node
* at the end of the sum list and assign it the
* value of 1.
*/
if( carry == 1 && sCurr->next == NULL )
{
struct integer *sCarry = ( struct integer* ) malloc (sizeof(struct integer));
sCarry->digit = 1;
sCarry->next = NULL;
sCurr->next = sCarry;
}
p = p->next;
q = q->next;
}
reverse(&sHead);
return sHead;
}
/*
* Function subtract
*
* #Parameter STRUCT* Integer
* #Parameter STRUCT* Integer
*
* Takes two linked lists representing struct integers.
* Traverses through the lists, subtracting each
* digits from the subsequent nodes to form a new
* struct integer, and then returns the newly formed
* linked list.
*
* #Return STRUCT* Integer
*
* TODO Comment me
*/
struct integer* subtract( struct integer *p, struct integer *q )
{
int carry = 0;
struct integer *dHead, *dCurr;
struct integer *pHead, *qHead;
pHead = p;
qHead = q;
dHead = NULL;
while( p )
{
dCurr = (struct integer*) malloc (sizeof(struct integer));
dCurr->digit = p->digit - q->digit - carry;
dCurr->next = dHead;
dHead = dCurr;
if( dCurr->digit < 0 )
{
dCurr->digit += 10;
carry = 1;
}
if( dCurr->next == NULL && carry == 1 )
{
struct integer *dCarry = (struct integer*) malloc (sizeof(struct integer));
dCarry->digit = -1;
dCarry->next = NULL;
dCurr->next = dCarry;
}
p = p->next;
q = q->next;
}
return dHead;
}
/*
* Function compare
*
* #Parameter STRUCT* Integer
* #Parameter STRUCT* Integer
*
* Takes in two linked lists representing struct integers.
* Traverses the lists one at a time, comparing the
* digits.
*
* Case: p < q
* #Return -1
*
* Case: p == q
* #Return 0
*
* Case: p > q
* #Return 1
*
* TODO Comment me
*/
int compare( struct integer *p, struct integer *q )
{
struct integer *pHead, *qHead;
int comp = 0;
pHead = p;
qHead = q;
while( p )
{
if( p->digit > q->digit )
{
comp = 1;
}
if( p->digit < q->digit )
{
comp = -1;
}
p = p->next;
q = q->next;
}
return comp;
}
i wrote reverse for you:
void reverse (struct integer **p){
if((*p)->next==0) return;
struct integer *i=*p,*j;
while(i->next){
j=i;
i=i->next;
}//i is now the tail;
// 1->2->3->4->NIL
i->next=j;
// 1 -> 2 -> 3 <-> 4
j->next=0;
// 1 -> 3 -> 3 <- 4
// |
// v
// NIL
reverse(p);// p looks like 1 -> 2 -> 3 now recurse
*p=i;
}
Your problem is caused by passing the wrong thing to atoi. atoi expects a string, which as you know in C is a char pointer. You're passing a single char, which is not a char pointer. atoi attempts to treat the value of the character as a memory address, which is almost certainly an address you're not allowed to access, so your program goes bang.
To get the numerical value of a char containing an ASCII digit, subtract '0' from it, ie change
n = atoi( tok[i] );
to
n = tok[i] - '0';
But you don't need strtok:
for (i = 0; i < numDigits; i++) {
n = stringInt[i] - '0';
// etc
}
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