PAT_甲级_1108 Finding Average (20point(s)) (C++)【字符串处理/sscanf与sprintf/测试点3】

目录

1,题目描述

 题目大意

注意

2,思路

3,AC代码

4,解题过程

第一搏

第二搏

第三搏

第四搏

第五搏


1,题目描述

Sample Input 1:

7
5 -3.2 aaa 9999 2.3.4 7.123 2.35

 

Sample Output 1:

ERROR: aaa is not a legal number
ERROR: 9999 is not a legal number
ERROR: 2.3.4 is not a legal number
ERROR: 7.123 is not a legal number
The average of 3 numbers is 1.38

 

Sample Input 2:

2
aaa -9999

 

Sample Output 2:

ERROR: aaa is not a legal number
ERROR: -9999 is not a legal number
The average of 0 numbers is Undefined

 题目大意

将合法的数字进行求和,并输出平均值。

注意

1,不合法的数据:

  • 字符串中含除“-.数字”以外的字符;
  • 若含负号,但未出现在第一位;
  • 含有超过一个小数点的数据;
  • 小数点后面位数超过2位的数据;
  • 表示范围超过区间[-1000, 1000];

2,sscanf与sprintf:

  • double x;
  • char s[100], ss[100];
  • scanf("%s", s);
  • sscanf(s, "%lf", &x);               //将这一字符串输出为一个浮点数x中
  • sprintf(ss, "%.2f", x);             //将这一浮点数输出为一个有两位小数的字符串ss中 
  • for(int i = 0; s[i] != '\0'; i++)   //注意以字符数组表示字符串末尾的方法

3,stod:

  • string s = "123.2";
  • double x = stod(s);

4,输出:

 

2,思路

  1. 设计函数判断字符串是否为合法数字,并将合法数据存放至全局变量x中:
  2. 接收数据并判断,累加合法数据:
  3. 输出:                                              

 

3,AC代码

#include<bits/stdc++.h>
using namespace std;
double x;
char s[100], ss[100];
bool isNum(){
    sscanf(s, "%lf", &x);               //将这一字符串输出为一个浮点数x中
    sprintf(ss, "%.2f", x);             //将这一浮点数输出为一个有两位小数的字符串ss中
    for(int i = 0; s[i] != '\0'; i++)   //注意以字符数组表示字符串末尾的方法
        if(s[i] != ss[i]) return false;
    if(abs(x) > 1000) return false;
    return true;
}
int main(){
#ifdef ONLINE_JUDGE
#else
    freopen("1.txt", "r", stdin);
#endif // ONLINE_JUDGE
    int N;
    scanf("%d", &N);
    double ans = 0;
    int num = 0;
    for(int i = 0; i < N; i++){
        scanf("%s", s);
        if(isNum()){
            num++;
            ans += x;
        }else{
            printf("ERROR: %s is not a legal number\n", s);
        }
    }
    if(num == 0)
        printf("The average of 0 numbers is Undefined");
    else if(num == 1)
        printf("The average of 1 number is %.2f", ans);//number不加s
    else
        printf("The average of %d numbers is %.2f", num, ans / num);
    return 0;
}

 

4,解题过程

第一搏

自认为这是涉及数字字符串处理中,最简单的一题。(毕竟不是哪种毫无思路,怎么做都别扭的题目orz,但。我错了)

