团体程序设计天梯赛-练习集 L1-025. 正整数A+B

原题如下:


L1-025. 正整数A+B

时间限制
400 ms
内存限制
65536 kB
代码长度限制
8000 B
判题程序
Standard
作者
陈越

本题的目标很简单,就是求两个正整数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:
? + ? = ?


不妨我再给这道题多几个输入输出样例


输入样例4:

22 22 22
输出样例4:
22 + ? = ?
输入样例5:
1 1234
输出样例5:
1 + ? = ?
输入样例6:
0 123
输出样例6:
? + 123 = ?

通过上述几个笔者增加的输入输出样例,估计得不了满分的同学应该知道需要考虑些什么边界条件了吧。  题目中要求我们注意:我们把输入中出现的第1个空格认为是A和B的分隔。也就是说B中的空格数可无法保证。


有了这些理解,笔者首先写出了如下代码:

#include <iostream>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
using namespace std;
int main()
{
    char a[1000],b[1000];
    cin>>a;
    getchar();
    gets(b);


    int A,B,i,len1,len2,temp1=0,temp2=0,num[1000];
    len1=strlen(a);
    len2=strlen(b);
    for(i=0; i<len1; i++)
    {
        if(a[i]-48>=0&&a[i]-48<=9)
        {
            temp1++;
        }
    }
    for(i=0; i<len2; i++)
    {
        if(b[i]-48>=0&&b[i]-48<=9)
        {
            temp2++;
        }
    }
    A=temp1==len1;
    B=temp2==len2;

    if(A&&B)
    {
        int C=atoi(a)>=1&&atoi(a)<=1000;
        int D=atoi(b)>=1&&atoi(b)<=1000;
        if(C&&D)
            cout<<a<<" + "<<b<<" = "<<atoi(a)+atoi(b)<<endl;
        else if(C&&!D)
            cout<<a<<" + "<<"? = ?"<<endl;
        else if(!C&&D)
            cout<<"? + "<<b<<" = ?"<<endl;
        else
            cout<<"? + ? = ?"<<endl;
    }
    else if(A&&!B)
    {
        cout<<a<<" + "<<"? ="<<" ?"<<endl;
    }
    else if(!A&&B)
        cout<<"? "<<"+ "<<b<<" = ?"<<endl;
    else
        cout<<"? + ? = ?"<<endl;
}


大体需要50行,而且这方法看起来着实笨重,不符合我们追求的代码风骚的要求,这时,笔者想到了C的一个库函数sscanf();用它来处理这道题就游刃有余了,先给出笔者的代码:

#include "bits/stdc++.h"
using namespace std;
int main()
{
  char a[99999],b[99999],atemp[99999],btemp[99999];
  scanf("%s",a);
  getchar();
  gets(b);
  sscanf(a,"%[0-9]",atemp);
  sscanf(b,"%[0-9]",btemp);
  if(strlen(a)>strlen(atemp)&&strlen(b)>strlen(btemp)||!(atoi(a)>=1&&atoi(a)<=1000)&&!(atoi(b)>=1&&atoi(b)<=1000))
    {
      cout<<"? + ? = ?"<<endl;
    }
  else if(strlen(a)>strlen(atemp)||!(atoi(a)>=1&&atoi(a)<=1000))
    {
      cout<<"? + "<<b<<" = ?"<<endl;
    }
  else if(strlen(b)>strlen(btemp)||!(atoi(b)>=1&&atoi(b)<=1000))
    {
      cout<<a<<" + ?"<<" = ?"<<endl;
    }
  else
    {
      cout<<a<<" + "<<b<<" = "<<atoi(a)+atoi(b)<<endl;
    }
}

顿时压缩到了30行以内思路显得十分清晰,对于这道题,我们要判断的,首先是是a和b是不是个 非负整数,也就是a和b中除了0-9这些数字是否存在其他字符,若有,直接pass掉这个数,若没有,则这个数已经是非负整数,由题意我们又知道a和b必须保证在[1,1000]内,故需要进行二重判断,理论上2*2=4种情况,笔者就分了4中情况;


附:关于sscanf()这个函数的用法,做如下解释:

sscanf() - 从一个字符串中读进与指定格式相符的数据.
  函数原型:
  int sscanf( string str, string fmt, mixed var1, mixed var2 ... );
  int scanf( const char *format [,argument]... );
  说明:
  sscanf与scanf类似,都是用于输入的,只是后者以屏幕(stdin)为输入源,前者以固定字符串为输入源。
  其中的format可以是一个或多个 {%[*] [width] [{h | l | I64 | L}]type | ' ' | '\t' | '\n' | 非%符号}
  注:
  1、 * 亦可用于格式中, (即 %*d 和 %*s) 加了星号 (*) 表示跳过此数据不读入. (也就是不把此数据读入参数中)
  2、{a|b|c}表示a,b,c中选一,[d],表示可以有d也可以没有d。
  3、width表示读取宽度。
  4、{h | l | I64 | L}:参数的size,通常h表示单字节size,I表示2字节 size,L表示4字节size(double例外),l64表示8字节size。
  5、type :这就很多了,就是%s,%d之类。
  6、特别的:%*[width] [{h | l | I64 | L}]type 表示满足该条件的被过滤掉,不会向目标参数中写入值
  支持集合操作:
  %[a-z] 表示匹配a到z中任意字符,贪婪性(尽可能多的匹配)
  %[aB'] 匹配a、B、'中一员,贪婪性
  %[^a] 匹配非a的任意字符,贪婪性
注意:在读入的字符串是空字符串时,sscanf函数并不改变待读入到的字符串的值。


例子:
  1. 常见用法。
  char buf[512] = ;
  sscanf("123456 ", "%s", buf);
  printf("%s\n", buf);
  结果为:123456
  2. 取指定长度的字符串。如在下例中,取最大长度为4字节的字符串。
  sscanf("123456 ", "%4s", buf);
  printf("%s\n", buf);
  结果为:1234
  3. 取到指定字符为止的字符串。如在下例中,取遇到空格为止字符串。
  sscanf("123456 abcdedf", "%[^ ]", buf);
  printf("%s\n", buf);
  结果为:123456
  4. 取仅包含指定字符集的字符串。如在下例中,取仅包含1到9和小写字母的字符串。
  sscanf("123456abcdedfBCDEF", "%[1-9a-z]", buf);
  printf("%s\n", buf);
  结果为:123456abcdedf
  5. 取到指定字符集为止的字符串。如在下例中,取遇到大写字母为止的字符串。
  sscanf("123456abcdedfBCDEF", "%[^A-Z]", buf);
  printf("%s\n", buf);
  结果为:123456abcdedf
  6、给定一个字符串iios/12DDWDFF@122,获取 / 和 @ 之间的字符串,先将 "iios/"过滤掉,再将非'@'的一串内容送到buf中
  sscanf("iios/12DDWDFF@122", "%*[^/]/%[^@]", buf);
  printf("%s\n", buf);
  结果为:12DDWDFF
  7、给定一个字符串““hello, world”,仅保留world。(注意:“,”之后有一空格)
  sscanf(“hello, world”, "%*s%s", buf);
  printf("%s\n", buf);
  结果为:world
  %*s表示第一个匹配到的%s被过滤掉,即hello被过滤了


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值