我们以前计算两个整数的和,需要定义两个整型变量来存储两个操作数。
但是,若这两个数大到任何整型类型都存放不下时,我们该怎么来计算它们的和呢?这就是我们今天所讨论的话题!
解决思路:
(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;
}
运行截图 :