PAT Basic 1054. 求平均值

发布时间 2023-03-30 15:35:52作者: 十豆加日月

PAT Basic 1054. 求平均值

1. 题目描述:

本题的基本要求非常简单:给定 \(N\) 个实数,计算它们的平均值。但复杂的是有些输入数据可能是非法的。一个“合法”的输入是 \([−1000,1000]\) 区间内的实数,并且最多精确到小数点后 2 位。当你计算平均值的时候,不能把那些非法的数据算在内。

2. 输入格式:

输入第一行给出正整数 \(N\)\(≤100\))。随后一行给出 \(N\) 个实数,数字间以一个空格分隔。

3. 输出格式:

对每个非法输入,在一行中输出 ERROR: X is not a legal number,其中 X 是输入。最后在一行中输出结果:The average of K numbers is Y,其中 K 是合法输入的个数,Y 是它们的平均值,精确到小数点后 2 位。如果平均值无法计算,则用 Undefined 替换 Y。如果 K 为 1,则输出 The average of 1 number is Y

4. 输入样例:

7
5 -3.2 aaa 9999 2.3.4 7.123 2.35
2
aaa -9999

5. 输出样例:

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
ERROR: aaa is not a legal number
ERROR: -9999 is not a legal number
The average of 0 numbers is Undefined

6. 性能要求:

Code Size Limit
16 KB
Time Limit
400 ms
Memory Limit
64 MB

思路:

不算除草题吧,考察基础IO,核心就是处理非法输入。一开始感觉无从下手,想着要把整行输入全部读入依次处理后再一起输出,还在想要分配多大的数组。。。

再看的时候发现依次处理每一个字符串即可,根据题意编写一个判断是否合法的子函数,注释掉的代码部分是一开始的想法,使用sscanf()sprintf()库函数一正一反获得转换后的字符串,然后再利用strcmp()库函数进行比较判断,然后发现不符合题意。。。因为题目要求最多2位小数点,而不是必须2位小数点。

最后还是对遍历每个字符进行判断,这里主要涉及的判断条件有:

  • 是否能读入一个double类型的数值
  • 数值是否在\([−1000,1000]\)区间内
  • 是否只有一个小数点
  • 小数点后是否只有两位小数

这四个判断条件即可AC,然后第一次提交时testpoint2报Runtime Error,考虑到是可能存在较长的非法输入,把数组大小增大到100后AC,一开始想着最大值1000.00共7个字符就分配了大小为8的数组。

另外就是这里其实还应该在遍历每个字符时对是否为数字进行判断,如果不进行判断的话,对于非法输入"1.AA"还是会当成合法输入"1.0"的,不过目前的测试用例不需要这个条件即可AC。

My Code:

#include <stdio.h> // sscanf header
#include <string.h> // strcmp header

int judgeNum(const char *tempStr, double *tempDb);

int main(void)
{
    int numCount = 0;
    //char tempStr[8] = ""; // first submit testpoint2 Runtime Error, for this array size is too small, cause out of range
    char tempStr[100] = "";
    double tempDb = 0.0;
    int validCount = 0;
    double res = 0.0;
    int i=0; // iterator
    
    scanf("%d", &numCount);
    for(i=0; i<numCount; ++i)
    {
        scanf("%s", tempStr);
        if(judgeNum(tempStr, &tempDb)) // valid Num
        {
            res += tempDb;
            ++validCount;
        }
        else // invalid Num
        {
            printf("ERROR: %s is not a legal number\n", tempStr);
        }
    }
    
    if(!validCount) // validCount == 0
    {
        printf("The average of 0 numbers is Undefined\n");
    }
    else if(validCount == 1)
    {
        printf("The average of 1 number is %.2lf\n", res);
    }
    else
    {
        printf("The average of %d numbers is %.2lf\n", validCount, res/validCount);
    }
    
    
    return 0;
}

int judgeNum(const char *tempStr, double *tempDb) // return 1 for valid Num, 0 for invalid Num
{
    //char convertStr[8] = "";
    int dotCount = 0;
    int decimalCount = 0;
    int i=0;
    
    if(!sscanf(tempStr, "%lf", tempDb)) // can't get a double
    {
        return 0;
    }
    if(*tempDb < -1000 || *tempDb > 1000)
    {
        return 0;
    }
    
    for(i=0; *(tempStr+i); ++i)
    {
        // no this If also can AC for current testpoint, but this if is needed. 
        // If no this condition, '1.AA' will be think a valid input '1.0'
        if(*(tempStr+i)!='.' && *(tempStr+i)!='-' && (*(tempStr+i) < '0' || *(tempStr+i)>'9'))
        {
            return 0;
        }
        
        if(dotCount>0) // the order of 2 if is important!!!
        {
            ++decimalCount;
        }
        
        if(*(tempStr+i) == '.')
        {
            ++dotCount;
        }

    }
    
    if(dotCount > 1 || decimalCount > 2)
    {
        return 0;
    }
    
    //printf("%lf\n", *tempDb); // test output
    return 1;
    
//     char convertStr[8] = "";
//     //int sscanf(const char *str, const char *format, ...)
//     sscanf(tempStr, "%lf", tempDb);
//     //int sprintf(char *str, const char *format, ...)
//     sprintf(convertStr, "%.2lf", *tempDb);
//     //int strcmp(const char *str1, const char *str2)
    
//     printf("tempStr: %s, converStr: %s\n", tempStr, convertStr);
// //     if(*tempDb >= -1000)
// //         printf("Correct!\n");
    
//     if(!strcmp(tempStr, convertStr) && *tempDb >= -1000 && *tempDb <= 1000)
//     {
//         return 1;
//     }
//     return 0;
}