杭電1047(Integer Inquiry)
阿新 • • 發佈:2018-12-07
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; }