题目描述
知识点
字符串处理题
实现
码前思考
我的思想 很暴力 ,就是每次读一个字符串,然后遍历这个字符串来判断是否合法。
- 从非负号开始读起;
- 记录小数点出现的次数,一旦出现两个小数点,返回
false
; - 记录小数点前面的值和小数点后面的值的大小;
- 检查当前字符是不是数字和小数点,不是则返回
false
; - 小数点前后相加,如果超过范围,返回
false
,否则返回true
。
代码实现
#include "bits/stdc++.h"
using namespace std;
const int maxn = 101;
int n;
int k;
double res;
char num[maxn];
bool judge(char num[]){
//从字符的第一个符号开始判断
//记录小数点的数量
int cnt = 0;
int decimal = 0;
int len = strlen(num);
double res = 0;
double before = 0;
double after = 0;
int start = 0;
//首先判断第一个数字是否是负号
if(num[0] == '-'){
start = 1;
}
for(int i=start;i<len;i++){
if(num[i]<'0'||num[i]>'9'){//如果当前位不是数字
//看是否是小数点
if(num[i] == '.'){
cnt++;
if(cnt > 1){//如果有多个小数点了,返回false
return false;
}
}else{
return false;
}
}else{//如果当前位是数字
if(cnt!=1){ //小数点之前的数
before = before*10 + (num[i]-'0');
}else{//小数点之后的数
decimal++;
if(decimal > 2){//超过两位
return false;
}
after = after + ((num[i]-'0')*pow(10,-decimal));
}
}
}
//得到最后的结果
res = before + after;
if(res>1000.00){
return false;
}else{
return true;
}
}
int main(){
scanf("%d",&n);
k = 0;
res = 0;
for(int i=0;i<n;i++){
//读入数据
scanf("%s",num);
//然后判断输入是否合法
bool isLegal = judge(num);
if(isLegal){
double val;
sscanf(num,"%lf",&val);
res += val;
k++;
}else{
printf("ERROR: %s is not a legal number\n",num);
}
}
if(k == 0){
printf("The average of 0 numbers is Undefined\n");
}else if(k == 1){
printf("The average of 1 number is %.2f\n",res);
}else{
double avg = res/k;
printf("The average of %d numbers is %.2f\n",k,avg);
}
return 0;
}
码后反思
-
毫无疑问,上面的代码又臭又长,一道20分的题目,不应该需要这么长的时间的,我用了50min才写完,我实在是太菜了!
-
我的暴力解法里面想到了使用
sprint
和sscanf
,但是没有真正的用好它们,我看了柳婼的代码才恍然大悟,原来还可以这样用!下面是修改后的代码,简单了不止一点点:#include "bits/stdc++.h" using namespace std; int main(){ int n; scanf("%d",&n); char a[50],b[50]; double tmp; double sum = 0; double avg = 0; int cnt = 0; for(int i=0;i<n;i++){ bool flag = true; scanf("%s",a); sscanf(a,"%lf",&tmp); sprintf(b,"%.2f",tmp); for(int j=0;j<strlen(a);j++){ //之所以使用a的长度是为了保证5与5.00是相等的 if(a[j] != b[j]){ flag = false; } } if(flag == false || (tmp<-1000) || (tmp>1000)){ printf("ERROR: %s is not a legal number\n",a); }else{ sum += tmp; cnt++; } } if(cnt == 0){ printf("The average of 0 numbers is Undefined\n"); }else if(cnt == 1){ printf("The average of 1 number is %.2f\n",sum); }else if(cnt > 1){ avg = sum/cnt; printf("The average of %d numbers is %.2f\n",cnt,avg); } return 0; }
- 之所以使用a的长度是为了保证5与5.00是相等的;
- 要在自己的心中过一遍下面这些情况,不要看代码简单,但是其中的情况还是复杂的:
- 如果
a
是以字符开头,程序能正常执行吗? - 如果
a
是两位以上精度,程序能正常执行吗? - 如果
a
是整数,程序能正常执行吗?
- 如果
-
需要认真的阅读题目,比如输出里面的
number
,有些是numbers
,有些是number
; -
另外我有一些关于输入的小疑惑,通过下面的实例来解决:
int main(){ char str1[100] = "aa12aa"; //注意 char str2[100]; int a; sscanf(str1,"%d",&a); sprintf(str2,"%d",a); printf("%d\n",a); printf("%s\n",str1); printf("%s\n",str2); return 0; }
输出结果是什么呢?如下:
int main(){ char str1[100] = "12aaaa"; //注意 char str2[100]; int a; sscanf(str1,"%d",&a); sprintf(str2,"%d",a); printf("%d\n",a); printf("%s\n",str1); printf("%s\n",str2); return 0; }
输出结果是什么呢?
int main(){ char str1[100] = " 12aaaa"; //注意 char str2[100]; int a; sscanf(str1,"%d",&a); sprintf(str2,"%d",a); printf("%d\n",a); printf("%s\n",str1); printf("%s\n",str2); return 0; }
输出结果是什么呢?
int main(){ char str1[100] = " 12.1aaaa"; //注意 char str2[100]; double a; sscanf(str1,"%lf",&a); sprintf(str2,"%.2f",a); printf("%lf\n",a); printf("%s\n",str1); printf("%s\n",str2); return 0; }
得到什么结果呢?
综上,我们发现从字符串输入数字时,会忽略前面所有的空格和换行。