我的PAT系列文章更新重心已移至Github,歡迎來看PAT題解的小伙伴請到Github Pages瀏覽最新內(nèi)容。此處文章目前已更新至與Github Pages同步。歡迎star我的repo。
題目
本題的基本要求非常簡單:給定 個實數(shù),計算它們的平均值。但復(fù)雜的是有些輸入數(shù)據(jù)可能是非法的。一個“合法”的輸入是 [
]
區(qū)間內(nèi)的實數(shù),并且最多精確到小數(shù)點后 2 位。當(dāng)你計算平均值的時候,不能把那些非法的數(shù)據(jù)算在內(nèi)。
輸入格式:
輸入第一行給出正整數(shù) (
)。隨后一行給出
個實數(shù),數(shù)字間以一個空格分隔。
輸出格式:
對每個非法輸入,在一行中輸出 ERROR: X is not a legal number,其中 X 是輸入。最后在一行中輸出結(jié)果:The average of K numbers is Y,其中 K 是合法輸入的個數(shù),Y 是它們的平均值,精確到小數(shù)點后 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
思路
先說說輸入: 我們不清楚題目會給出多長的非法輸入,因此為了防止溢出,我們應(yīng)該選擇一個安全的方式應(yīng)對這種情況。
我的方法是先確定合法數(shù)字的最長長度:8個字符,那么我們每次就先只讀8個字符。如果輸入流(stdin)中的下一個字符不是空白字符,那么這個數(shù)就絕對非法;如果是空白字符的話,再繼續(xù)討論接下來的問題。
(這個問題幾乎網(wǎng)上所有AC的方法都是用的一個大數(shù)組來讀取,應(yīng)該是PAT對這一點沒有嚴格檢查(要是有上千字符的輸入就不行了)。我只是出于健壯性考慮,照顧到了這一點)
(通過率0.19的題我一次AC了,先讓我激動一會兒 \(≧▽≦)/ )
代碼實現(xiàn)
- 讀取8個字符,使用了
scanf("%8s", str),就是讀到空白字符或者8個字符。 - 判斷是否是浮點,使用了函數(shù)
strtod(const char *, char **),這個函數(shù)的第二個參數(shù)是一個指針的地址,用來使該指針指向未用于轉(zhuǎn)換的第一個字符,我們可以根據(jù)這個指針是否為NULL來判斷這個字符串是否為浮點。
(e.g. 如第一個參數(shù)傳入字符串2.3.4,第二個參數(shù)這個指針會指向第二個小數(shù)點) - 精度,找到小數(shù)點(有的話)的位置,看它距字符串結(jié)尾有幾個字符就好了,不能大于3個。
P.S. 在網(wǎng)上看到了結(jié)合使用sscanf和sprintf的方法,相當(dāng)?shù)那擅?。忘記了在哪里,讀者可自行查找,或嘗試自己去實現(xiàn)。
代碼
最新代碼@github,歡迎交流
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
int count = 0, N;
double f, sum = 0;
/* Maxium scenario: -1000.00. So just need to read 8 chars(+ '\0' = 9) */
char s[9], *pEnd, *pDot, c;
scanf("%d", &N);
for(int i = 0; i < N; i++)
{
scanf("%8s", s); /* Just read up to 8 chars */
c = ungetc(getchar(), stdin); /* Read next char and push back */
f = strtod(s, &pEnd); /* pEnd -> converted floating number */
pDot = strchr(s, '.'); /* pDot -> (first) decimal point */
if(!isspace(c) /* string too long */
|| *pEnd /* not floating number */
|| (f > 1000 || f < -1000) /* out of range */
|| (pDot && pDot - s < strlen(s) - 3)) /* precision too high */
{
printf("ERROR: %s", s);
/* this can avoid overflow (we don't know how long input is) */
while(!isspace(c = getchar())) putchar(c);
printf(" is not a legal number\n");
}
else /* legel number */
{
count++;
sum += f;
}
}
if(count == 0) printf("The average of 0 numbers is Undefined\n");
if(count == 1) printf("The average of 1 number is %.2lf", sum);
if(count >= 2) printf("The average of %d numbers is %.2lf", count, sum / count);
return 0;
}