#include<stdio.h>
#include<string.h>
#define size 1001
int main()
{
char str1[size],str2[size],*num1,*num2,*p1,*p2;
int ncase/*多组输入数目*/,mcase=1/*输出时的第几个输出计数器*/,up/*进位存储器*/,len1,len2,len;
scanf("%d",&ncase);
while(ncase--)
{
scanf("%s %s",str1,str2);
printf("Case %d:\n",mcase++);
printf("%s + %s = ",str1,str2);
len1=strlen(str1);/*分别计算两数长度*/
len2=strlen(str2);
if( len1 >= len2 )/*把num1赋较大数的数组首地址num2赋较小数的数组首地址,且保证len1存长数组长度len2存短数组长度*/
{
num1=str1;
num2=str2;
}
else
{
num1=str2;
num2=str1;
len=len1;
len1=len2;
len2=len;
}
up=0;/*进位赋初值0*/
for(p1=num1+len1-1,p2=num2+len2-1;p1>=num1;p1--,p2--)/*从各自最小位逐位相加,以较大数的最高位为边界*/
{ /********不顾越界的危险去操作*******/
if( p2 < num2 )
*p2=48;/*如果越界了则赋0值*/
*p1=*p1+*p2-96+up;/*由ascII码值化为十进制值*/
up=0;
if( *p1 >= 10 )/*如果此位相加结果十进制值大于10则作减10处理*/
{
*p1-=10;
up=1;/*进位寄存器赋1*/
}
*p1+=48;/*再次化为ascII码以供输出*/
}
if( up == 1 )
printf("1");
printf("%s\n",num1);/*输出经加法处理改动的大数组*/
if( ncase != 0 )
printf("\n");
}
return 0;
}
上面的代码是我刚开始的版本。我为了省心省力,对越界的部分进行了操作,在数组边界前的内存赋0。几乎可以保证跑出来的所有结果都是正确的。(毕竟人不是机器,一些极为边界的值是无法测试到的)结果在oj上的结果是OLE。我一直很困惑,因为自己用电脑跑了几组都没问题。而且看上去也很完美没有什么十分明显的致命错误。
后来咨询了acm老队员。终于弄清楚了原因所在。因为对数组越界之后的内存进行了操作。事实上这块内存是未知的位置,可能非常幸运的是空的内存可以毫无问题的使用,但事实上极有可能操作的就是较大数组的内容。而因为数组太大了,测试数据很难反映出这个问题,大数组的最后几个单元已经被读取过了。当大数组里的值是一个1000位的数时,或许最后的输出就能显示出错误。
总之得到的教训和经验就是不要随意操作没有申请的内存空间。
下面是修改之后的结果。终于可以完美运行并ac了。
#include<stdio.h>
#include<string.h>
#define size 1001
int main()
{
char str1[size],str2[size],*num1,*num2,*p1,*p2;
int ncase/*多组输入数目*/,mcase=1/*输出时的第几个输出计数器*/,up/*进位存储器*/,len1,len2,len;
scanf("%d",&ncase);
while(ncase--)
{
scanf("%s %s",str1,str2);
printf("Case %d:\n",mcase++);
printf("%s + %s = ",str1,str2);
len1=strlen(str1);/*分别计算两数长度*/
len2=strlen(str2);
if( len1 >= len2 )/*把num1赋较大数的数组首地址num2赋较小数的数组首地址,且保证len1存长数组长度len2存短数组长度*/
{
num1=str1;
num2=str2;
}
else
{
num1=str2;
num2=str1;
len=len1;
len1=len2;
len2=len;
}
up=0;/*进位赋初值0*/
for(p1=num1+len1-1,p2=num2+len2-1;p2>=num2;p1--,p2--)/*从各自最小位逐位相加,以较小数的最高位为边界*/
{
*p1=*p1+*p2-96+up;/*由ascII码值化为十进制值*/
up=0;
if( *p1 >= 10 )/*如果此位相加结果十进制值大于10则作减10处理*/
{
*p1-=10;
up=1;/*进位寄存器赋1*/
}
*p1+=48;/*再次化为ascII码以供输出*/
}
for(;p1>=num1;p1--)
{
*p1=*p1-48+up;/*由ascII码值化为十进制值*/
up=0;
if( *p1 >= 10 )/*如果此位相加结果十进制值大于10则作减10处理*/
{
*p1-=10;
up=1;/*进位寄存器赋1*/
}
*p1+=48;/*再次化为ascII码以供输出*/
}
if( up == 1 )
printf("1");
printf("%s\n",num1);/*输出经加法处理改动的大数组*/
if( ncase != 0 )
printf("\n");
}
return 0;
}