Assignment 3

Assignment Background

Integer arithmetic is limited because of the size of the primitive data types in C – char, short and long. You are tasked to design a prototype software system for providing unlimited accuracy of integer arithmetic for addition and multiplication operations. After consultation with your project leader you decided to implement the software package using linked lists. The following are the requirements for system:

1. The system shall prompt the user with the following options:

  1. Insert first number
  2. Insert second number
  3. Add numbers
  4. Multiply numbers
  5. Quit

Enter Option:

The user will enter one of the options (1-5). The system will have to validate that the entered option is acceptable. Namely, the system will check that the user entered an integer numeric value in the range of 1-5. If the input is incorrect then the system will respond “Incorrect option” and present the user with the menu.

2. The system shall perform the following tasks for each option

  • Insert first number – in this case the user will enter an unlimited number of digits (e.g., 34563859584873473958438583485873092345234540495820). The system will read the number and store it in a linked list. You can assume that the input will consists only of digits. Namely, you do not have to validate the input. If no number is entered then the first number is equal to 0. Note that the user may insert the first number several times.
  • Insert second number – in this case the user will enter an unlimited number of digits (e.g., 34563859584873473958438583485873092345234540495820). The system will read the number and store it in a 2nd linked list. You can assume that the input will consists only of digits. Namely, you do not have to validate the input. If no number is entered then the second number is equal to 0. Note that the user may insert the second number several times.
  • Add numbers – the system will then add the two numbers and output the correct answer. For example: if the first number is 123456789 and the second number is 987654321 then the system will output 1111111110.
  • Multiply numbers – the system will take the two numbers and multiply them. For example, if the first number is 123456789 and the second number is 987654321 then the system will output 121932631112635269.
  • Quit – the system shall terminate.

Solution

number.h

#include<stdlib.h>
#include<stdio.h>
 
LIST_HEAD *createNumber(char *number);
int add_two_digits(int d1, int d2, int carry_in, int * result, int *carry_out);
LIST_HEAD *add_two_numbers (LIST_HEAD *n1, LIST_HEAD *n2);
LIST_HEAD *multiply_number_digit(LIST_HEAD *N1, int digit);
int multiply_two_digits(int d1, int d2, int carry_in, int *result, int *carry_out);
LIST_HEAD * multiply_two_numbers (LIST_HEAD *n1, LIST_HEAD *n2);
LIST_HEAD *multiply_number_by_10(LIST_HEAD *n);

number.c

#include<stdlib.h>
#include<stdio.h>
#include "linked_list.h"
#include "number.h"
 
//create new number
LIST_HEAD *createNumber(char *number){
  LIST_HEAD *list;
  if(!number || !*number) //if number character is null...
    insertFirst(list, 0); //...insert first number zero
  else {
    while(*number){
      insertFirst(list, (DATA)(*number - ' ')); //insert given number, converted to DATA (integer) after removing blank space from character
      number++;
    }
  }
 
  return list;
}
 
//add two digits
int add_two_digits(int d1, int d2, int carry_in, int * result, int *carry_out){
	*result = d1+d2+carry_in;
	if (*result>=10) {
		*result = *result-10;
		*carry_out=1;
		return 0;
		}
	else {
		*carry_out=0;
		return 0;}
 
	return 1;
}
 
