Insight into something.
|
Assignment : |
|
|
Source Code : |
|
|
Compiled Executables : |
|
|
Documentation : |
|
|
Sample Test Files : |
////////////////////////////////////////////////////////////////////////////////
///
/// \file bigint2.c
/// \brief Adds or subtracts very large numbers from a formatted file using
/// linked lists, and outputs the result to a file.
///
/// <br>Author(s): Nicholas Guthrie
/// <br>Created: 06 February 2011
/// <br>Email: nickguthrie@knights.ucf.edu
/// <br>Web: http://nickguthrie.com
/// <br>Title: Big Integers (Linked List Version)
/// <br>Course: COP3502C Computer Science I
/// <br> Class #: 16173
/// <br>Section #: 0001
///
/// THIS SOFTWARE IS PROVIDED BY THE NICHOLAS GUTHRIE''AS IS'' AND ANY EXPRESS
/// OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
/// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
/// NO EVENT SHALL UCF BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
/// EXEMPLARY,OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
/// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
/// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
/// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
/// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
/// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
///
////////////////////////////////////////////////////////////////////////////////
# define _CRT_SECURE_NO_WARNINGS 1
////////////////////
// Includes //
////////////////////
#include<stdio.h>
#include<stdlib.h> //necessary for malloc
#include<string.h>
////////////////////
// Structures //
////////////////////
struct integer
{
int digits; /**< value of digit */
struct integer *next; /**< pointer to next digit */
};
/////////////////////////
// Function Prototypes //
/////////////////////////
struct integer* convert_integer(char* stringInt);
void print(FILE *ntw, struct integer *p);
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);
struct integer* addToFront(struct integer *list, int value);
struct integer* addToEnd(struct integer *list, int value);
struct integer* delZero(struct integer *list);
void freeInteger(struct integer *ptr);
////////////////////
// Main //
////////////////////
int main(){
/////////////////
// Variables //
/////////////////
FILE *input, *output; /**< input & output streams */
char itemp[201]; /**< number collection */
int i, j; /**< navigation */
int repeat; /**< number of equations in file */
int operation; /**< stores +/- as int, +=1, -=2 */
char op; /**< stores +/- as char */
int reverse; /**< true if #s should reverse for printing */
int big, small; /**< used as input parameters */
////////////////////
// Initilizations //
////////////////////
struct integer * data[3];
////////////////////
// File I/O //
////////////////////
input = fopen ("bigint.txt", "r");
//file open error checking
if(input == NULL)
{
printf("File not Found, Press ENTER to exit\n");
getchar();
return 0;
}
output = fopen("out.txt", "w");
//scan first int in file to determine number of equations to solve
fscanf(input, "%d", &repeat);
for(i = 0; i<repeat; i++)
{
fscanf(input, "%d", &operation); //collect operation (+/-)
//store +/- based on input
if(operation == 2)
op = '-';
else
op = '+';
//collect big numbers
for(j = 0; j<2; j++)
{
fscanf(input, "%s", itemp); //collect big numer as string
data[j] = convert_integer(itemp); //convert big number string to ints
}
//determine which file is bigger & configure flag reverse if necessary
if(compare(data[0],data[1]) == -1)
{
big = 1;
small = 0;
reverse = 1;
}
//for adding keep the numbers as they are in the file
else
{
big = 0;
small = 1;
reverse = 0;
}
//addition
if(operation == 1)
{
data[2] = add(data[big],data[small]);
//prepare for printing
if(reverse == 1)
{
big = 0;
small = 1;
}
}
//subtraction
else if(operation == 2)
data[2] = subtract(data[big],data[small]);
////////////////////
// Print to File //
////////////////////
print(output, data[big]);
fprintf(output, " %c ", op);
print(output, data[small]);
fprintf(output, " = ");
print(output, data[2]);
fprintf(output, "\n");
//free memory
for(j = 0; j<3; j++)
{
freeInteger(data[j]);
}
}
//close files and exit program
fclose(input);
fclose(output);
return 0;
}
////////////////////////////////////////////////////////////////////////////////
///
/// \brief frees the memory allocated in an integer structure
///
/// \param[in] pointer to a integer structure
///
/// \return void
///
////////////////////////////////////////////////////////////////////////////////
void freeInteger(struct integer *ptr)
{
struct integer *temp = ptr;
if (temp) {
freeInteger(temp->next);
free(ptr);
}
}
////////////////////////////////////////////////////////////////////////////////
///
/// \brief adds a number to the front of a dynamic list
///
/// \param[in] pointer pointer to an integer structure
/// \param[in] value to add to beginning of list
///
/// \return pointer to a struct Integer
///
////////////////////////////////////////////////////////////////////////////////
struct integer* addToFront(struct integer *list, int value)
{
// Create the new node and store argument date in it
struct integer * pNew = (struct integer *) malloc(sizeof(struct integer));
pNew->digits = value;
pNew->next = NULL;
//IF the list is empty, set the original head ptr to point to the new node
if(list == NULL)
{
list = pNew;
}
else
{
//point the new node to wherever the head pointer points to
pNew->next = list;
//point the head pointer to the new node
list = pNew;
}
return list;
}
////////////////////////////////////////////////////////////////////////////////
///
/// \brief adds a number to the end of a dynamic list
///
/// \param[in] pointer pointer to an integer structure
/// \param[in] value to add to end of list
///
/// \return pointer to a struct Integer
///
////////////////////////////////////////////////////////////////////////////////
struct integer* addToEnd(struct integer *list, int value)
{
struct integer *help_ptr = list; /**< helper pointer for navigation */
struct integer *pNew = (struct integer *) malloc(sizeof(struct integer));
pNew->digits = value;
pNew->next = NULL;
//if the list is empty, pNew becomes the first node
if (list == NULL)
{
return pNew;
}
//otherwise, traverse the list and arrive at the last node
while (help_ptr->next !=NULL)
{
help_ptr = help_ptr->next;
}
//make the last node point to the insertion node
help_ptr->next = pNew;
return list;
}
////////////////////////////////////////////////////////////////////////////////
///
/// \brief deletes all the leading zeros in a struct Integer
///
/// \param[in] pointer pointer to a struct Integer
///
/// \return pointer to a struct Integer
///
////////////////////////////////////////////////////////////////////////////////
struct integer* delZero(struct integer *list)
{
struct integer *help_ptr, *node2delZero;
help_ptr = list;
while(help_ptr->next != NULL)
{
if(help_ptr->next->next == NULL && help_ptr->next->digits == 0)
{
node2delZero = help_ptr->next;
help_ptr->next = NULL;
free(node2delZero);
if(help_ptr->digits == 0)
{
return delZero(list);
}
}
else{
help_ptr = help_ptr->next;
}
}
return list;
}
////////////////////////////////////////////////////////////////////////////////
///
/// \brief reads the digits of the large integer, character by character, and
/// converts them into integers.
///
/// \param[in] string with only digits, does not start with 0, < 200 char long
///
/// \return pointer to a struct Integer
///
////////////////////////////////////////////////////////////////////////////////
struct integer* convert_integer(char* stringInt)
{
struct integer* data = NULL;
//navigation variables
int i;
int length = strlen(stringInt);
//convert char to int and store result
for(i = 0; i<length; i++)
{
data = addToFront(data, (int)stringInt[i]-'0');
}
return data;
}
////////////////////////////////////////////////////////////////////////////////
///
/// \brief prints out a big integer
///
/// \param[in] pointer to a struct Integer to print
///
////////////////////////////////////////////////////////////////////////////////
void print(FILE *input, struct integer *p)
{
if(p->next != NULL)
{
print(input, p->next);
}
fprintf(input, "%d", p->digits);
}
////////////////////////////////////////////////////////////////////////////////
///
/// \brief adds two struct Integers and returns the result as a new Integer
///
/// \param[in] pointer to a struct Integer to add
/// \param[in] pointer to a struct Integer to add
///
/// \return pointer to a struct Integer which is the sum of both params
///
////////////////////////////////////////////////////////////////////////////////
struct integer* add(struct integer *p, struct integer *q)
{
struct integer* solution = NULL; /**< output data */
struct integer* big = p; /**< store the head of the big number */
struct integer* small = q; /**< store the head of the small number */
int result, remainder = 0;
//do for all elements of the larger number
while(big !=NULL)
{
//do for all elements of the smaller number
if(small != NULL)
{
result = big->digits + small->digits + remainder;
solution = addToEnd(solution, result%10);
small = small->next;
}
//do when no more elements left in the smaller number
else
{
result = big->digits+remainder;
solution = addToEnd(solution, result%10);
}
big = big->next;
//handle remainders
if(result > 9)
{
remainder = 1; /**< if the result is > 9 carry the one */
}
else
{
remainder = 0; /**< the result <= 9, do not carry the one */
}
}
//case where there is a remainder and a digit remaining
if(remainder == 1)
{
solution = addToEnd(solution, 1);
}
return solution;
}
////////////////////////////////////////////////////////////////////////////////
///
/// \brief 2nd param is subtracted from the first and the result is returned.
///
/// \param[in] pointer to a struct Integer, >= 2nd param
/// \param[in] pointer to a struct Integer to subtract from first param
///
/// \return pointer to a struct Integer which is the result of subtraction
///
////////////////////////////////////////////////////////////////////////////////
struct integer* subtract(struct integer *p, struct integer *q)
{
struct integer* solution = NULL;
struct integer* big = p; /**< store the head of the big number */
struct integer* small = q; /**< store the head of the small number */
//navigation variables
int remainder = 0;
int btemp;
while(big != NULL)
{
btemp = big->digits;
//handle remainder & big
//big > 1, use 0
if(remainder == 1)
{
if(btemp - 1 >=0)
{
btemp--;
remainder = 0;
}
//big = 0, borrow from next digit
else
{
btemp=9;
}
}
//if the current position is greater than the size of the smaller number
if(small != NULL)
{
//calculate values
if(btemp - small->digits >= 0)
{
solution = addToEnd(solution, btemp - small->digits);
}
else
{
solution = addToEnd(solution, btemp - small->digits+10);
remainder = 1;
}
small = small->next;
}
//no more q digits to subtract
else
{
if(btemp >= 0)
{
solution = addToEnd(solution, btemp);
}
else
{
solution = addToEnd(solution, btemp +10);
remainder = 1;
}
}
big = big->next;
}
//remove leading 0s
solution = delZero(solution);
return solution;
}
////////////////////////////////////////////////////////////////////////////////
///
/// \brief Determines which struct Integer has a larger value
///
/// \param[in] pointer to a struct Integer, >= 2nd param
/// \param[in] pointer to a struct Integer to subtract from first param
///
/// \return -1 if first > second
/// 0 if first = second
/// +1 if first > second
///
////////////////////////////////////////////////////////////////////////////////
int compare(struct integer *p, struct integer *q)
{
//base case where the next node on the array is null
//this means the numbers have the same # of digits
if(p->next == NULL && q->next == NULL)
{
//then p is definitively > q
if(p->digits > q->digits)
{
return 1;
}
//then p is definitively < q
else if(p->digits < q->digits)
{
return -1;
}
//p and q might be equal
else if(p->digits == q->digits)
{
return 0;
}
}
//p has more digits, therefore p > q
else if(p->next == NULL && q->next != NULL)
{
return -1;
}
//q has more digits, therefore p < q
else if(q->next == NULL && p->next !=NULL)
{
return 1;
}
//current node is not the last node
else
{
//recurse until last node is found
switch (compare(p->next, q->next))
{
//all higher nodes are equal
case 0:
{
//if p>q, p is definitively greater
if(p->digits > q->digits)
{
return 1;
}
//if p<q, q is definitively greater
else if(p->digits < q->digits)
{
return -1;
}
//they are still equal up unto this digit
else if(p->digits == q->digits)
{
return 0;
}
}
//if -1 was returned, q is definitively greater
case -1:
{
return -1;
}
//if 1 was returned, p is definitively greater
case 1:
{
return 1;
}
}
}
}