Home PAT 1108 Finding Average
Post
Cancel

PAT 1108 Finding Average

Link

题目很简单, 但是可以学到几个知识点: stox (其中x=i,d,ld,...) 的用法, 以及 sscanfsprintf 的用法.

stod

stof: string to float

stoi: string to int

stol: string to long

stoll: string to long long

stoul: string to unsigned long

stoull: string to unsigned long long

stod: string to double

stold: string to long double

fixed, setprecision, setw

C++ 格式化输出定点小数的方法 (不用 printf):

首先 #include <iomanip>.

fixed 是指 “write floating-point values in fixed-point notation”, 用定点表示法表示浮点数.

代码中只要出现了 fixed, 则后面都是以 fixed 输出.

1
2
3
4
5
6
7
//类型一: 整数位很多
double x=12345678;
//类型二: 小数位很多,有效小数位少
double y=0.00001234;

cout<<x<<endl;
cout<<y<<endl;

输出结果是:

1
2
1.23457e+07
1.234e-05

但是用了 fixed 之后 (默认的浮点数计数法保留有效位至多6位, 且有效位包括小数点前的位数):

1
2
cout<<fixed<<x<<endl;
cout<<fixed<<y<<endl;

输出结果是:

1
2
12345678.000000
0.000012

fixedsetprecision(n) 连用可以控制小数点后的位数.

如果没有 fixed 、只有 setprecision(n) 的话, 就是浮点数记数法了, 那么 setprecision(n) 控制的就是有效数字的位数 (包括小数点前的). 而使用 fixed 时, 就是控制小数点后的位数.

1
cout<<fixed<<setprecision(6)<<x<<endl;

setw(n) 控制后面输出的长度, 默认右对齐, 输出内容长度不够就用空格补齐, 输出内容长度超过则正常输出.

setw(n) 只对后面紧跟的输出数据起作用 (Sets the number of characters to be used as the field width for the next insertion operation).

可以使用 setiosflags(ios::left) 设置为左对齐输出;

默认使用空格补齐, 也可以通过 setfill(char x) 指定用字符 x 填充.

1
2
3
4
5
6
7
8
9
10
11
cout << setw(10) << setiosflags(ios::left) <<setfill('*') << 10 << endl;
cout << setw(10) << setiosflags(ios::right) <<setfill('*') << 10 << endl;
cout << setw(10) << setfill('*') << 10 << endl;

//或者直接 set field 更加简洁
int a = 10;
int b = 20;
cout.setf(ios::right, ios::adjustfield); //set field
cout.fill('0');
cout << setw(5) << a <<endl;
cout << setw(5) << b << endl;

手动分析字符串版:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <string>
#include <string.h>
#include <vector>
#include <cmath>
#include <cctype>
using namespace std;
int n,k;
double ans=0.0;
string s;
int main() {
    cin>>n;
    for(int i=1;i<=n;++i){
        cin>>s;
        if(s.size()>8||(s.size()==8&&s[0]!='-')){
            cout<<"ERROR: "<<s<<" is not a legal number"<<endl;
            continue;
        }
        bool flag=true;
        int pos=-1,start=s[0]=='-'?1:0;
        for(int i=start;i<s.size();++i)
            if(!isdigit(s[i])){
                if(s[i]=='.'){
                    if(pos!=-1){
                        flag=false;
                        break;
                    }
                    pos=i;
                }else{
                    flag=false;
                    break;
                }
            }
        if(!flag||(pos!=-1&&s.size()-1-pos>2)||(s[0]=='-'&&s.size()==1)){
            cout<<"ERROR: "<<s<<" is not a legal number"<<endl;
            continue;
        }
        double decimal=stod(s);
        if(decimal<-1000||decimal>1000){
            cout<<"ERROR: "<<s<<" is not a legal number"<<endl;
            continue;
        }
        k++;
        ans+=decimal;
    }
    if(!k) printf("The average of 0 numbers is Undefined\n");
    else if(k==1) printf("The average of %d number is %.2lf\n",k,ans);
    else printf("The average of %d numbers is %.2lf\n",k,ans/k);
    return 0;
}

sscanf, sprintf

sscanfsprinf 都在 <stdio.h> 中.

int sscanf(const char *str, const char *format, ...) 从字符串读取格式化输入.

  • str – C 字符串, 是函数检索数据的源.
  • format – C 字符串, 包含了以下各项中的一个或多个: 空格字符、非空格字符和 format 说明符. format 说明符形式为 [=%[*][width][modifiers]type=].

int sprintf(char *str, const char *format, ...) 发送格式化输出到 str 所指向的字符串.

1
2
3
4
char str[80];

sprintf(str, "PI = %f", M_PI); //#include <math.h>
puts(str);
1
2
3
4
5
int day, year;
char weekday[20], month[20], dtm[100];
strcpy( dtm, "Saturday March 25 1989" );
sscanf( dtm, "%s %s %d %d", weekday, month, &day, &year );
printf("%s %d, %d = %s\n", month, day, year, weekday ); //March 25, 1989 = Saturday

巧用 sscanfsprintf 版:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <iostream>
#include <cstdio>
#include <string.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);
        sprintf(b, "%.2f",temp);
        int flag = 0;
        for(int j = 0; j < strlen(a); j++)
            if(a[j] != b[j]) flag = 1;
        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;
}

PS: 关于 C++ 格式化控制的更详细讲解可以参考我的另一篇文章 C++ 格式控制.

This post is licensed under CC BY 4.0 by the author.