I am finished with my first assignment in a C prog 2 class. I am going to post it here and hopefully get some constructive criticism. This program is nothing really to shout about...adds and subtracts arbitrarily large numbers, not designed to handle negative numbers. I know that there is nothing earthshattering in here, but I have definitely learned a lot in the past two weeks. If some of you programming masters can take a look and provide me with some constructive criticism it would be much appreciated.

I will also attach this as a .c file

I am trying to improve my knowledge of C and programming in general, feel free to be brutal.


Code:
// Wes Kendrick
// BIGINT.C
// THIS PROGRAMS ALLOWS FOR SIMPLE MANIPULATION OF LARGE INTEGERS.
// THE USER CAN ADD, OR SUBTRACT TWO LARGE INTEGERS INPUT FROM THE KEYBOARD
// THIS PROGRAM DOES NOT ALLOW FOR A NEGATIVE RESULT. THE SMALLER NUMBER WILL
// ALWAYS BE SUBTRACTED FROM THE LARGER NUMBER WHEN SUBTRACTION IS THE OPERATION
// DESIRED

// This program was written in Dev-C++ 4.9.9.2, and is written strictly for use
// on a PC. Not all functions used are assumed to be ANSI C

#include <stdio.h>
#include <stdlib.h>
#define TRUE 1
#define FALSE 0
#define ADD 1
#define SUBTRACT 2
#define QUIT 3
#define MAX 200


//Preconditions: the first parameter is string that stores
//               only contains digits, doesn't start with
//               0, and is 200 or fewer characters long.
//Postconditions: The function will read the digits of the
//	large integer character by character, 
//	convert them into integers and place them in 
//	nodes of a linked list. The pointer to the 
//	head of the list is returned.

struct integer* read_integer();

//Preconditions: p is a pointer to a big integer, stored in
//               reverse order, least to most significant 
//               digit, with no leading zeros.
//Postconditions: The big integer pointed to by p is 
//                printed out.
void print_bigint(struct integer *p);

//Preconditions: p and q are pointers to big integers, 
//               stored in reverse order, least to most 
//               significant digit, with no leading zeros.
//Postconditions: A new big integer is created that stores
//                the sum of the integers pointed to by p
//                and q and a pointer to it is returned.
struct integer* add(struct integer *p, struct integer *q);

//Preconditions: p and q are pointers to big integers, 
//               stored in reverse order, least to most 
//               significant digit, with no leading zeros.
//Postconditions: A new big integer is created that stores
//                the absolute value of the difference 
//                between the two and a pointer to this is
//                returned.
struct integer* subtract(struct integer *p, struct integer *q);

//Preconditions: Both parameters of the function are 
//	pointers to struct integer. 
//Postconditions: The function compares the digits of two 
//	numbers recursively and returns: 
//    -1 if the first number is smaller than the second, 
//     0 if the first number is equal to the second number,
//   1 if the first number is greater than the second.  
int compare(struct integer *p, struct integer *q);

//Preconditions: Both parameters point to struct integer
//Postconditions: Prints spaces so that the numbers are 
//                aligned to the right

//Preconditions: p, q, and answer point to struct integer, operation is
//               the operation to be performed
//Postconditions: Formats the output

void format_output(struct integer *p, struct integer *q, struct integer *answer, int operation);

//Preconditions: choice, low, and high are all int...low is low bound of
//               acceptable input, high is high bound
//Postconditions: Returns TRUE if input is valid, otherwise returns FALSE

int valid_choice(int choice, int low, int high);

//Preconditions: None
//Postconditions: Retrieves the user choice from the keyboard and returns it
int get_user_choice();

//Preconditions: how_many is an int, character is a char
//Postconditions: prints out character how_many times

void print_characters(int how_many, char character);

//Preconditions: answer is of type struct integer, it has at least one
//               leading zero (because method of complements is used for 
//               subtraction.)
//Postconditions: All leading zeroes are removed, and the size
//                of answer is adjusted accordingly

void remove_zeroes(struct integer *answer);

struct integer
{
    int *digits;
    int size;
};


int main()
{
    int choice, operation;
    struct integer *bigint1,*bigint2,*answer;

// Run until user chooses to quit

    do
    {
        choice=get_user_choice();
        if(choice !=QUIT)
        {
            system("CLS");
            printf("Please enter the first number: ");
            bigint1=read_integer();
            printf("\nPlease enter the second number: ");
            bigint2=read_integer();

// Executes users choice

            switch(choice)
            {
                case ADD:
                     answer = add(bigint1,bigint2);
                     operation=ADD;
                     break;
                
                case SUBTRACT:
                     answer = subtract(bigint1,bigint2);
                     operation=SUBTRACT;
                     break;
            } // End switch
            
            format_output(bigint1,bigint2,answer,operation);
            system("PAUSE");
            
// Frees memory
            
            free(bigint1);
            free(bigint2);
            free(answer);
        }
    }
    while(choice!=QUIT);

// End program

    printf("\n\nThank you for using the Big Int calculator!\n\n\n");
    system("PAUSE");
    return 0;
}

