團體程序設計天梯賽-練習集 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被過濾了


發佈了45 篇原創文章 · 獲贊 27 · 訪問量 13萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章