PTA L1-025 整数A+B
题目描述
题的目标很简单,就是求两个正整数A和B的和,其中A和B都在区间[1,1000]。稍微有点麻烦的是,输入并不保证是两个正整数。
输入格式:
输入在一行给出A和B,其间以空格分开。问题是A和B不一定是满足要求的正整数,有时候可能是超出范围的数字、负数、带小数点的实数、甚至是一堆乱码。
注意:我们把输入中出现的第1个空格认为是A和B的分隔。题目保证至少存在一个空格,并且B不是一个空字符串。
输出格式:
如果输入的确是两个正整数,则按格式A + B = 和输出。如果某个输入不合要求,则在相应位置输出?,显然此时和也是?。
输入样例1:
123 456
输出样例1:
123 + 456 = 579
输入样例2:
22. 18
输出样例2:
? + 18 = ?
输入样例3:
-100 blabla bla…33
输出样例3:
? + ? = ?
AC代码如下:
#include<iostream>
#include<cstdio>
using namespace std;
int main()
{
char a[1005], b[1005], c;
char* p = a, * q = b;
int flag_a = 0, flag_b = 0, sum_a = 0, sum_b = 0;
scanf("%s", a);//第一部分
c = getchar();//吸收空格
scanf("%[^\n]", b);//读取一个字符集
//遍历两个集合,若不符合正整数形式,flag置为1
for (; *p != '\0'; p++)
if (*p < 48 || *p>57) {
flag_a = 1;
break;
}
p = a;//指针复位
for (; *q != '\0'; q++)
if (*q < 48 || *q>57) {
flag_b = 1;
break;
}
q = b;
//若为正整数,则计算A,B的数值
if (!flag_a) {
while (*p != '\0') {
sum_a *= 10;
sum_a += (int)(*p - '0');
p++;
}
}
if (!flag_b) {
while (*q != '\0') {
sum_b *= 10;
sum_b += (int)(*q - '0');
q++;
}
}
//按照格式输出
if (sum_a > 1000 || sum_a < 1) {
if (sum_b > 1000 || sum_b < 1) {
printf("? + ? = ?");
return 0;
}
else
{
printf("? + %s = ?", b);
return 0;
}
}
else
{
if (sum_b > 1000 || sum_b < 1) {
printf("%s + ? = ?", a);
return 0;
}
else
{
printf("%s + %s = %d", a, b, sum_a + sum_b);
return 0;
}
}
}
思路
- 通过字符数组存储字符串
- 关于空格的处理
- 第一个空格作为A,B分隔符,可通过scanf("%s")处理掉,再用getchar吸收空格
- 之后的空格作为B的组成部分则需要全部读取知道换行符出现,此处有多种处理方式
- 1)使用scanf读取字符集scanf("%[^\n]")
- 2)使用gets读取
但是PTA的编译器似乎没有gets,也没有gets_s
- 另外还可以用getline来读取一行,然后从中找到第一个空格所在处作为A,B的分隔。
- 关于空格的处理
- 判断求和前提
- 遍历两个数组,判断是否为正整数形式
- 使用flag_a;flag_b来存储判断结果
- 在判定求和的条件下,通过将A,B中每位数按权相加得到两者的数值
- 判断数值是否在[1,1000]内
- 按标准正确标准错误输出结果
代码分析
- 通过flag_,flag_b判断是否求和
- 不求和则sum_a/sum_b为零,在代码向后执行时跳转到对应输出
- 求和则按权重相加,数字位数每向左一位,权重变为原来的10倍。在下边的代码中将判断和的范围,即 A,B的值。
- 按要求输出。
个人感想
这道题一下做了60分钟,做的过程中思路挺明确,只是在采用哪种判断依据(只用flag还是和sum一起)的时候重构一下代码出了很多逻辑错误,耗费一点时间,大头都用在了对字符串的处理上,比如scanf停止后,空格仍然留在缓冲区,需要getchar 吸收掉,此前一直以为空格被删除掉了;各种从stdin读取数据的函数的运行模式不是很清楚;读取字符串的多种方式。
参考文章
送上大神关于I/O的总结一份
sun_top的深入详解标准C语IO