本题的基本要求非常简单:给定 N 个实数,计算它们的平均值。但复杂的是有些输入数据可能是非法的。一个“合法”的输入是 [−1000,1000] 区间内的实数,并且最多精确到小数点后 2 位。当你计算平均值的时候,不能把那些非法的数据算在内。
输入格式:
输入第一行给出正整数 N(≤100)。随后一行给出 N 个实数,数字间以一个空格分隔。
输出格式:
对每个非法输入,在一行中输出 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
。
输入样例 1:
7
5 -3.2 aaa 9999 2.3.4 7.123 2.35
输出样例 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
输入样例 2:
2
aaa -9999
输出样例 2:
ERROR: aaa is not a legal number
ERROR: -9999 is not a legal number
The average of 0 numbers is Undefined
做了三天的题,一开始第一次看到的时候完全没有任何思路,只能想到用字符串数组去实现。最多100个数,则定义字符串数组aa[100],通过访问下标可以输出某一个字符串。
简单地想到了利用for循环。 最难处理的是许多种的情况,一开始对于情况的分析如下:主要解决四个问题,负号,小数点的数目,其他符号是否存在,数字的大小合法性。
对于有无负号,先对第一位进行判别。有负号,则逐个比较的字符要从下标为1的位置开始,若无负号,则从下标为0开始。
统计完负号后,再统计小数点的数目以及其余的符号。记录下小数点的位置,若存在不等于小数点或数字的字符,则判断为错误,输出。
当不存在其余字符时,若小数点数目为0,通过for循环逐个位置计算。小数点数目为1,通过小数点被记录下的位置进行数值的计算。小数点数目大于等于2时,直接报错。
小数点的位置解决后,最后需要检验数字是否合法。当数字计算的数字大于等于1000时,报错即可。当小于等于1000,对正负号判断,正数则加,复数则减,数字的数目进行加。至于数字的位数,在报错时进行判断len-placep是否大于等于4即可。
但这么做仍然会有测试点234无法过,最直接的便是测试点3,注意读题只有一个合法数字的时候应该是number而非numbers。测试点2与4是一并解决的。当时写出的对于小于-1000的判断条件是直接写number<-1000,但其实number计算得一个正数,代表输入数的绝对值。倘若输入的是负数,只需在求和部分减去number即可。无论正数或负数,number大于1000即是非法。
代码如下:
#include <iostream>
#include <string.h>
#include <iomanip>
using namespace std;
string aa[100];
int main()
{
int n;
cin>>n;
for(int i=0; i<n; i++)
{
cin>>aa[i];
}
int shuzi=0;//记录数字个数
double sum=0;
int k=0;
double time1=1;
double time2=0.1;
for(int i=0; i<n; i++)
{
int len=aa[i].length();
double number=0;//记录数字
int countp=0;//统计小数点
int placep=0;//记录下小数点的位置如果有
int j=0,l=0,t=0;
int flag2=0;//代表字符
int flag=0;//flag为0代表正数?
if(aa[i][0]=='-')
{
flag=1;//可能是负数
j=1;
l=1;
t=1;
}
for(j; j<len; j++)
{
if(aa[i][j]=='.')
{
countp++;
placep=j;
}
else if(aa[i][j]<'0'||aa[i][j]>'9')
{
flag2=1;
}
}
if(flag2==1)
{
cout<<"ERROR: "<<aa[i]<<" is not a legal number"<<endl;
//cout<<"字符错误"<<endl;
continue;
}
else if(flag2==0)
{
if(countp==0)
{
for(l; l<len; l++)
{
k=(int)aa[i][l]-(int)'0';
time1=1;
for(t=0; t<len-l-1; t++)
{
time1*=10;
}
number += time1*k;
}
}
else if(countp==1)
{
time2=0.1;
for(l; l<len; l++)
{
if(l==placep)
{
continue;
}
else
{
k=((int)aa[i][l]-(int)'0');
if(l<placep)
{
time1=1;
for(t=0; t<placep-l-1; t++)
{
time1*=10;
}
number+=time1*k;
}
else if(l>placep)
{
number+=time2*k;
time2*=0.1;
}
}
}
}//有小数点
else if(countp>=2)
{
cout<<"ERROR: "<<aa[i]<<" is not a legal number"<<endl;
//cout<<"两个小数点"<<endl;
continue;
}
if(flag==0)
{
if((len-placep)>=4&&countp==1)
{
cout<<"ERROR: "<<aa[i]<<" is not a legal number"<<endl;
//cout<<"小数位数过多"<<endl;
continue;
}
else if(countp<=1)
{
if(number>1000)
{
cout<<"ERROR: "<<aa[i]<<" is not a legal number"<<endl;
//cout<<"数字过大"<<endl;
continue;
}
else if(number<=1000)
{
sum+=number;
//cout<<number<<endl;
shuzi++;
//cout<<number<<" ";
}
}
}
else if(flag==1)
{
if((len-placep)>=4&&countp==1)
{
cout<<"ERROR: "<<aa[i]<<" is not a legal number"<<endl;
//cout<<"小数位数过多"<<endl;
continue;
}
else
{
if(number>1000)
{
cout<<"ERROR: "<<aa[i]<<" is not a legal number"<<endl;
//cout<<number<<endl;
//cout<<"数字过小"<<endl;
continue;
}
else if(number<=1000)
{
sum-=number;
//cout<<number<<endl;
shuzi++;
}//负数有小数点
}
}
}
}
if(shuzi==0)
{
cout<<"The average of "<<0<<" numbers is Undefined"<<endl;
}
else if(shuzi==1)
{
cout<<"The average of 1 number is "<<setiosflags(ios::fixed)<<setprecision(2)<<sum/shuzi<<endl;
}
else
{
cout<<"The average of "<<shuzi<<" numbers is "<<setiosflags(ios::fixed)<<setprecision(2)<<sum/shuzi<<endl;
}
return 0;
}
//问题在于 负数与小数点的关系无法弄清,两位小数也无法求解