1. 程式人生 > >杭電1047(Integer Inquiry)

杭電1047(Integer Inquiry)

意思的話自己翻譯

test1

4
123456789012345678901234567890
123456789012345678901234567890
123456789012345678901234567890
0

123456789012345678901234567890
123456789012345678901234567890
0

90
12234567890
12345675678901234567890
1234567678901234567890
0


45453
832345675678901234567890
1234567678901234567890
0

test2:
輸入不輸入加數直接為0;

1
0

答案是0

test3

2

0000
000
0

0

答案是
0

0
清空了,導致輸出的空的。就WA

所以在最後應該不是清空,而是重新賦0

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

#define MAX 1000    // 大數的最大位數
char z_all[MAX]; //存放乘法結果
char reduce[MAX];
char plus[MAX];
char *multi_bignum(char x[MAX], char y[MAX])
{
	//char x[MAX];
	//char y[MAX];
	//char z_all[MAX];
	memset(z_all, 0, MAX * sizeof(char));
	char z[MAX];//存放每次乘法結果

	char big[MAX];//存放x[]和y[]更大的那個陣列 ,相當於列式計算的上面那個數 
	char small[MAX];//存放x[]和y[]更小的那個陣列 ,相當於列式計算的下面那個數 

	int multi = 0;//2個數相乘得到的 
	int count = 0;//乘法進位的數

	int length = 0;//用於計算z[]的長度
	int length_all = 0; //用於計算z_all[]的長度,很難搞,因為ascii0代表為\0,所以strlen(z_all)沒用,length_all=length或者length+1或-1 

	int plus = 0;//2個數相加得到的 
	int count_z = 0;//加法進位的數

	//scanf("%s",&x);
	//scanf("%s",&y);

	int x_length = strlen(x);
	int big_length = 0;//記錄x_length和y_length更大的長度為 

	int y_length = strlen(y);
	int small_length = 0;//記錄x_length和y_length更小的長度為 

	//1,判斷x[]和y[]誰更長,得到長度,並把更長的放入big[],更短的放入small[] 
	//2,每一位都-48,才可以開始計算。 
	if (x_length > y_length)
	{
		big_length = x_length;
		small_length = y_length;
		for (int i = 0; i < (big_length); i++)
		{
			big[i] = x[i] - 48;
			if (i < y_length)
				small[i] = y[i] - 48;
			else small[i] = 0;
		}
	}
	else
	{
		big_length = y_length;
		small_length = x_length;
		for (int i = 0; i < (big_length); i++)
		{
			big[i] = y[i] - 48;
			if (i < x_length)
				small[i] = x[i] - 48;
			else small[i] = 0;
		}
	}

	//字串逆轉strrev(),不能用這個函式,和strlen()一樣,碰ascii0結束 
	//strrev(big);
	int num = big_length / 2;
	int first_num = 0;//執行字串逆轉的 
	for (int i = 0; i < num; i++)
	{
		first_num = big[i];
		big[i] = big[big_length - 1 - i];
		big[big_length - 1 - i] = first_num;
	}

	//strrev(small);
	num = small_length / 2;
	for (int i = 0; i < num; i++)
	{
		first_num = small[i];
		small[i] = small[small_length - 1 - i];
		small[small_length - 1 - i] = first_num;
	}

	//--------------------計算每次結果,並執行加法,得到總結果 
	for (int i = 0; i < small_length; i++)
	{
		memset(z, 0, sizeof(z));//用完陣列一定要記得情空 
		count = 0;
		length = 0;
		for (int j = 0; j < big_length; j++)
		{

			multi = small[i] * big[j] + count;
			if (multi < 10)
			{
				count = 0;
			}
			else count = multi / 10;

			z[j] = multi % 10;
			length++;

			//每次運算結果的第一位可能需要進位 
			if (j == big_length - 1)
			{
				if (multi >= 10)
				{
					length++;
					z[j + 1] = multi / 10;

				}
				count = 0;     //運算完了之後進位為0

			}

		}

		//逆轉每次運算結果再加上根據正在計算small[]中第幾個數決定末尾的0,真正的每次運算結果 
		//strrev(z);//字串逆轉 
		num = length / 2;
		for (int m = 0; m < num; m++)
		{
			first_num = z[m];
			z[m] = z[length - 1 - m];
			z[length - 1 - m] = first_num;
		}
		//根據正在計算small[]中第幾個數決定末尾的0,真正的每次運算結果
		for (int m = 0; m < i; m++)
		{
			z[length] = 0;
			length++;
		}

		//在每次 執行z_all[]和z[] 的加法  之前先對z_all[]補充到和z[]一樣的位數
		//可能補充1位,可能補充2位 
		if (length_all == length)
			;
		else
		{
			//1 是 -1,2是+0,3是+1 ,4是 +2,相差2 
			//觀察得到 length-length_all-2 是 
			for (int m = length + (length - length_all - 2); m >= length - length_all; m--)
			{
				z_all[m] = z_all[m - (length - length_all)];
			}
			for (int m = 0; m < length - length_all; m++)
			{
				z_all[m] = 0;
			}
			length_all = length;

		}

		//加起來存放在z_all[],執行z_all[]和z[] 的加法
		for (int m = (length - 1); m >= 0; m--)
		{
			plus = z[m] + z_all[m] + count_z;
			if (plus >= 10)
			{
				count_z = 1;
				z_all[m] = plus % 10;

				//每次運算結果的第一位可能需要進位
				if (m == 0)
				{
					count_z = 0;

					//必須這樣寫,不然strlen()以\0結束,而ascii的0就是\0  
					length_all = length + 1;
					for (int n = length; n > 0; n--)
					{
						z_all[n] = z_all[n - 1];
					}
					z_all[0] = 1;

				}

			}
			else
			{
				z_all[m] = plus;
				count_z = 0;
			}
		}

	}
	//--------------------得到總結果

	//還原成char[],才可以用字串%s顯示出來,不然可能要一個一個%d輸出	 
	for (int i = 0; i < length_all; i++)
	{
		z_all[i] += 48;
	}

	//printf("總結果為%s",z_all);

	//函式不要返回區域性變數的指標,因為這是不確定的行為,指標所指的內容函式結束後就自動釋放了,之後的值可能被其他內容覆蓋
	return z_all;

}

