利用一位加法器实现大数相加

#include<stdio.h>
#include<stdlib.h>

/*
	编写十进制一位加法器add()
	以被加位、加位、低位进位为参数,用十进制数字字符表示,以本位结果和高位进位为输出。
	实现两个任意长整数加法,其他过程自理,不能使用字符串库函数。
*/

//字符数组初始大小101,如果不够,动态增加,每次加20
#define MAX 101
#define INCREARMENT 20

typedef struct ADDITEM
{
	char baseBit;		//本位
	char carryBit;		//进位
}ADDITEM;

//十进制一位加法器
//以被加位、加位、低位进位为参数,
//用十进制数字字符表示,以本位结果和高位进位为输出

ADDITEM Add(char num1,char num2,char carryBit)
{
	ADDITEM item;
	int num;
	
	num = num1 + num2 + carryBit - '0'*3;
	item.baseBit = num % 10 + '0';
	item.carryBit = num / 10 + '0';

	return item;
}

//输入"无限大小"整数,以Enter结束
char* inputStr(char* str)
{
	//str_len字符串的长度,max_size当前字符数组空间大小
	int str_len,max_size;
	char ch;
	
	str_len = 0;	
	max_size = MAX;		
	str = (char*)malloc(sizeof(char) * max_size);
	if (str == NULL)
	{
		printf("allocation failture\n");
	}
	scanf("%c",&ch);
	while(ch!='\n')
	{
		str[str_len] = ch;
		str_len = str_len + 1;
		//空间不足,追加空间,每次加INCREAMENT个
		if(str_len >= max_size)
		{
			str = (char*)realloc(str,sizeof(char)*(max_size + INCREARMENT));
			if (!str)
			{
				printf("allocation failture\n");
			}
			max_size = max_size + INCREARMENT;
		}
		scanf("%c",&ch);
	}	
	str[str_len] = '\0';

	return str;
}

//get the length of str
int StrLen(char* str)
{
	int len;
	len = 0;
	while(str[len] != '\0')
	{
		len = len + 1;
	}
	return len;
}
//将字符串反转
void strReverse(char* str)
{
	int i,len;
	char ch;

	len = StrLen(str);
	for (i = 0;i<len/2;i++)
	{
		ch = str[i];
		str[i] = str[len - i - 1];
		str[len - i - 1] = ch;
	}
}

int GetMax(int a,int b)
{
	return a>b?a:b;
}

//逆序相加
char* BigNumAdd(char* num1,char* num2)
{
	int len1,len2,len3,i1,i2,i3;
	char* str;	//存储结果
	ADDITEM item;

	len1 = StrLen(num1);
	len2 = StrLen(num2);
	len3 = GetMax(len1,len2);
	
	//两数相加,结果肯定不会大于两者最大值+2,
	str = (char*)malloc(sizeof(char)*(len3+2));	//一个字符保存'\0',另一个保存进位
	item.carryBit = '0';
	i1 = 0; 
	i2 = 0;
	i3 = 0;
	strReverse(num1);	//将字符串反转
	strReverse(num2);

	while(num1[i1]!='\0' && num2[i2]!='\0')
	{
		item = Add(num1[i1],num2[i2],item.carryBit);	//调用一位加法器
		str[i3] = item.baseBit;
		i3  = i3 + 1;
		i1 = i1 + 1;
		i2 = i2 + 1;
	}

	while(num1[i1]!='\0')
	{
		item = Add(num1[i1],'0',item.carryBit);
		str[i3] = item.baseBit;
		i3  = i3 + 1;
		i1 = i1 + 1;
	}

	while(num2[i2]!='\0')
	{
		item = Add('0',item.carryBit);
		str[i3] = item.baseBit;
		i3  = i3 + 1;
		i2 = i2 + 1;
	}
	if (item.carryBit > '0')	//判断最后是否有进位
	{
		str[i3] = item.carryBit;
		i3  = i3 + 1;
	}
	str[i3] = '\0';
	
	strReverse(str);		//将结果翻转

	return str;
}




int main(int argc,char* argv[])
{
	char *num1,*num2,*num3;
	
	num1 = inputStr(num1);
	num2 = inputStr(num2);
	
	num3 = BigNumAdd(num1,num2);
	
	//num1,num2的数据被反转,因为BigNumAdd中使用逆序求和,没有将num1,num2恢复为初始数据
	printf("%s\n",num1);		
	printf("%s\n",num2);
	printf("%s\n",num3);

	return 0;
}

/*
如何在子函数使用malloc 和 relloc 给数组开辟空间
然后在主函数或者其他地方使用

错误方法:
	void f(char* str)
	{
		str = (char*)malloc(sizeof(char)*100);
	}
	原因,malloc()分配的内存并没用释放,只有free之后才会释放。
	为什么又会出错呢?
	传递的str是表示一个指向字符数组的指针,即该传递方法为值传,
	是一个局部变量,即主函数中str和f函数中的str是不一样的,只是数据copy,是单向传递
	当函数返回之后,没有像[正确方法1]那样将地址返回,因而,在主函数中引用时,str依然为空。
	地址传递的方法是f(char& str),传递一个字符的地址,
	

正确方法1
	char* f(char* str)
	{
		str = (char*)malloc(sizeof(char)*100);
		return str;
	}
	分析:通过指针返回开辟的空间,之后通过返回的指针,获得数据
	该函数退出(局部变量p所在内存已经释放)并返回到调用点str=GetMemory(...);把寄存器中的值赋值给str,就是用malloc非配的内存区基址。

正确方法2
	void f(char** str)
	{
		*str = (char*)malloc(sizeof(char*)*100);
	}
	分析:在子函数形参中使用指向指针的指针
	使用方法:
	char *str=NULL;
	f(&str);
*/

相关文章

自1998年我国取消了福利分房的政策后,房地产市场迅速开展蓬...
文章目录获取数据查看数据结构获取数据下载数据可以直接通过...
网上商城系统MySql数据库设计
26个来源的气象数据获取代码
在进入21世纪以来,中国电信业告别了20世纪最后阶段的高速发...