题目链接:
由于输入可能有字母或是多个小数点,因此采用字符数组的方式输入(%s)。
本题主要的难点在于判断每一个输入数据是否合法。
分析:
使用sscanf和sprintf函数~
sscanf() – 从一个字符串中读进与指定格式相符的数据
sprintf() – 字符串格式化命令,主要功能是把格式化的数据写入某个字符串中
#include <bits/stdc++.h>
using namespace std;
int main() {
int n, cnt = 0;
char a[50], b[50];
double temp = 0.0, sum = 0.0;
cin >> n;
for(int i = 0; i < n; i++) {
scanf("%s", a);
sscanf(a, "%lf", &temp);//把字符串a中的浮点数取出
sprintf(b, "%.2f", temp);//将浮点数temp保留两位小数读到字符串b中(此时字符串b为“看起来是两位小数”的字符串)
int flag = 0;
for(int j = 0; j < strlen(a); j++)//因为是“最多精确到小数点后2位”,所以a的字符串长度一定>=b的,所以循环结束为到strlen(a)为止。
{if(a[j] != b[j]) flag = 1;}//如果a[j]!=b[j],说明a不是两位小数以内的实数,输出~~~。
if(flag || temp < -1000 || temp > 1000) {
printf("ERROR: %s is not a legal number\n", a);
continue;//直接开始下一步循环
} else {//输入合法则求和,且计数器++
sum += temp;
cnt++;
}
}
/*模拟*/
if(cnt == 1)
printf("The average of 1 number is %.2f", sum);
else if(cnt > 1)
printf("The average of %d numbers is %.2f", cnt, sum / cnt);
else
printf("The average of 0 numbers is Undefined");
return 0;
}
验证程序:
int n, cnt = 0;
char a[50], b[50];
double temp = 0.0, sum = 0.0;
cin >> n;
for(int i = 0; i < n; i++) {
scanf("%s", a);
sscanf(a, "%lf", &temp);
sprintf(b, "%.2f", temp);
printf("a = %s , b = %s\n\n\n", a, b);
补充:
1、sscanf函数(包含于#include <cstdio>
头文件中):
1、作用:从一个字符串中读进于指定格式相符的数据。利用它可以从字符串中取出整数、浮点数和字符串。
2、函数原型:int sscanf(const char *str, const char *format,......);
3、和scanf的区别:scanf是以键盘作为输入源,sscanf是以字符串作为输入源。
4、用法概述:
sscanf()会将参数str的字符串根据参数format字符串来转换格式并格式化数据。转换后的结果存于对应的参数内。
5、函数返回值:成功则返回参数数目,失败则返回0
例1:取指定长度的字符串/读入字符串:
#include<cstdio>
int main()
{
char str[100];
sscanf("12345","%4s",str);
printf("%s\n",str);
return 0;
}
//输出1234
#include<cstdio>
int main()
{
char str[100];
sscanf("12345","%s",str);
printf("%s\n",str);
return 0;
}
//输出12345
#include<cstdio>
int main()
{
char str1[100], str2[100], str3[100];
gets(str1);
sscanf(str1,"%s%s",str2,str3);
printf("%s %s\n",str2,str3);
return 0;
}
//输入xinxi love you
//输出xinxi love
例2:整型数字/浮点数转换:
2.1:
int year, month, day;
int converted = sscanf("20191103", "%04d%02d%02d", &year, &month, &day);
printf("converted = %d, year = %d, month = %d, day = %d\n", converted, year, month, day);
输出:
converted = 3, year = 2019, month = 11, day = 03
"%04d%02d%02d"是用来解析字符串的格式,%表示格式转换的开始,d表示转换为一个整数,04作为d的修饰,表示这是一个长度为4位的整数,不足4位时以0补齐。
例子返回结果等于3,表示有3个数据成功转换,转换成功数目同时取决于被解析的字符串以及其转换格式,如果我们把例子中的格式改为"%04d%02d",那么sscanf将只返回2,day的数值不会被sscanf更改。
2.2:
double longitude, latitude;
int converted = sscanf("113.123456789 31.123456789", "%lf %lf", &longitude, &latitude);
printf("converted = %d, longitude = %.9lf, latitude = %lf/n", converted, longitude, latitude);
输出:
converted = 2, longitude = 113.123456789, latitude = 31.123457
例3:*的用法: %* d和%* s加了(*)表示跳过此数据不读入(也就是不把此数据读入参数中)
3.1:
char str[100];
sscanf("123456abcdedf", "%*[0-9]%[a-z]", str);
printf("str = %s\n", str);
//输出str = abcdef
3.2:
#include <cstdio>
int main()
{
char str[100];
sscanf("1234abcd", "%*d%s", str);
printf("%s\n",str);
return 0;
}
//输出abcd
例4:^的用法:
4.1:取到指定字符为止的字符串
#include<cstdio>
int main()
{
char str[100];
sscanf("1234+abc","%[^+]",str);
printf("%s\n",str);
return 0;
}
//输出1234
4.2:取到指定字符集为止的字符串
char str[100];
sscanf("123456abcdedf", "%[^a-z]", str);
printf("%s\n", str);
//输出123456
4.3:取仅包含指定字符集的字符串。(取仅包含数字和小写字母的字符串,是取得连续的字符串)。
#include<cstdio>
int main()
{
char str[100];
sscanf("123456abcdefBFRGTY7890","%[1-9a-z]",str);
printf("%s\n",str);
return 0;
}
//输出123456abcdef
2、sprintf函数(包含于#include <cstdio>
头文件中):
由于 sprintf 跟 printf 在用法上几乎一样,只是打印的目的地不同而已,前者打印到字符串中,后者则直接在命令行上输出。这也导致 sprintf 比 printf 有用得多。所以本文着重介绍 sprintf,有时也穿插着用用 snprintf。
函数原型:
int sprintf( char *buffer, const char *format [, argument] … );
用法详述:
1、格式化数字字符串
sprintf最常见的应用之一莫过于把整数打印到字符串中,所以,sprintf 在大多数场合可以替代itoa(把一个整数转换为字符串)。如:
1、 把整数123打印成一个字符串保存在s中。
sprintf(s, "%d", 123); // 产生"123"
2、可以指定宽度,不足的左边补空格:
sprintf(s, "%8d%8d", 123, 4567); // 产生:" 123 4567"
(当然也可以左对齐):
sprintf(s, "%-8d%8d", 123, 4567); // 产生:"123 4567"
3、也可以按照16进制打印:
sprintf(s, "%8x", 4567); // 小写16进制,宽度占8个位置,右对齐
sprintf(s, "%-8X", 4568); // 大写16进制,宽度占8个位置,左对齐
这样,一个整数的16进制字符串就很容易得到,但我们在打印16进制内容时,通常想要一种左边补0的等宽格式,那该怎么做呢?很简单,在表示宽度的数字前面加个0就可以了。
sprintf(s, "%08X", 4567); // 产生:"000011D7"
上面以 “%d” 进行的10进制打印同样也可以使用这种左边补0的方式。
sprintf 和 printf 还可以按8进制打印整数字符串,使用==“%o”==。注意8进制和16进制都不会打印出负数,都是无符号的,实际上也就是变量的内部编码的直接的16进制或8进制表示。
2、控制浮点数打印格式
浮点数的打印和格式控制是 sprintf 的又一大常用功能。
1、浮点数使用格式符“%f”控制,默认保留小数点后6位数字:
sprintf(s, "%f", 3.1415926); // 产生 "3.141593"
但有时我们希望自己控制打印的宽度和小数位数,这时就应该使用:“%m.nf”格式,其中m表示打印的宽度,n表示小数点后的位数。比如:
sprintf(s, "%10.3f", 3.1415626); // 产生:" 3.142″
sprintf(s, "%-10.3f", 3.1415626); // 产生:"3.142 "
sprintf(s, "%.3f", 3.1415626); // 不指定总宽度,产生:"3.142"
附录:本文部分转载自sscanf函数使用详解、sscanf的用法、C 字符串函数 sprintf()、snprintf() 详解,感谢作者@faihung,@yanyanwenmeng,@love、reading。
以上。