两个大数相加

       我们以前计算两个整数的和,需要定义两个整型变量来存储两个操作数。

       但是,若这两个数大到任何整型类型都存放不下时,我们该怎么来计算它们的和呢?这就是我们今天所讨论的话题!


解决思路:

      (1)、存储问题:我们可以使用字符串来存储操作数,这样不管操作数有多长都能放得下。

      (2)、计算问题:自定加法时,我们要考虑每一位的相加,还有相加时是否有进位值产生。若产生进位,则要在下一位相加时加上进位值。

      (3)、存储结果:两个数相加的结果的位数肯定小于等于两个数的较长的数的位数+1,因为要考虑的最高位进位。即:

                   结果的位数 = (操作数1位数  > 操作数2位数 ?  操作数1位数 : 操作数2位数) + 1;

      (4)、输出问题:这是最简单的问题,因为申请的结果位数可能大于真正的结果的位数。所以第一个字符可能为空字符'\0', 所以输出是应把它跳过。


好,思路理清了。开始写代码:

        写代码时遇到一个问题:释放所申请的结果的内存时出现释放错误


HEAP CORRUPTION DETECTED:after Normal block(#***) at 0x****.CRT detected that application wrote memory after end of heap buffer.


        可能很多人都遇见过这种错误,原因是:以对内在操作的过程中,所写的地址超出了所分配内在的边界。

但是我感觉并没有超界,但是没办法。用最笨的办法:

         将内存申请的大一些。所以我的结果位数比原来的大了一个字节,你们在代码中是可以看到的。然后程序就可以正常运行了!

源代码 :

#include<stdio.h>
#include<string.h>
#include<malloc.h>

/*
**功能: 从键盘获取加法操作数的输入
**参数说明: 无参数
**返回值: 输入的操作数存储位置的指针
*/
char *GetOperInput()
{
	char Oper[1000];  //定义一个足够大的空间
	char *pOper = NULL;  //指向真正存储操作数的指针

	int len;   //操作数的长度

	gets(Oper);
	len = strlen(Oper);

	pOper = malloc(len + 1);
	strncpy(pOper, Oper, len);  //将Oper的len个字节内容拷贝到pOper中
	pOper[len] = '\0';

	return pOper;
}

/*
**功能: 将两个字符串形式的整数相加,得到结果
**参数说明: 
**@pAddResult: 存储加法结果;  
**@pOperOne: 存储加法第一个操作数 @pOperTwo: 存储加法第二个操作数 (两个操作数不可更改)
**返回值: 无
*/
void GetResult(char **pAddResult, int resultLength, const char *const pOperOne, const char *const pOperTwo)
{
	int carryValue = 0;  //进位值(两个数相加的进位值不是 0 就是 1 )
	int AddValue = 0;    //每一位相加后的值

	int lenOne = strlen(pOperOne);
	int lenTwo = strlen(pOperTwo);
	

	//lenOne、resultLength 和lenTwo要作为下标值
	lenOne--;
	lenTwo--;
	resultLength--;

	//循环相加每一位
	while (lenOne >= 0 && lenTwo >= 0)
	{
		AddValue = (pOperOne[lenOne] - '0') + (pOperTwo[lenTwo] - '0') + carryValue;
		
		if (AddValue >= 10)
		{
			carryValue = 1;
			AddValue -= 10;
		}
		else
		{
			carryValue = 0;
		}

		(*pAddResult)[resultLength] = AddValue + '0';

		lenOne--;
		lenTwo--;
		resultLength--;
	}

	//如果哪一个操作数剩下未相加的位,直接加到结果中
	while (lenOne >= 0)
	{
		(*pAddResult)[resultLength] = pOperOne[lenOne] + carryValue;
		if (carryValue)
		{
			carryValue = 0;
		}
		lenOne--;
		resultLength--;
	}

	while (lenTwo >= 0)
	{
		(*pAddResult)[resultLength] = pOperOne[lenTwo] + carryValue;
		if (carryValue)
		{
			carryValue = 0;
		}
		lenTwo--;
		resultLength--;
	}

	//如果有最高位进位的话
	if (carryValue)
	{
		(*pAddResult)[resultLength] = '0' + carryValue;
	}

}

int main(void)
{
	//加法操作的两个操作数
	char *pOperOne = NULL;
        char *pOperTwo = NULL;

	//加法的结果
	char *pAddResult = NULL;
	int resultLength = 0, lenOne = 0, lenTwo = 0;

	//获取两个操作数的输入
	puts("请输入第一个加数:");
	pOperOne = GetOperInput();
	puts("请输入第二个加数:");
	pOperTwo = GetOperInput();

	//申请到足够的结果空间
	resultLength = strlen(pOperOne) > strlen(pOperTwo) ? strlen(pOperOne) : strlen(pOperTwo);
	resultLength += 2;  //考虑到可能有进位
	pAddResult = malloc(resultLength);  
	memset(pAddResult, 0, resultLength);  //清空

	//计算结果(第二个参数传长度-1,是为了结果字符串以\0结尾)
	GetResult(&pAddResult, resultLength - 1, pOperOne, pOperTwo);

	//输出结果
	printf("%s + %s = ", pOperOne, pOperTwo);

	char *pResult = pAddResult;
	int i = 0;

	//如果没有进位的话,前面几位是空字符
	while(pAddResult[i] == '\0')
	{
		pResult++;
		i++;
	}

	puts(pResult);
		
	//收尾工作
	free(pOperOne);
	pOperOne = NULL;
	free(pOperTwo);
	pOperTwo = NULL;
	free(pAddResult);
	pAddResult = NULL;

	return 0;
}


运行截图 :

                 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值