char *Subtraction(char num1[], char num2[])
{
	int sum[MAX] = { 0 }; // 存放計算的結果 
	memset(sum, 0, sizeof(int)*MAX);
	//char reduce[MAX];
	memset(reduce, 0, MAX * sizeof(char));
	int i, j, len, blag;
	char *temp;
	int n2[MAX] = { 0 };
	int len1 = strlen(num1); // 計算陣列num1的長度,即大數的位數 
	int len2 = strlen(num2); // 計算陣列num2的長度,即大數的位數

	// 在進行減法之前要進行一些預處理 
	blag = 0; // 為0表示結果是正整數,為1表示結果是負整數 
	if (len1 < len2) // 如果被減數位數小於減數
	{
		blag = 1; // 標記結果為負數
		// 交換兩個數,便於計算 
		temp = num1;
		num1 = num2;
		num2 = temp;
		len = len1;
		len1 = len2;
		len2 = len;
	}
	else if (len1 == len2) // 如果被減數的位數等於減數的位數
	{
		// 判斷哪個數大 
		for (i = 0; i < len1; i++)
		{
			if (num1[i] == num2[i])
				continue;
			if (num1[i] > num2[i])
			{
				blag = 0; // 標記結果為正數 
				break;
			}
			else
			{
				blag = 1; // 標記結果為負數 
				// 交換兩個數,便於計算 
				temp = num1;
				num1 = num2;
				num2 = temp;
				break;
			}
		}
	}
	len = len1 > len2 ? len1 : len2; // 獲取較大的位數
	//將num1字元陣列的數字轉換為整型數且逆向儲存在整型陣列sum中,即低位在前,高位在後
	for (i = len1 - 1, j = 0; i >= 0; i--, j++)
		sum[j] = num1[i] - '0';
	// 轉換第二個數 
	for (i = len2 - 1, j = 0; i >= 0; i--, j++)
		n2[j] = num2[i] - '0';
	// 將兩個大數相減 
	for (i = 0; i <= len; i++)
	{
		sum[i] = sum[i] - n2[i]; // 兩個數從低位開始相減 
		if (sum[i] < 0)   // 判斷是否有借位 
		{    // 借位 
			sum[i] += 10;
			sum[i + 1]--;
		}
	}
	// 計算結果長度 
	for (i = len1 - 1; i >= 0 && sum[i] == 0; i--)
		;
	len = i + 1;
	if (blag == 1)
	{
		sum[len] = -1;  // 在高位新增一個-1表示負數 
		len++;
	}

	if (sum[i = len - 1] < 0) // 根據高位是否是-1判斷是否是負數
	{
		//printf("-"); // 輸出負號
		i--;
	}
	int jj = 0;
	for (; i >= 0; i--)
	{
		reduce[jj++] = sum[i] + 48;
	}
	return reduce;   // 返回結果的位數 
}
char *Addition(char num1[], char num2[])
{


	int sum[MAX] = { 0 }; // 存放計算的結果 
	memset(sum, 0, sizeof(int)*MAX);
	//char plus[MAX];
	memset(plus, 0, MAX * sizeof(char));
	int i, j, len;
	int n2[MAX] = { 0 };
	int len1 = strlen(num1); // 計算陣列num1的長度,即大數的位數 
	int len2 = strlen(num2); // 計算陣列num2的長度,即大數的位數 

	int count1 = 0;
	int count2 = 0;
	for (int i = 0; i < len1; i++)
	{
		if (num1[i] == '0')
			count1++;
	}
	for (int i = 0; i < len2; i++)
	{
		if (num2[i] == '0')
			count2++;
	}
	if (count1 == len1 && count2 == len2)
	{
		strcpy(plus, "0");
		return plus;
	}
	else if (count1 == len1)
	{
		strcpy(plus, num2);
		return plus;
	}
	else if (count2 == len2)
	{
		strcpy(plus, num1);
		return plus;
	}

	len = len1 > len2 ? len1 : len2; // 獲取較大的位數
	//將num1字元陣列的數字字元轉換為整型數字,且逆向儲存在整型陣列sum中,即低位在前,高位在後
	for (i = len1 - 1, j = 0; i >= 0; i--, j++)
		sum[j] = num1[i] - '0';
	// 轉換第二個數 
	for (i = len2 - 1, j = 0; i >= 0; i--, j++)
		n2[j] = num2[i] - '0';
	// 將兩個大數相加 
	for (i = 0; i <= len; i++)
	{
		sum[i] += n2[i];  // 兩個數從低位開始相加 
		if (sum[i] > 9)   // 判斷是否有進位 
		{   // 進位 
			sum[i] -= 10;
			sum[i + 1]++;
		}
	}
	if (sum[len] != 0)  // 判斷最高位是否有進位 
		len++;

	int jj = 0;
	for (i = len - 1; i >= 0; i--)
		plus[jj++] = sum[i] + 48;

	char plus_last[MAX];
	memset(plus_last, 0, MAX * sizeof(char));
	if (plus[0] != '0')
		return plus;
	else
	{
		int l = strlen(plus);
		for (int i = 0; i < l; i++)
		{
			if (plus[i] != '0')
			{
				int flag = 0;
				for (; i < l; i++)
				{
					plus_last[flag++] = plus[i];
				}
				strcpy(plus, plus_last);
				return plus;
			}
		}
	}
	return plus;
}
int main()
{
	int n;
	char x[MAX] = "0";
	char y[MAX];

	scanf("%d", &n);
	while (n--)
	{
		while (scanf("%s", y) )
		{
			if (strcmp(y, "0") == 0)
				break;
			else
			{
				strcpy(x, Addition(x, y));
			}
			    
		}
		printf("%s\n", x);
		if (n != 0)
		{
			printf("\n");
		}
		strcpy(x, "0");
	}
	return 0;
}