如果我們需要很大范圍的十進制整數加法,對於4字節int型,不能表示該數據,此時需要用字符串保存操作數和結果,采取逐位運算的方式。如:
987654321 + 1234567989 = 1111111110
-1234 + (-4567) = -5801
-1234 + 30 = -1204
0 + 0 = 0
0 + 34 = 34.
實現函數void add(const char *num1, const char *num2, char *result).
注:輸入字符串所有位均為有效數字,不存在由0開始的串。要求輸出所有位也是有效數組。
正數前沒有符號,負數在最開始有 ‘-’號。
實現如下:
開始以為分分鍾搞定,結果寫了幾個小時,有很多細節要考慮:如(1)做減法時去掉符號后,要保證用大的數減去小的數;(2)逐為累加時要考慮哪個數長,把多余部分與進位相加,另外有可能兩個數都完了,但是此時還有進位不為0。
因為是用C寫的,因為題目給出了函數的簽名,所以代碼寫了很長,因為對字符串的各種處理都要自己手動進行。
1 #include<stdio.h> 2 #include<stdlib.h> 3 #include<string.h> 4 5 void move(char *str, int length) //移除字母前的"-"符號 6 { 7 if(str[0] != '-') 8 return; 9 int i; 10 for(i = 0; i < length-1; i++) 11 str[i] = str[i+1]; 12 str[i] = '\0'; 13 } 14 15 int remove_zero(char *result, int length) 16 { 17 int count = 0; 18 for(int i = length-1; i > 0; i--) //從最后開始移除0,直到遇到非0數字,只對最初位置上的0不予判斷 19 { 20 if(result[i] == '0') 21 { 22 result[i] = '\0'; 23 count++; 24 }else 25 return length-count; 26 } 27 return length - count; 28 } 29 30 void reverse(char *result, int length) //將字符串倒轉 31 { 32 char temp; 33 for(int i = 0; i <= (length-1)/2; i++) 34 { 35 temp = result[i]; 36 result[i] = result[length-1-i]; 37 result[length-1-i] = temp; 38 } 39 } 40 41 int real_add(char *str1, char *str2, char *result, const bool flag) 42 { 43 int len1 = strlen(str1); 44 int len2 = strlen(str2); 45 int n1, n2, another = 0; //another表示進位 46 int cur_rs = 0; //表示result的當前位數 47 int i, j; 48 int curSum; 49 for(i = len1-1, j = len2-1; i >= 0 && j >= 0; i--, j--) 50 { 51 n1 = str1[i] - '0'; 52 n2 = str2[j] - '0'; 53 curSum = n1 + n2 + another; 54 result[cur_rs++] = curSum % 10 + '0'; 55 another = curSum / 10; 56 } 57 58 if(j < 0) 59 { 60 while(i >= 0) //遍歷str1剩余各位 61 { 62 n1 = str1[i--] - '0'; 63 curSum = n1 + another; 64 result[cur_rs++] = curSum % 10 + '0'; 65 another = curSum / 10; 66 } 67 if(another != 0) //如果還有進位未加上 68 result[cur_rs++] = another + '0'; 69 }else{ 70 while(j >= 0) 71 { 72 n2 = str2[j--] - '0'; 73 curSum = n2 + another; 74 result[cur_rs++] = curSum % 10 + '0'; 75 another = curSum / 10; 76 } 77 if(another != 0) 78 result[cur_rs++] = another + '0'; 79 } 80 81 result[cur_rs] = '\0'; 82 83 cur_rs = remove_zero(result, cur_rs); 84 if(!flag) 85 { 86 result[cur_rs++] = '-'; 87 result[cur_rs] = '\0'; 88 } 89 reverse(result, strlen(result)); 90 return cur_rs; 91 } 92 93 94 int real_minus(char *str1, char *str2, char *result) //使用str1減去str2 95 { 96 char big[100], small[100]; 97 int big_len, sml_len; 98 99 int len1 = strlen(str1); 100 int len2 = strlen(str2); 101 bool flag = false; //用於標記str2是否比str1大 102 103 if(len1 < len2) 104 flag = true; 105 else if(len1 == len2) 106 { 107 if(strcmp(str1, str2) == 0) 108 { 109 result[0] = '0'; 110 result[1] = '\0'; 111 return 1; 112 }else if(strcmp(str1,str2) < 0) 113 flag = true; 114 } 115 116 if(flag) //將str1和str2交換,確保str1指向的值是其中較大者,最后通過flag確定要不要給前面加-號 117 { 118 char *temp = str1; 119 str1 = str2; 120 str2 = temp; 121 len1 = strlen(str1); 122 len2 = strlen(str2); 123 } 124 125 int n1, n2, another = 0; //another表示是否有借位 126 int i, j; 127 int cur_rs = 0; 128 int curMinus; 129 130 for(i = len1-1, j = len2-1; i>=0 && j>=0; i--,j--) 131 { 132 n1 = str1[i] - '0'; 133 n2 = str2[j] - '0'; 134 if(n1 >= n2+another) 135 { 136 result[cur_rs++] = (n1-n2-another) +'0'; 137 another = 0; 138 } 139 else 140 { 141 result[cur_rs++] = (n1+10-n2-another) + '0'; 142 another = 1; 143 } 144 } 145 146 while(i >= 0) 147 { 148 n1 = str1[i--] - '0'; 149 if(another != 0) 150 { 151 n1 -= another; 152 another = 0; 153 } 154 result[cur_rs++] = n1 + '0'; 155 } 156 157 result[cur_rs] = '\0'; 158 cur_rs = remove_zero(result, cur_rs); 159 if(flag) 160 { 161 result[cur_rs++] = '-'; 162 result[cur_rs] = '\0'; 163 } 164 reverse(result, cur_rs); 165 166 return cur_rs; 167 } 168 169 void add(const char *num1, const char *num2, char *result) 170 { 171 int len1 = strlen(num1); 172 int len2 = strlen(num2); 173 int rs_len; 174 if(!len1 || !len2) 175 return; 176 char str1[100], str2[100]; 177 strncpy(str1, num1, len1); 178 str1[len1] = '\0'; 179 strncpy(str2, num2, len2); 180 str2[len2] = '\0'; 181 182 if(str1[0] == '-' && str2[0] == '-') 183 { 184 move(str1, len1); 185 move(str2, len2); 186 rs_len = real_add(str1, str2, result, false); 187 188 }else if(str1[0] == '-') 189 { 190 move(str1, len1); 191 rs_len = real_minus(str2, str1, result); 192 } 193 else if(str2[0] == '-') 194 { 195 move(str2, len2); 196 rs_len = real_minus(str1, str2, result); 197 }else 198 rs_len = real_add(str1, str2, result, true); 199 } 200 201 int main(int argc, char *argv[]) 202 { 203 char result[100]; 204 memset(result, 0, 100); 205 add(argv[1], argv[2], result); 206 printf("%s\n", result); 207 208 return 0; 209 }