上次【计算机程序设计2】课程讲到了大整数运算,之前我没有接触过这个。仅仅大整数加法的代码我就写了好久=
百练
几次提交
代码主要分为3个部分,输入部分,算法处理加法部分,输出部分。几个麻烦的地方:
- 输入处理,感觉每次上机题输入部分我都要花好多时间。
- 因为数字加法是从最低位开始相加,而输入是从最高位开始读入(作为数组下标小的部分),所以需要倒序。
第一次提交
一开始我是用整型数组来表示大整数,但我忘记考虑了前导零的情况。(还有可能有其他错误)
/*
ASCII 0~48, 9~57
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define N 200
int main()
{
int ai[N] = {0}, bi[N] = {0}; //ai,bi是倒序输入的数字
int a[N] = {0}, b[N] = {0}; //a,b把倒序改成正序
int s[N+1]={0};
int i, j, k, n, m;
//输入部分,从高位往低位输入
for (i=0; (n=getchar()) != '\n'; i++) ai[i] = n - 48;
for (j=0; (n=getchar()) != '\n'; j++) bi[j] = n - 48;
for (k=0; k<i; k++) a[k] = ai[i-k-1];
for (k=0; k<j; k++) b[k] = bi[j-k-1];
//计算部分,从低位往高位计算
for (k=0; k= 10) {
s[k] = m - 10;
s[k+1] = 1;
}
else {
s[k] = m;
}
}
//输出部分,从高位往低位输出
if (s[k] != 0) printf("%d", s[k]);
for (i=k-1; i>=0; i--) printf("%d", s[i]);
printf("\n");
return 0;
}
状态: Wrong Answer
第二次提交
考虑了前导零的情况,使得输入部分的代码变得麻烦了一些,但是0+0的情况将会输入错误。
/*
ASCII 0~48, 9~57
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define N 200
int main()
{
int i, j, k, n, m;
int ai[N] = {0}, bi[N] = {0}; //ai,bi是倒序输入的数字
int a[N] = {0}, b[N] = {0}; //a,b把倒序改成正序
int s[N+1] = {0};
//输入部分,从高位往低位输入
while ((n=getchar()) == '0'); //排除前导0
ai[0] = n - 48;
for (i=1; (n=getchar()) != '\n'; i++) {
ai[i] = n - 48;
}
while ((n=getchar()) == '0');
bi[0] = n - 48;
for (j=1; (n=getchar()) != '\n'; j++) {
bi[j] = n - 48;
}
//逆序改回顺序
for (k=0; k<i; k++) a[k] = ai[i-k-1];
for (k=0; k<j; k++) b[k] = bi[j-k-1];
//计算部分,从低位往高位计算
for (k=0; k= 10) {
s[k] = m - 10;
s[k+1] = 1;
}
else {
s[k] = m;
}
}
//输出部分,从高位往低位输出
if (s[k] != 0) printf("%d", s[k]);
while (k > 0) {
printf("%d", s[k-1]);
k--;
}
printf("\n");
return 0;
}
状态: Runtime Error
第三次提交
感觉用整型数组存储大整数,挺浪费内存的(int 在64位机器上是4个字节,而我们只需要表示0~9),而且输入部分很麻烦,所以改用字符数组(char 在64位机器上是1个字节)。
用了字符数组之后,输入部分做了较大的改动,为了排除前导零以及输入为0+0的情况,我采用了指针。
/*
ASCII 0~48, 9~57
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define N 200
int main()
{
int k, m;
char ai[N] = {0}, bi[N] = {0}; //ai,bi是倒序输入的数字
char *pa = ai, *pb = bi;
char a[N] = {0}, b[N] = {0}; //a,b把倒序改成正序
char sum[N+1] = {0};
int a_len, b_len, s_len;
//输入部分,注意是从高位往低位输入
scanf("%s", ai);
scanf("%s", bi);
//排除前导0
while (*pa=='0' && *(pa+1)!='\0') pa++;
while (*pb=='0' && *(pb+1)!='\0') pb++;
a_len = strlen(pa);
b_len = strlen(pb);
//逆序改回顺序,并且把ASCII值换成数字大小
for (k=0; k<a_len; k++) a[k] = *(pa+a_len-k-1) - 48;
for (k=0; k<b_len; k++) b[k] = *(bi+b_len-k-1) - 48;
//计算部分,从低位往高位计算
for (k=0; k= 10) {
sum[k] = m - 10;
sum[k+1] = 1;
}
else {
sum[k] = m;
}
}
//输出部分,从高位往低位输出
s_len = strlen(sum);
if (sum[k] != 0) printf("%d", sum[k]);
while (k > 0) {
printf("%d", sum[k-1]);
k--;
}
printf("\n");
return 0;
}
状态: Wrong Answer
第四次提交
花了快半个小时…才发现第三次提交代码中有一个笔误(第三次提交第32行,bi改成pb),其他并没有大的修改。感悟是,如果写代码的过程中进行了比较大的修改,经常会有一些细节被漏掉,这时候 debug 好浪费时间 = =。所以最好一开始就选择对的框架,避免半途中代码重构。
/*
ASCII 0~48, 9~57
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define N 200
int main()
{
int k, m;
char ai[N] = {0}, bi[N] = {0}; //ai,bi是倒序输入的数字
char *pa = ai, *pb = bi;
char a[N] = {0}, b[N] = {0}; //a,b把倒序改成正序
char sum[N+1] = {0};
int a_len, b_len;
//输入部分,注意是从高位往低位输入
scanf("%s", ai);
scanf("%s", bi);
//排除前导0
while (*pa=='0' && *(pa+1)!='\0') pa++;
while (*pb=='0' && *(pb+1)!='\0') pb++;
a_len = strlen(pa);
b_len = strlen(pb);
//逆序改回顺序
for (k=0; k<a_len; k++) a[k] = *(pa+a_len-k-1) - 48;
for (k=0; k<b_len; k++) b[k] = *(pb+b_len-k-1) - 48;
//计算部分,从低位往高位计算
for (k=0; k= 10) {
sum[k] = m - 10;
sum[k+1] = 1;
}
else {
sum[k] = m;
}
}
//输出部分,从高位往低位输出
if (sum[k] != 0) printf("%d", sum[k]);
while (k > 0) {
printf("%d", sum[k-1]);
k--;
}
printf("\n");
return 0;
}
状态: Accepted
另外,我把这学期的上机代码放到了 GitHub 上。

不建议写48这样的magic number,应该写成’0’,表明其含义,在换用别的字符集的时候也可以保持兼容性。
已改