其他分享
首页 > 其他分享> > 1054 求平均值 (20 point(s))

1054 求平均值 (20 point(s))

作者:互联网

// 正确代码
#include <bits/stdc++.h>
using namespace std;

int main() {
	// N个实数 剔除非法数据 求平均值
	int n, legal = 0;
	double result = 0, num = 0;
	cin >> n;

	while(n--) {
		char a[100], b[100];
		scanf("%s", &a);
		sscanf(a, "%lf", &num);
		sprintf(b, "%.2f", num);
		int flag = 0;
		for(int j = 0; j < strlen(a); j++)
			if(a[j] != b[j]) flag = 1;
		
		// 非数字判断 或 区间判断
		if(flag || abs(num) > 1000)
			printf("ERROR: %s is not a legal number\n", a);
		// 合法统计
		else
			result += num, legal++;
	}

	// 结果保留两位小数
	if(legal == 0)
		printf("The average of 0 numbers is Undefined");
	else if(legal == 1)
		printf("The average of 1 number is %.2f", result);
	else
		printf("The average of %d numbers is %.2f", legal, result / legal);
}
// 15分代码
#include <bits/stdc++.h>
using namespace std;

// 判断两位小数 
bool two(string str){
	int point = false, cnt = 0;
	for(auto s : str){
		if(s == '.'){
			point = true;
			// 跳过当前小数点. 防止多统计一次 
			continue;
		} 
		// 有小数点后开始统计
		if(point == true)  ++cnt;
		if(cnt > 2) return true;
	}
	return false;
}

bool alpha(string str){
	int cnt = 0;
	for(auto s : str){
		if(isalpha(s))  ++cnt;
		if(cnt > 0) return true;
	}
	return false;
}

int main() {
	// N个实数 剔除非法数据 求平均值  
	int n, legal = 0; 
	double result = 0;
	cin >> n;
	
	while(n--){
		string str;
		cin >> str;
		// 非数字判断 或 区间判断
		if(alpha(str) || count(begin(str), end(str), '.') > 1 ||
	 	two(str) || abs(stoi(str)) > 1000)
			printf("ERROR: %s is not a legal number\n", str.c_str());
		// 合法统计 
		else
			result += atof(str.c_str()), legal++;
	}
	
	// 结果保留两位小数 
	if(legal == 0)
		printf("The average of 0 numbers is Undefined");
	else
		printf("The average of %d numbers is %.2f", legal, result / legal);
}

其实感觉不需要自己额外判断,如果可以捕获错误的话,用try-catah打印错误信息即可。不过试了下不晓得c++要怎么写,好像atof不会抛出异常。

试了试,原来c++的cin会自动截取正确数据,而不会认为输入的这一串东西应该属于一个类型。所以就没有抛出异常。atof应该也是同理。

image


看别人的代码用到了 sscanf 和 sprintf 跟原来的输入输出区别仅在于前面多了一个 s ,应该跟字符串 string 关系的缘故。

sscanf 是将字符串以格式化输出到其他变量,就像 scanf 区别只是将标准化输入设备 stdin 换成了 string 字符串作为输入。sscanf 跟 scanf 一样不要忘了加 & 取地址。

sprintf 同理,将本来输出 stdout 变成了字符串。

scanf("%s", a);

别人代码处,因为 a 作为字符串数组变量名本身就是地址了,所以就不需要加 & 。 字符串和其他类型的数组应该具有相似的原理。


image

然后看下别人这部分代码是怎么工作的。

image

首先是输入正确数据的话,a 里面会得到一个 5,而 5 通过 %.2f 传给 b 就会变成浮点类型,多出小数点和后面的 0 。但后面有判断语句,条件是根据 a 的长度比较转换成 b 之后其中的字符是否一致。虽然长度上 b > a , 但只判断到 a 的 5就停止了,后面多出来的没关系,也算正确。这是整型时情况。

image

如果是正确的浮点和整型类似,只是 a 也会有小数点后面的数据。

image

image

如果输入乱七八糟的情况,比如全部非数字的,或者前面数字后面非数字的,可以看到测试结果的处理方式跟前面,cin 输入如果遇到非对应数据类型的处理方式相似,只会将正确的部分读取,而其他抛弃。

比如上面的图,全部是字母情况,那么一个正确的 double 类型的数据都没有,所以只能够得到一个 0.00 的结果。而下面的情况,就将前面正确的数截取,后面的全部抛弃,比如 5 就留下来变成了 5.00 后面从 a 开始的部分就没有了,即便里面可能有数字。

image

多余小数点的处理思路类似,一个小数点是合法浮点数,再多就非法,所以多余小数点及其后面部分就被抛弃了。

image

而如果是超过合法的两位小数位,那么在判断时候,会判断两个字符串不同位置是否一致,显然 a 后面还有许多数字,跟合法的 b 就不相同,就会返回 false。

参考代码


当时自己写是差 2 3 测试点未通过,想了想虽然参考别人的解题方法能够全部AC,也知道别人的处理的方法,但是自己应该怎样调整还是很困难的,或者说自己原来缺陷的部分应该怎样改进,光靠别人正确的代码还是很困难的。


刚才查阅的时候还试了试字符数组和字符串之间的转化,如果是字符数组转成字符串的话,直接等号赋值即可, str = a; 这样。

如果是字符串赋值给字符数组,则需要借助一个函数 strcpy() C语言里面,同时将字符串转化成字符数组用 c_str() 函数 变成 strcpy(a, str.c_str()); 。

C++中字符数组与string的相互转换


当时只知道一个字符串转换成数字的函数 stoi(),以为这个东西能够变成浮点数,结果测试只能够变成整型。而变成浮点数得借助另一个函数 atof() 。


这题还有一个要注意的,就是输出的时候字符串里面有一个单词 number 复数的时候是会 + s 的 numbers 如果是一个结果就是 number 。

也就说以后输出的时候不仅要考虑数据上面的边界问题,还得注意下输出的东西是否符合英文的语法。。

所以查了查,发现还是有很多人研究不同测试点的特殊情况是什么的。我们可以借助这些对应的文章来改进原来考虑的不足,这比单纯学习别人全部AC的方法要更好点。

不然真正写的时候,光有方法但对于特殊情况没有意识,即便知道方法也不知道应该用怎样的方式来处理。

标签:1054,point,int,legal,result,str,printf,字符串,20
来源: https://www.cnblogs.com/Atl212/p/15221302.html