int get_user_choice()
{
    int choice;
    system("CLS");
    do
    {
        printf("1. Add two large integers\n2. Subtract two large integers\n3. Quit\n");
        printf("\n\nEnter the number corresponding to your choice: ");
        scanf("%d",&choice);
       
    }

// Checks for valid input in the while loop

    while(valid_choice(choice,1,3)==FALSE);
    return choice;
}

int valid_choice(int choice, int low, int high)
{
    
// Checks entry against bounds
    
    if(choice<low || choice > high)
    {
        printf("\n\nThat is invalid input.\n\n\n");
        return FALSE;
    }
    else
        return TRUE;
}

struct integer* read_integer()
{

// Temporary string is created to read in the number from the user

   char string_num[MAX];

// Allocates memory for the struct integer, the address of this will be returned

   struct integer *temp= (struct integer *)malloc(sizeof(struct integer));
   int counter;

// Reads string

   scanf("%s",string_num);

// Sets the size of the "integer"

   temp->size=strlen(string_num);

// Dynamically allocates memory for the array of int

   temp->digits=(int *)(malloc((temp->size*sizeof(int))));

// Subtracts '0' from the character to get the digit...numbers are stored
// with the least signifigant digit in index 0...this makes the code
// slightly simpler 

   for(counter=temp->size-1;counter>=0;counter--)
       temp->digits[temp->size-1-counter]=string_num[counter]-'0';
   return temp;
}

struct integer* add(struct integer *p, struct integer *q)
{

// Allocates integer

    struct integer *answer=malloc(sizeof(struct integer));
    int counter, carry=0;

// If p is bigger than q, size the array in answer to the size of p

    if(compare(p,q)==1)
    {
        answer->size=p->size;

// To simplify the code, we reallocate memory to the smaller number and set its
// size to the size of the bigger one (if they are the same number of digits, nothing
// happens

        q->digits=realloc(q->digits,p->size*sizeof(int));

        for(counter=q->size; counter < p-> size; counter++)
        {
            q->digits[counter]=0;
        }
    }

// Q is bigger, repeat process as above, but switch p and q

    else
    {
        answer->size=q->size;
        if(q->size != p->size)
        {
            p->digits=realloc(p->digits,q->size*sizeof(int));
            for(counter=p->size;counter< q->size;counter++)
                p->digits[counter]=0;
        }
    }

// Allocates enough memory for the array of int inside answer

    answer->digits=(int *) malloc(answer->size*sizeof(int));

// Runs counter for entire length of answer

    for(counter=0;counter< (answer->size);counter++)
    {
    
// Sets answer->digits[counter] to the sum of the digit in the same index position
// of q and p, as well as "carry" which is initialized to zero    
    
        answer->digits[counter]=p->digits[counter]+q->digits[counter] + carry;

// Number is greater than 9...must be reduced and reset carry

        if(answer->digits[counter]>9)
        {
            answer->digits[counter]%=10;
            carry=1;
        }
        else

// Carry is zero, answer->digits[counter] is less than 10

            carry=0;
    }

// End of the for-loop, if carry is still 1, reallocate the size of answer->digits
// to answer->size+1, and increment answer->size

    if(carry==1)
    {

// turns digit from > 10

        answer->size++;
        answer->digits=realloc(answer->digits,answer->size*sizeof(int));

// Will never be greater than one...(worst case example: 999+999 = 1998 (4 digits, leading 1)

        answer->digits[(answer->size-1)]=1;
    }
    
// Reallocate p and q to their original sizes, only the added zeroes will be removed

    p->digits=realloc(p->digits,p->size*sizeof(int));
    q->digits=realloc(q->digits,q->size*sizeof(int));

// address of answre is returned

    return answer;
}
            
struct integer* subtract(struct integer *p, struct integer *q)
{
    
// COMPLEMENTS stores the nines complement of a digit 0-9    
    
    int COMPLEMENTS[10], counter, difference;//, not_a_leading_zero, how_big_answer;
    
// Required for complement method of subtraction, to add one to the result
// This segment sets the attributes of one
    
    struct integer *one= (struct integer *)(malloc(sizeof(struct integer)));
    one->size=1;
    one->digits=(int *)(malloc(one->size*sizeof(int)));
    one->digits[0]=1;

// Nines complement will hold the nines complement of the smaller number

    struct integer *nines_complement=(struct integer *)(malloc(sizeof(struct integer)));
    struct integer *answer;

// Initializes the nines complement of digits 0-9

    for(counter=0;counter<10;counter++)
    {
        COMPLEMENTS[counter]=9-counter;
    }
    
// If p > q    
    