//add two numbers
LIST_HEAD *add_two_numbers (LIST_HEAD *n1, LIST_HEAD *n2){
	struct node *p1;
	p1 = malloc(sizeof(struct node));
	struct node *p2;
	p2 = malloc(sizeof(struct node));
 
	int temp=0; //temp integer to store a result of adding
	int carry_in = 0; //carry_in value, local
	int carry_out = 0; //carry_out value, global, goes as adress to add_two_digits function
 
	p1=n1->head; //let p1 point to the beginning of first number list
	p2=n2->head; //and p2 - to the second
	LIST_HEAD *result = malloc(sizeof(LIST_HEAD)); //this is result list
 
	if(result) {
    result->head = 0; //if created succesfully - make head point to nothing
    result->size = 0; //and size is zero
	}
 
	while (p1!=NULL && p2!=NULL){ //add every two digits in lists until one list is finished
		carry_in=carry_out; //carry_in is equal to carry_out from previous operation
		add_two_digits(p1->digit, p2->digit, carry_in, &temp, &carry_out); 
		insertFirst(result, temp); //add one node to the beginning of the list with the result of adding
		p1=p1->next;
		p2=p2->next;
	}
 
	//make new node and point it to continuing of p1 OR p2 OR nothing
	struct node *p;
	p = malloc(sizeof(struct node)); 
	if (p1 == NULL) p = p2; 
	else p = p1;			
 
	//and now add every digit from the rest with zeros
	while (p!=NULL){ 
		carry_in=carry_out;
		add_two_digits(p->digit, 0, carry_in, &temp, &carry_out);
		insertFirst(result, temp); //add one node to the beginning of the list with the result of adding
		p=p->next;
 
	}
 
	//if there's carry_out left, add it as digit to list
	if (p==NULL && carry_out!=0) insertFirst(result, carry_out);
 
	return result;
}
 
//multiplying number as LIST_HEAD with digit
LIST_HEAD *multiply_number_digit(LIST_HEAD *N1, int digit){
	struct node *p1;
	int temp=0; //temp integer to store a result of adding
	int carry_in = 0; 
	int carry_out = 0;
 
	p1 = malloc(sizeof(struct node));
	p1=N1->head; //let p1 point to the beginning of first number list
	LIST_HEAD *result = createList();
 
	while (p1!=NULL){ //multiply number by digit until list is finished
		carry_in=carry_out;
		multiply_two_digits(p1->digit, digit, carry_in, &temp, &carry_out);
		insertFirst(result, temp); //add one node to the beginning of the list with the result of adding
		p1=p1->next;
	}	
	//if there's carry_out left, add it as digit to list
	if (p1==NULL && carry_out!=0) insertFirst(result, carry_out);
 
	return result;
}
 
//multiplying two digits
int multiply_two_digits(int d1, int d2, int carry_in, int *result, int *carry_out){
  if((*result = d1 * d2 + carry_in) >= 10){
    *carry_out = *result/10;
    *result = *result%10;
  } else *carry_out = 0;
 
  return 0;
}
 
//multiplying two numbers
LIST_HEAD *multiply_two_numbers (LIST_HEAD *n1, LIST_HEAD *n2){
	struct node *p1;
	/*p1 = malloc(sizeof(struct node));*/
	struct node *p2;
	p2 = malloc(sizeof(struct node));
 
	p1=n1->head; //let p1 point to the beginning of first number list
	p2=n2->head; //and p2 - to the second
 
	LIST_HEAD *result = createList(); //list for full result
	LIST_HEAD *stepresult = createList(); //list for step result
 
	int x=0; //this is variable showing how many times should we multiply stepresult by 10
	int count=0; //this is counter for multiplying_by_10 loop
 
	while (p1!=NULL){ //work until end of list
		count=0; //initial count is zero
		emptyList(stepresult); //empty previous stepresult
		stepresult=multiply_number_digit(n2, p1->digit); //multiply second list by first digit of first list
		while (count<x){	stepresult=multiply_number_by_10(stepresult);   count++;} //and multiply it by 10x or 1 if needed
 
		result=add_two_numbers(result, stepresult); //add stepresult to result
		x++;										//next time - multiply by 10 one more time (shifting)
		p1=p1->next;
	}
 
	return result;
}
 
//multiplying number by 10
LIST_HEAD *multiply_number_by_10(LIST_HEAD *n){
	LIST_HEAD *result = createList();
	result->head=n->head;
	insertFirst(result, 0); //just add 0 as first node in a list
	return result;
}

mainfile.c

#include<stdlib.h>
#include<stdio.h>
#include "linked_list.h" //...these       my
#include "number.h"		//...            are      files
 