#include<bits/stdc++.h>
using namespace std;
bool isNum(string s){
    int point = 0;
    int i = s[0] == '-' ? 1 : 0;
    for(; i < s.size(); i++){
        if(s[i] == '.'){
            if(point == 0)//目前没有小数点
                point = i;
            else//已有小数点
                return false;
        }else if(!isdigit(s[i]))//是否含有非数字字符
            return false;
    }
    if(s.size() - point - 1 > 2)//判断精确位置是否超过2位
        return false;

    double n = stod(s);
    if(n >= -1000 && n <= 1000)
        return true;
    return false;
}
int main(){
#ifdef ONLINE_JUDGE
#else
    freopen("1.txt", "r", stdin);
#endif // ONLINE_JUDGE
    int N;
    scanf("%d", &N);
    string s;
    double ans = 0;
    int num = 0;
    for(int i = 0; i < N; i++){
        cin>>s;
        if(isNum(s)){
            num++;
            ans += stod(s);
        }else{
            cout<<"ERROR: "<<s<<" is not a legal number"<<endl;
        }
    }
    if(num == 0)
        printf("The average of 0 numbers is Undefined");
    else if(num == 1)
        printf("The average of 1 number is %.2f", ans);//number不加s
    else
        printf("The average of %d numbers is %.2f", num, ans / num);
    return 0;
}

第二搏

又到了精彩的推理环节了o(* ̄▽ ̄*)ブ

在判断字符串是否为数字时,考虑了四种情况:

  1. 含有多个小数点;
  2. 含有非数字字符;
  3. 精确位数大于2;
  4. 数字表示范围超过[-1000,1000];

此时,若s=='.'s=='-.'s=='-'时,stod函数会出错,于是加上了这个:

可惜并不是

第三搏

又发现,point的初始值不能设为0,因为若输入为 .0.12时,第二个小数点读入时检测到point为0,便将第二个小数点的位置覆盖掉point。于是我便把point初值设为-1:

然而仍然不是。。。

第四搏

此时的我已经在击碎电脑屏幕的边缘(╯‵□′)╯︵┻━┻

(虽然已经了解到,使用sscanf可以完全不用考虑这些问题,但浪费了我一个小时的BUG,我绝不会这么轻易的放过他!(╯▔皿▔)╯)

事实证明,我的倔强将会再次浪费我两个小时。。。

经过即为曲折的过程(寻找类似代码,手动设计测试数据,甚至查验stod函数的特性。。。)

终于( ̄y▽ ̄)╭ Ohohoho.....

按照我的算法,当字符串中未出现小数点时,point将保持初值-1,若此时不判断point是否为-1,而直接利用s.size() - point - 1 > 2来判断小数点后的位数时,会产生精度位数过大的错误。

比如输入123,此时point = -1,小数点后的位数3-(-1)=4,误判为超过精度!

第五搏

当我把求索过程中的补丁去掉以后(如图红框的部分)

仍然可以通过全部示例,说明.12是否合法并不影响题目的解决!(看网上说法不一,经过亲身实践后,确实没有此差异,可能没有涉及到类似的示例)

#include<bits/stdc++.h>
using namespace std;
bool isNum(string s){
    int point = -1;
    string s1 = s.substr(0, 2);
    if(s == "-." || s == "." || s == "-" || s1 == "-." || s1[0] == '.')
        return false;
    int i = s[0] == '-' ? 1 : 0;
    for(; i < s.size(); i++){
        if(s[i] == '.'){
            if(point == -1)
                point = i;
            else
                return false;//小数点超过一个
        }else if(!isdigit(s[i]))//是否含有非数字字符
            return false;
    }
    if(point != -1 && s.size() - point - 1 > 2)//判断精确位置是否超过2位
        return false;

    double n = stod(s);
    if(n >= -1000 && n <= 1000)
        return true;
    return false;
}
int main(){
#ifdef ONLINE_JUDGE
#else
    freopen("1.txt", "r", stdin);
#endif // ONLINE_JUDGE
    int N;
    scanf("%d", &N);
    string s;
    double ans = 0;
    int num = 0;
    for(int i = 0; i < N; i++){
        cin>>s;
        if(isNum(s)){
            num++;
            ans += stod(s);
        }else{
            cout<<"ERROR: "<<s<<" is not a legal number"<<endl;
        }
    }
    if(num == 0)
        printf("The average of 0 numbers is Undefined");
    else if(num == 1)
        printf("The average of 1 number is %.2f", ans);//number不加s
    else
        printf("The average of %d numbers is %.2f", num, ans / num);
    return 0;
}

 

 

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值