    if(compare(p,q)==1)
    {

// Difference will represent the number of additional digits that must
// be added to make both numbers the same size

        difference=p->size - q->size;

// sets nines_complement->size to the bigger numbers size

        nines_complement->size=p->size;

// Allocates memory for the int array inside nines_complement

        nines_complement->digits=(int *)(malloc(nines_complement->size*sizeof(int)));

// Sets all "unaccounted for digits" to 9...counter stops when it equals the difference in 
// size between nines_complement and the smaller number

        for(counter=nines_complement->size-1;counter>=(nines_complement->size-difference);counter--)
        {
            nines_complement->digits[counter]=9;
        }

// sets the rest of the "accounted for digits" to the respective digit in the smaller of
// the two numbers (in this case q)

        for(counter=nines_complement->size-difference-1;counter>=0;counter--)
        {
            nines_complement->digits[counter]=COMPLEMENTS[q->digits[counter]];
        }
        
// This is the method of complements, the intermediate step answer is set to 
// the sum of the larger number and the nines complement of the smaller number
        
        answer=add(nines_complement,p);
    }

// In this case, p is smaller (or equal to) q...same logic as above except the 
// p's and q's have been switched

    else
    {
        difference=q->size - p->size;
        nines_complement->size=q->size;
        nines_complement->digits=(int *)(malloc(nines_complement->size*sizeof(int)));
        for(counter=nines_complement->size-1;counter>=(nines_complement->size-difference);counter--)
        {
         
            nines_complement->digits[counter]=9;
        }
        for(counter=nines_complement->size-difference-1;counter>=0;counter--)
        {
            nines_complement->digits[counter]=COMPLEMENTS[p->digits[counter]];
        }
        
        answer=add(nines_complement,q);
    }

// Second to last step of complements method, one is added to answer

    answer=add(answer,one);

// Finished with nines_complement and one

    free(nines_complement);
    free(one);

// We know that the size of answer has been incremented by one, and this new 
// digit holds a 1...final step of this algorithm is to remove the one.

    answer->digits[(answer->size-1)]=0;
    
// Removes leading zeroes from answer    
    
    remove_zeroes(answer);
    return answer;
}

void remove_zeroes(struct integer *answer)
{
    
// First digit will be a zero
    
    int not_a_leading_zero=0, counter;

// Runs until counter > 0 because if answer is 0 we want it left that way

    for(counter=answer->size-1;counter>0;counter--)
    {
        if(answer->digits[counter]==0 && not_a_leading_zero==0)

// Size of answer is smaller

            answer->size--;
        else
            not_a_leading_zero=1;
    }

// Reallocate memory for answer, only the leading zeroes will be removed

    answer->digits=realloc(answer->digits,answer->size*sizeof(int));
}

void print_bigint(struct integer *p)
{ 
    int counter;
 
// Since the number is stored in reverse order, we print it out in reverse order
// to get the number as it should appear
 
    for(counter=p->size-1;counter>=0;counter--)
    {
        printf("%d",p->digits[counter]);
    }
}        
        
int compare(struct integer *p, struct integer *q)
{
    int counter;

// If p has more digits then it is larger

    if(p->size>q->size)
        return 1;

// if p has fewer digits then p is smaller

    if(p->size<q->size)
        return -1;

    for(counter=q->size-1;counter>=0;counter--)
    {

// If any digit from p is greater than the digit in the same place of q
// is larger, then p is larger

        if(p->digits[counter]>q->digits[counter])
            return 1;

// If any digit from q is greater than the digit in the same place of p
// then q is larger

        if(q->digits[counter]>p->digits[counter])
            return -1;
    }

// Digits are equal

    return 0;
}

void format_output(struct integer *p, struct integer *q, struct integer *answer, 
                   int operation)
{
     int counter, difference=0;    
     printf("\n");
     switch(operation)
     {
         case ADD: 
      
// If p is greater than q, then print p and print spaces equal to the 
// difference in size of p and q...this is strictly aesthetic      
      
              if(compare(p,q)==1)
              {
                  print_bigint(p);
                  printf("\n+\n");
                  print_characters(p->size-q->size,' ');
                  print_bigint(q);
              }
              else
              {

// If q is larger, then we print spaces, then print p, then print q

                  print_characters(q->size-p->size, ' ');
                  print_bigint(p);
                  printf("\n+\n");
                  print_bigint(q);
              }
              printf("\n");
              print_characters(answer->size,'-');
              break;

// The specs for the program do not allow for negative numbers...this uses
// the same logic as above, only prints the larger number on top of the smaller
// number. Since the result of subtraction can have a variety of sizes, we set
// difference to the larger numbers size minus the size of the answer

         case SUBTRACT:
              if(compare(p,q)==1)
              {
                  print_bigint(p);
                  printf("\n-\n");
                  print_characters(p->size-q->size,' ');
                  print_bigint(q);
                  printf("\n");
                  print_characters(p->size,'-');
                  difference=p->size-answer->size;
              }
              else
              {
                  print_bigint(q);
                  printf("\n-\n");
                  print_characters(q->size-p->size, ' ');
                  print_bigint(p);
                  printf("\n");
                  print_characters(q->size,'-');
                  difference=q->size-answer->size;                  
              }
              break;

    } // End Switch

    printf("\n");

// Prints spaces to format the answer, this will always be zero
// in the case of addition

    print_characters(difference,' ');
    print_bigint(answer);
    printf("\n\n");

}

void print_characters(int how_many, char character)
{
     int counter;

// Prints character n times

     for(counter=0;counter<how_many;counter++)
         printf("%c",character);
}