兩個大數相加

       我們以前計算兩個整數的和,需要定義兩個整型變量來存儲兩個操作數。

       但是,若這兩個數大到任何整型類型都存放不下時,我們該怎麼來計算它們的和呢?這就是我們今天所討論的話題!


解決思路:

      (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;
}


運行截圖 :

                 

發佈了51 篇原創文章 · 獲贊 55 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章