//convert character to integer
int charToInt(char c){
int result=0;
 
if (c=='0') result=0;
if (c=='1') result=1;
if (c=='2') result=2;
if (c=='3') result=3;
if (c=='4') result=4;
if (c=='5') result=5;
if (c=='6') result=6;
if (c=='7') result=7;
if (c=='8') result=8;
if (c=='9') result=9;
 
return result;
}
 
int main(void){
	char option=' ';
	LIST_HEAD *number1 = createList();
	LIST_HEAD *number2 = createList();
//
// BIG WHILE -  - - -- -- - - - !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
//	
while (option!='5'){	
	//show the menu of options
	while (option!='1' && option!='2' && option!='3' && option!='4' && option!='5') {
	//and keep showing until 1-5 is not pressed
	printf("\n");
	printf("1. Insert first number\n");
	printf("2. Insert second number\n");
	printf("3. Add numbers\n");
	printf("4. Multiply numbers\n");
	printf("5. Quit\n\n");
	printf("Enter option: ");
	option=' ';
	scanf("%c", &option); //input option
	getchar(); //this is to clear extra character scanf left
	printf("\n");
	}
 
//if 1 pressed (insert first number)
if (option=='1'){
	emptyList(number1); //empty previous number
	printf("\nPlease, enter first number now.\n");
	char c=' ';
	struct node *inptr;
	inptr = malloc(sizeof(struct node));
 
	//enter one character at a time until '\n' entered (ENTER button)
	while(1) {
    scanf("%c", &c);
	if(c == '\n') break;
	inptr = insertFirst(number1, charToInt(c)); //add every character as a digit into list number1
	}
 
	option='0';
	}
 
//if 2 pressed (insert second number)
if (option=='2'){
	emptyList(number2); //empty previous number
	printf("\nPlease, enter second number now.\n");
	char c=' ';
	struct node *inptr;
	inptr = malloc(sizeof(struct node));
 
	//enter one character at a time until '\n' entered (ENTER button)
	while(1) {
    scanf("%c", &c);
	if(c == '\n') break;
 
	   inptr = insertFirst(number2, charToInt(c)); //add every character as a digit into list number2
	}
 
	option='0';
	}
 
// if 3 pressed (add two numbers)
if (option=='3'){
	printf("\nThe result of adding two numbers is: ");
 
	//if number1 or number2 is emptylist, make it the list containing zero only
	if (number1==NULL) insertFirst(number1, 0);
	if (number2==NULL) insertFirst(number2, 0);
 
	//create list of result and print it
	LIST_HEAD *numplusnum = createList();
	numplusnum=add_two_numbers(number1,number2);
	printList(numplusnum);
	option='0';
	}
 
//if 4 pressed (multiply two numbers)
if (option=='4'){
	printf("\nThe result of multiplying two numbers is: ");
 
	//if number1 or number2 is emptylist, make it the list containing zero only
	if (number1==NULL) insertFirst(number1, 0);
	if (number2==NULL) insertFirst(number2, 0);
 
	//create list of result and print it
	LIST_HEAD *numbynum = createList();
	numbynum=multiply_two_numbers(number1,number2);
	printList(numbynum);
	option='0';
	}	
 
 
}
printf("\nGood bye, TA!\n");	 
}

linked_list.h

#include<stdlib.h>
#include<stdio.h>
 
//type definitions (used in all functions)
typedef int DATA;
 
typedef struct node {
  struct node * next;
  DATA digit; /* a digit of a number range 0-9*/
} NODE;
 
typedef struct {
  struct node *head; /* the head of the list */
  int size; /* number of elements in the list */
} LIST_HEAD;
 
void emptyList(LIST_HEAD *list);
void deleteList(LIST_HEAD *list);
LIST_HEAD *createList(void);
NODE *insertFirst(LIST_HEAD *list, DATA digit);
NODE *insertAfter(LIST_HEAD *list, NODE *p, DATA digit);
NODE *searchList(LIST_HEAD *list, DATA digit);
LIST_HEAD *reverseList(LIST_HEAD *list);
int deleteFirst(LIST_HEAD *list, DATA *digit);
int deleteNode(LIST_HEAD *list, NODE *p, DATA *digit);
void printList(LIST_HEAD *list);

