寒假作业之二(1)

时间:2021-05-24 21:53:17

github上的代码请点击1001. A+B Format20

先看看题目
寒假作业之二(1)

看见题目,根据我被坑的经验,首先的反应就是:

  • 1.测试组数,题目意思应该是多组,那么就跑不了while(scanf()!=EOF)的类型
  • 2.范围,数量级是7次方,不大,int类型是21亿,所以,用int足够(虽然我经常是打开来dev,准备设置变量的时候,才会回头看范围)
    然后,我发现,这题和Fzu上一题基本上一样详情见FZU1405

做这题,我的第一反应就是,a+b的结果用字符串数组存起来,然后每经过3个字符,加一个‘,’,这样子就很简单了,所以要用到stdlib.h中的itoa函数,其中进制转换选择为十进制。

首先,测试一下看看函数用法有没有用错
寒假作业之二(1)

第一次尝试结果

寒假作业之二(1)

看来没有函数没有用错,然后接下来就是做题了

这题要注意的是,答案可能有正有负,这个很简单,只要判断一下正负,如果是负数,就输出‘-’,然后变成正数就可以按正的方法做了,定义变量k,统计当前字符个数(不包括负号)接下来只要每3个字符然后输出一个‘,’就完成了

然后代码为

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int main()
{
int a,b,c;
char s[10];
while(scanf("%d %d",&a,&b)!=EOF)
{
c=a+b;
itoa(c,s,10);
int i=0,k=0;
if(s[0]=='-')
{
printf("-");
i=1;
}
while(s[i]!='\0')
{
printf("%c",s[i++]);
k++;
if(k%3==0&&k!=0) printf(",");
}
printf("%s\n",s);
}
}

由于题目给的数据测试太弱,只好自己测试
寒假作业之二(1)


测试之后,发现错误很多,不仅忘记把第一次调试结果删除,而且忘记处理末尾逗号

然后继续改代码,判断如果下一个字符是‘\0’,就不加‘,’,把第一次调试的结果给注释了,加上换行

while(scanf("%d %d",&a,&b)!=EOF)
{
c=a+b;
itoa(c,s,10);
int i=0,k=0;
if(s[0]=='-')
{
printf("-");
i=1;
}
while(s[i]!='\0')
{
printf("%c",s[i++]);
k++;
if(k%3==0&&k!=0&&s[i]!='\0') printf(",");
}
printf("\n");
// printf("%s\n",s);
}

测试结果如下

寒假作业之二(1)


然后发现- -,我忘记‘,’是从后往前加的了。。

所以,继续改代码,这个时候,就要用到统计字符串中字符个数的函数,
如果有5个字符,那么定义k一开始为1,所以第三个字符前有‘,’,如果有4个字符,那么定义k=2,第二个字符前有‘,’
这就要用到k=3-strlen(s)%3,而且不统计负号进去,

修改后代码如下

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int main()
{
int a,b,c;
char s[10];
while(scanf("%d %d",&a,&b)!=EOF)
{
c=a+b;
itoa(c,s,10);
int i=0,k=0;
if(s[0]=='-')
{
printf("-");
i=1;
}
int n=strlen(s);
n-=i;//去负号
k=3-n%3;
while(s[i]!='\0')
{
printf("%c",s[i++]);
k++;
if(k%3==0&&k!=0&&s[i]!='\0') printf(",");
}
printf("\n");
// printf("%s\n",s);
}
return 0;
}

测试寒假作业之二(1)


出错了。。。查了一下原因

寒假作业之二(1)

咦,居然itoa函数在PAT上不能用,但是我把代码a+b改成a-b,提交到fzu上。明明可以的...然后我百度了一下,结果是,itoa不是标准的C函数库什么什么...

这时....我想起了与printf相对应的据说更实用的sprintf打印进数组的函数,然后我查了一下他的用法,

把itoa注释,改成sprintf函数

 sprintf(s,"%d",c);
// itoa(c,s,10);

寒假作业之二(1)

成功了。。
因为之前询问了一下大神关于itoa,他们说并没有用过,然后说直接写就好了,然后我顺便想了一下,发现其实不用字符串,也是挺简单的,先变为正的,然后分类讨论数的范围小于1000.1000~1000000,与大于10000000就好了(表示眼瞎一次,第一次范围看错为5个0,然后部分错误一次)然后记得用%.3d这个输出方式来补0,以中间一中情况为例,取1000为余数,保存后3位数字,然后再/1000,保存前面的位数,然后输出,后3位记得补0,就没什么问题了,

具体代码如下:

#include<stdio.h>
int main()
{
int a,b,c,d,e;
while(scanf("%d %d",&a,&b)!=EOF)
{
c=a+b;
if(c<0)
{
printf("-");
c*=-1;
}
if(c<1000) printf("%d",c);
else if(c<1000000)
{
d=c%1000;
c/=1000;
printf("%d,%.3d\n",c,d);
}
else
{
d=c%1000;
e=c%1000000;
e/=1000;
c/=1000000;
printf("%d,%.3d,%.3d\n",c,e,d);
}
}
}

测试结果:

寒假作业之二(1)


总结

  • 1.这题难度不大,数据范围不会过大,但测试数据比较弱,在提交前请至少要测试3位数以内,5位数以内,7位数以内的正数,与至少一组负数,才提交
  • 2.数据范围不要看错,第二种方法因为范围是7次方看出6次方导致部分错误一次....