PAT Basic 1054. 求平均值
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;
}