题目介绍
The basic task is simple: given N real numbers, you are supposed to calculate their average. But what makes it complicated is that some of the input numbers might not be legal. A legal input is a real number in [−1000,1000] and is accurate up to no more than 2 decimal places. When you calculate the average, those illegal numbers must not be counted in.
Input Specification:
Each input file contains one test case. For each case, the first line gives a positive integer N (≤100). Then N numbers are given in the next line, separated by one space.
Output Specification:
For each illegal input number, print in a line ERROR: X is not a legal number
where X
is the input. Then finally print in a line the result: The average of K numbers is Y
where K
is the number of legal inputs and Y
is their average, accurate to 2 decimal places. In case the average cannot be calculated, output Undefined
instead of Y
. In case K
is only 1, output The average of 1 number is Y
instead.
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
注解
原本我的解法,就是根据题目的输入样例,来归纳一个合格的浮点数是怎么样的。
我当时总结出了这样的规律:
- 如果有符号,那就在开头,否则就不要有
- 数字中间部分,只能有一次浮点数,或者不要有,而只有数字
- 不能出现除符号+数字+浮点之外其余字符
- 在[-1000,1000]范围内
- 浮点数只有精确两位
然后写出了很繁琐的代码,不过最后倒也能过。
但翻看了柳婼学姐的代码:1108. Finding Average (20)-PAT甲级真题_柳婼 の blog-优快云博客
不得不赞叹,柳婼学姐在这题的思路确实厉害。
如果不是有这个函数,原本给定一个字符串,来判断它是不是一个正常的浮点数是非常麻烦的。
但现在有了sscanf和sprintf的存在,这个大难题就交给了系统,是内置函数帮我们做的。
(正常读进去了就接着后面的判断,如果是错误输入而无法读取,那么temp就会保持原本的值,起初是0,不影响,之后就算读入了,也是旧值,后面字符串逐位判断也是走不过的)
随后,得到的是一个正常浮点数。
再判断范围,以及通过输出到字符串与此前状态比较来判断是否是不超过两位小数。
题目也就结束了。
代码
我的很繁琐但也能过的代码,权当记录一下。
#include<bits/stdc++.h>
using namespace std;
//要求
//1.如果有符号,那就在开头,否则就不要有
//2.数字中间部分,只能有一次浮点数,或者不要有,而只有数字
//3.不能出现除符号+数字+浮点之外其余字符
//4.在[-1000,1000]范围内
//5.浮点数只有精确两位
//最后一个测试点不太好想,59.也是合理的浮点数!
int main()
{
int N;
cin>>N;
string s;
double sum=0;
int K=0;
while(N--)
{
cin>>s;
//先判断是不是要求的数-符号部分
int flag=1; //是的标记
if(!(s[0]=='-' || isdigit(s[0]))) flag = 0;
int cou=0; //浮点出现次数
for(int i=1;i<s.size();i++)
{
if(!(isdigit(s[i]) || s[i]=='.'))
{
flag=0;
break;
}
if(s[i]=='.') cou++;
}
if(cou>1) flag=0;
if(flag==0) //不是合理数字
{
cout<<"ERROR: "<<s<<" is not a legal number\n";
continue;
}
//判断是不是要求的数-数值部分 <=> 转换计算
int point = s.find("."); //小数点位置
if(point==-1) //整数
{
int value = 0;
if(s[0]=='-')
{
for(int i=1;i<s.size();i++) value = value*10+s[i]-'0';
value = -value;
}
else
{
for(int i=0;i<s.size();i++) value = value*10+s[i]-'0';
}
if(value>=-1000&&value<=1000)
{
sum += value;
K++;
}
else
cout<<"ERROR: "<<s<<" is not a legal number\n";
}
else //浮点数
{
if(s[0]=='-' && s.size()-point-1<=2 || s[0]!='-'&&s.size()-point-1<=2)
{
double value = 0;
if(s[0]=='-')
{
for(int i=1;i<point;i++) value = value*10+s[i]-'0';
if(s.size()-point-1==1) value += 0.1*(s[point+1]-'0');
else if(s.size()-point-1==2) value += 0.1*(s[point+1]-'0')+0.01*(s[point+2]-'0');
value = -value;
}
else
{
for(int i=0;i<point;i++) value = value*10+s[i]-'0';
if(s.size()-point-1==1) value += 0.1*(s[point+1]-'0');
else if(s.size()-point-1==2) value += 0.1*(s[point+1]-'0')+0.01*(s[point+2]-'0');
}
if(value>=-1000&&value<=1000)
{
sum += value;
K++;
}
else
cout<<"ERROR: "<<s<<" is not a legal number\n";
}
else
cout<<"ERROR: "<<s<<" is not a legal number\n";
}
}
if(K==0) printf("The average of 0 numbers is Undefined\n");
else if(K==1) printf("The average of 1 number is %.2lf\n",sum);
else printf("The average of %d numbers is %.2lf\n",K,sum/K);
return 0;
}