PAT 1054求平均值(20分)

目录

解题思路:

分层解析:

代码部分:

关于人为书写检测机制的技巧:


本题的基本要求非常简单:给定 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

解题思路:

首先判断输入是否合法,具体有以下要求:

1.是实数;

2.范围在[-1000,1000]内 &&如果有小数点,小数至多两位;

其次,按照要求书写主函数,进行输出显示层面的编程;

分层解析:

1.是实数:

        首先,输入的就不一定为一个数,所以输入的数据类型就应该是字符数组;循环遍历这个数组,需要判断这3点来证明输入的字符数组是否可以转化为实数:

        只由数字、一个或零个负号、一个或零个小数点组成;

        判断方法为,在满足以上条件下,符合以上条件的字符数总数是否等于字符数组长度;

2.范围与小数位数:

        范围很好判断,在已经判断字符数组可以转化为实数之后,就可以用atof()函数来实现转化,从而判断范围;

        关于包括atof()在内的所有字符串转数字的函数及其相应用法,请参考以下连接:https://blog.csdn.net/bc202205/article/details/128433151?spm=1001.2014.3001.5501

        小数位数:循环遍历数组,确定小数点的位置;通过求取小数点后有几个数组元素,就可以确定该字符数组所转化的实数是否满足小数位数的要求了;

代码部分:

函数代码实现如下:

#include <iostream>
#include <cstring>
using namespace std;
bool isnumber(char a[], int len)//判断是否为实数;
{
	int counts = 0, countdots = 0, countfu = 0;
	for (int i = 0; i < len; i++)
	{
		if (a[i] >= '0' && a[i] <= '9')
			counts++;
		else if (a[i] == '.')
			countdots++;
		else if (a[i] == '-')
			countfu++;
	}
	return (counts + countdots + countfu == len)
		&& (countdots == 0 || countdots == 1)
		&& (countfu == 0 || countfu == 1) ? true : false;
}
bool isfloat(char a[], int len)
{
	if (isnumber(a, len) && (atof(a) > 1000 || atof(a) < -1000))
		return false;//判断是否为范围内的实数;
	else//判断是否为2位小数以内的实数;
	{
		int pos = -1;
		if (isnumber(a, len))
		{
			for (int i = 0; i < len; i++)
				if (a[i] == '.')
					pos = i;
			if (pos == -1)
				return true;
			else
				return len - pos - 1 <= 2 ? true : false;
		}
		else
			return false;
	}
}
int main()
{
	int n;
	cin >> n;
	char a[100];
	int counts = 0;
	double sum = 0;
	for (int i = 0; i < n; i++)
	{
		cin >> a;
		if (isfloat(a, strlen(a)) == false)
			cout << "ERROR: " << a << " is not a legal number" << endl;
		else
		{
			counts++;
			sum += atof(a);
		}
	}
	//一定要对counts的情况根据题意分开讨论!
	if (counts == 0)
		cout << "The average of 0 numbers is Undefined";
	else if (counts == 1)
	{
		cout << "The average of " << counts << " number is ";
		printf("%.2f", sum / counts);//测试点3;
	}
	else
	{
		cout << "The average of " << counts << " numbers is ";
		printf("%.2f", sum / counts);
	}
	return 0;
}

关于人为书写检测机制的技巧:

        发现答案部分正确怎么办?判断条件太多,不妨在函数内自己书写检测机制

        如果用此方法,不太适合用“?:”表达式了,虽然if else语句相较于“?:”表达式,书写起来可能会比较繁琐,但是对于编程漏洞的检查起到很大帮助;

        笔者写的检测机制如下:

#include <iostream>
#include <cstring>
using namespace std;
bool isnumber(char a[],int len)
{
	int counts = 0, countdots = 0, countfu = 0;
	for (int i = 0; i < len; i++)
	{
		if (a[i] >= '0' && a[i] <= '9')
			counts++;
		else if (a[i] == '.')
			countdots++;
		else if (a[i] == '-')
			countfu++;
	}
	//监测点一;
	if ((counts + countdots + countfu == len)
		&& (countdots == 0 || countdots == 1)
		&& (countfu == 0 || countfu == 1))
		return true;
	else
	{
		cout << "error1" << endl;
		return false;
	}
	/*//原代码
	return (counts+countdots+countfu == len)
		&&(countdots==0||countdots==1)
		&&(countfu==0||countfu==1) ? true : false;
	*/
}
bool isfloat(char a[], int len)
{
	if (isnumber(a, len) && (atof(a) > 1000 || atof(a) < -1000))
	{
		cout << "error2" << endl;//监测点二;
		return false;//原代码只有这一句
	}

	else
	{
		int pos = -1;
		if (isnumber(a, len))
		{
			for (int i = 0; i < len; i++)
				if (a[i] == '.')
					pos = i;
			//监测点三;
			if (pos == -1)
				return true;
			else
			{
				if (len - pos - 1 <= 2)
					return true;
				else
				{
					cout << "error3" << endl;
					return false;
				}
				//return len - pos-1 <= 2 ? true : false;//原代码只有这一句;
			}
		}
		else
		{
			cout << "error4" << endl;//监测点五;
			return false;//原代码只有这一句;
		}

	}
}
int main()
{
	int n;
	cin >> n;
	char a[100];
	int counts = 0;
	double sum = 0;
	for(int i=0;i<n;i++)
	{
		cin >> a;
		if (isfloat(a, strlen(a)) == false)
			cout << "ERROR: " << a << " is not a legal number" << endl;
		else
		{
			counts++;
			sum += atof(a);
		}
	}
	//一定要对counts的情况根据题意分开讨论!
	if (counts == 0)
		cout << "The average of 0 numbers is Undefined";
	else if(counts==1)
	{
		cout << "The average of " << counts << " number is ";
		printf("%.2f", sum / counts);//测试点3
	}
	else
	{
		cout << "The average of " << counts << " numbers is ";
		printf("%.2f", sum / counts);
	}
	return 0;
}

 这样,我们就在函数中建立了检测机制。当我们输入样例时,程序会自动告知我们,到底是函数判断的哪部分出现了漏洞;

比方说,我们现在将监测点三中的判断条件改为len-pos<=2,我们一起看一下会出现什么结果。

输入样例一,运行结果如下:

我们可以清楚地看到,2.35  这个数“应对未对”,原因是在error3的位置出现了错误,从而定点修改。

以上就是小编写的一点解析,有帮助的话帮忙点个赞呦~

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

青山入墨雨如画

你的鼓励将是我创作的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值