我們以前計算兩個整數的和,需要定義兩個整型變量來存儲兩個操作數。
但是,若這兩個數大到任何整型類型都存放不下時,我們該怎麼來計算它們的和呢?這就是我們今天所討論的話題!
解決思路:
(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;
}
運行截圖 :