linked_list.c

f#include<stdlib.h>
#include<stdio.h>
#include "linked_list.h"
 
//creating a list
LIST_HEAD *createList(void)
{
  LIST_HEAD *head = malloc(sizeof(LIST_HEAD)); //create list head by allocation of memory
  if(head) { //if created, then...
    head->head = 0; //point it to nothing
    head->size = 0; //make size=0
  }
  return head;
}
 
//emptying a list
void emptyList(LIST_HEAD *list)
{
  NODE *next, *node;
 
  next = list->head; 
  while(next){
    node = next;
    next = node->next;
    free(node);
  }
  list->size = 0;
  list->head = 0;
}
 
//deleting a list
void deleteList(LIST_HEAD *list)
{
  emptyList(list); //empty as before
  free(list); //and free the memory allocated
}
 
//printing a list 
void printList(LIST_HEAD *list){
 
	struct node *node;
	node = list->head;
	while(node!=NULL){ //print every node's digit value until end of list
		printf("%d", node->digit);
		node = node->next;
	}
  printf("\n");
}
 
//insert node with given digit as first 
NODE *insertFirst(LIST_HEAD *list, DATA digit){
	struct node *newnode = NULL;
	newnode = malloc(sizeof(struct node));
		if(!newnode)	return NULL; //in case memory allocation failed
	newnode->next = list->head;
	newnode->digit = digit;
	list->head = newnode;
	(list->size)++;
	return newnode;
}
 
//insert node with given digit after given node
NODE *insertAfter(LIST_HEAD *list, NODE *p, DATA digit){
	struct node *newnode = NULL;
	newnode = malloc(sizeof(struct node));
		if(!newnode)	return NULL; //in case memory allocation failed
	newnode->digit = digit;
	newnode->next = p->next; //point new node where old 'p' was poining
	p->next = newnode; //and point old 'p' to new node
	(list->size)++;
	return newnode;
}
 
//search the list for given digit
NODE *searchList(LIST_HEAD *list, DATA digit)
{
  struct node *node = list->head;
  while(node && (node->digit != digit)){ //go to next node until finished or until digit found
    node = node->next;
  }
  return node;
}
 
//delete first node in a list
int deleteFirst(LIST_HEAD *list, DATA *digit)
{
  NODE *node = list->head;
  if(node) { //if node created...
    list->head = node->next; //point head of list to second node
    free(node); //free memory of first node;
    list->size--; //reduce size
    return 0;
  }
 
  return 1;
}
 
//delete given node
int deleteNode(LIST_HEAD *list, NODE *p, DATA *digit)
{
  struct node *prev=0;
  struct node *node = list->head;
  while(node){ //if node created....
    if(node == p){
      if(prev)
		prev->next = node->next; //point previous node to next-next node (after 1)
      free(node); //free the memory of node between those
      return 0;
    }
    prev = node;
    node = node->next;
  }
 
  return 1;
}
 
//reverse given list
LIST_HEAD *reverseList(LIST_HEAD *list)
{
  struct node *prev, *curr, *next;
 
  if((prev = list->head)) {
    curr = prev->next;
    prev->next = 0;
  }
 
  while(curr){ //while 'curr' node is not NULL...
    next = curr->next; //point 'next' to curr's next node
    curr->next = prev; //make curr's next node previous one
    prev = curr; 	   // now make previous node be current
    curr = next;	   //and current make next
  }
 
  list->head = prev; //lastly, point list's head to 'prev' node, which is now first
  return list;
}

 
sources/2007/linux_and_c/assignment_3.txt · Последние изменения: 2010/03/05 07:16 От freetonik
 
За исключением случаев, когда указано иное, содержимое этой вики предоставляется на условиях следующей лицензии:CC Attribution-Noncommercial-Share Alike 3.0 Unported
Recent changes RSS feed Donate Powered by PHP Valid XHTML 1.0 Valid CSS Driven by DokuWiki