大正數減法(華爲2013校園招聘上機筆試題 )

問題描述:    
兩個任意長度的正數相減,這兩個正數可以帶小數點,也可以是整數,請輸出結果。 輸入的字符串中,不會出現除了數字與小數點以外的其它字符,不會出現多個小數點以及小數點在第一個字符的位置等非法情況,所以考生的程序中無須考慮輸入的數值字符串非法的情況。 
詳細要求以及約束:
1.輸入均爲正數,但輸出可能爲負數; 
2.輸入輸出均爲字符串形式;
3.如果輸出是正數則不需要帶符號,如果爲負數,則輸出的結果字符串需要帶負號
例如:2.2-1.1 直接輸出爲“1.1”,1.1-2.2 則需要輸出爲“-1.1”
 4.輸出的結果字符串需要過濾掉整數位前以及小數位後無效的0,小數位爲全0的,直接輸出整數位
例如相減結果爲11.345,此數值前後均不可以帶0,“011.345”或者“0011.34500”等等前後帶無效0的均視爲錯誤 輸出。例如1.1-1.1結果爲0.0,則直接輸出0。
要求實現函數:
void Decrease(char *input1, char*input2, char *output)
【輸入】 char *iinput1 被減數
char*nput2 減數 
【輸出】 char *output 減法結果
【返回】 無
示例
輸入:char *input1="2.2" 
char *input2="1.1"
輸出:char*output="1.1"
輸入:char *input1="1.1" 
char *input2="2.2"
輸出:char *output="-1.1"

以上摘自 http://blog.csdn.net/lanyan822/article/details/7983832 ,但是考慮到沒有給出這個的源代碼,自己隨手寫了一個,寫得不好,僅供娛樂,歡迎大神指點。

 

 

這次的代碼很長,我是爲了寫的可讀性更高一點,很多地方比較累贅而且用的方法比較直接,也是我一開始直接想到的。如果有更好的方法希望大家提供哈...

//正數減法
//問題描述:    
//兩個任意長度的正數相減,這兩個正數可以帶小數點,也可以是整數,請輸出結果。
//輸入的字符串中,不會出現除了數字與小數點以外的其它字符,不會出現多個小數點以及小數點在第一個字符的位置等非法情況,所以考生的程序中無須考慮輸入的數值字符串非法的情況。 
//詳細要求以及約束:
//1.輸入均爲正數,但輸出可能爲負數; 
//2.輸入輸出均爲字符串形式;
//3.如果輸出是正數則不需要帶符號,如果爲負數,則輸出的結果字符串需要帶負號
//例如:2.2-1.1 直接輸出爲“1.1”,1.1-2.2 則需要輸出爲“-1.1”
// 4.輸出的結果字符串需要過濾掉整數位前以及小數位後無效的0,小數位爲全0的,直接輸出整數位
//例如相減結果爲11.345,此數值前後均不可以帶0,“011.345”或者“0011.34500”等等前後帶無效0的均視爲錯誤 輸出。例如1.1-1.1結果爲0.0,則直接輸出0。
//要求實現函數:
//void Decrease(char *input1, char*input2, char *output)
//【輸入】 char *iinput1 被減數
//char*nput2 減數 
//【輸出】 char *output 減法結果
//【返回】 無
//示例
//輸入:char *input1="2.2" 
//char *input2="1.1"
//輸出:char*output="1.1"
//輸入:char *input1="1.1" 
//char *input2="2.2"
//輸出:char *output="-1.1"
#include <algorithm>
#include <assert.h>
//得到小數點的位置
int getDot(char *input1)//小數點計算函數
{
	return find(input1,input1+strlen(input1),'.') - input1;
}

void Decrease(char *input1, char*input2, char *output)
{
	assert(input1 != NULL && input2 != NULL && output != NULL);//假設三個參數都不爲空
//1.小數點對其
	int dot1 = getDot(input1),dot2 = getDot(input2);
//2.小數點對其初始化兩個char數組,方便之後運算。長度爲雙方可能的最大位數
	int length = ((strlen(input1)-dot1)>(strlen(input2)-dot2)?(strlen(input1)-dot1):(strlen(input2)-dot2))/*小數部分最長的值*/
		+(dot1>dot2?dot1:dot2)/*整數部分最長的值*/+1/*可能產生的符號位與小數點*/;
	char *str1,*str2,*result;

	str1 = (char *)malloc(length+1);//加1爲了存結束符
	str2 = (char *)malloc(length+1);
	result = (char *)malloc(length+1);

	memset(str1,'0',length);
	memset(str2,'0',length);
	memset(result,'0',length);

	str1[length] = '\0';
	str2[length] = '\0';
	result[length] = '\0';

//3.得出每個字符串小數點對其後的位置,但是不拷貝最後一個'\0'結束符
	memcpy(&str1[abs(dot1>dot2?dot1:dot2-dot1)+1],input1,strlen(input1));
	memcpy(&str2[abs(dot1>dot2?dot1:dot2-dot2)+1],input2,strlen(input2));

	
//4.得到兩數之間較大的數,爲了保證始終大數減小數,省的借位情況複雜
	int isPlus = true;//如果被減數更大則爲真
	char *max = str1,*min = str2;
	for(int i = 1;i < length;++i)
	{
		if(str1[i] > str2[i])
		{
			max = str1;
			min = str2;
			break;
		}
		else if(str1[i] < str2[i])
		{
			isPlus = false;
			max = str2;
			min = str1;
			break;
		}
		else if(i == length - 1)
		{//兩個字符串數字相等
			output[0] = '0';
			output[1] = '\0';
			return ;
		}
	}
	//把沒有小數點的全部補齊
	result[dot1>dot2?dot1:dot2 + 1] = '.';
	max[dot1>dot2?dot1:dot2 + 1] = '.';
	min[dot1>dot2?dot1:dot2 + 1] = '.';
//5.開始運算
	for(int i = length-1;i > 0;--i)
	{//開始從右到左開始減
		if(max[i] == '.')
		{
			result[i] == '.';
			continue;
		}
		int temp;
		temp = max[i] - min[i];
		if(temp < 0)
		{//如果不夠減時向高位借數
			int j = i;
			while(max[j] == '0' || max[j] == '.'/* && j != 0*/)
			{//找到可以借位的數爲止,因爲輸入的都是整數,所以不做更多討論
				if(max[j] == '0')
				{
					max[j] = '9';
				}
				j--;
			}
			max[j]--;
			temp += 10;
		}
		result[i] = temp + '0';
	}
	if(!isPlus)
		output[0] = '-';
//6.把結果字符格式化給output字符串
	for(unsigned int i = strlen(result);i >= 0;++i)
	{//清除末尾0或最後一位是小數點
		if(result[i] == '0' || result[i] == '.')
			result[i] = '\0';
		else
			break;
	}
	unsigned int first = 1;//記錄第一位有效位的起始位置
	while(result[first] == '0')
	{
		first++;
	}
	strcpy(output,&result[first]);
}

int _tmain(int argc, _TCHAR* argv[])
{
	char r[10000];
	Decrease("2.2", "1.1",r);
	cout<<r;
	return 0;
}


 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章