PAT Basic 1054. 求平均值 (20)(C語言實(shí)現(xiàn))

我的PAT系列文章更新重心已移至Github,歡迎來看PAT題解的小伙伴請(qǐng)到Github Pages瀏覽最新內(nèi)容。此處文章目前已更新至與Github Pages同步。歡迎star我的repo。

題目

本題的基本要求非常簡(jiǎn)單:給定 N 個(gè)實(shí)數(shù),計(jì)算它們的平均值。但復(fù)雜的是有些輸入數(shù)據(jù)可能是非法的。一個(gè)“合法”的輸入是 [ -1000, 1000 ]
區(qū)間內(nèi)的實(shí)數(shù),并且最多精確到小數(shù)點(diǎn)后 2 位。當(dāng)你計(jì)算平均值的時(shí)候,不能把那些非法的數(shù)據(jù)算在內(nèi)。

輸入格式:

輸入第一行給出正整數(shù) N\le 100 )。隨后一行給出 N 個(gè)實(shí)數(shù),數(shù)字間以一個(gè)空格分隔。

輸出格式:

對(duì)每個(gè)非法輸入,在一行中輸出 ERROR: X is not a legal number,其中 X 是輸入。最后在一行中輸出結(jié)果:The average of K numbers is Y,其中 K 是合法輸入的個(gè)數(shù),Y 是它們的平均值,精確到小數(shù)點(diǎn)后 2
位。如果平均值無法計(jì)算,則用 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

思路

先說說輸入: 我們不清楚題目會(huì)給出多長(zhǎng)的非法輸入,因此為了防止溢出,我們應(yīng)該選擇一個(gè)安全的方式應(yīng)對(duì)這種情況。
我的方法是先確定合法數(shù)字的最長(zhǎng)長(zhǎng)度:8個(gè)字符,那么我們每次就先只讀8個(gè)字符。如果輸入流(stdin)中的下一個(gè)字符不是空白字符,那么這個(gè)數(shù)就絕對(duì)非法;如果是空白字符的話,再繼續(xù)討論接下來的問題。
(這個(gè)問題幾乎網(wǎng)上所有AC的方法都是用的一個(gè)大數(shù)組來讀取,應(yīng)該是PAT對(duì)這一點(diǎn)沒有嚴(yán)格檢查(要是有上千字符的輸入就不行了)。我只是出于健壯性考慮,照顧到了這一點(diǎn))

(通過率0.19的題我一次AC了,先讓我激動(dòng)一會(huì)兒 \(≧▽≦)/

代碼實(shí)現(xiàn)

  • 讀取8個(gè)字符,使用了scanf("%8s", str),就是讀到空白字符或者8個(gè)字符。
  • 判斷是否是浮點(diǎn),使用了函數(shù)strtod(const char *, char **),這個(gè)函數(shù)的第二個(gè)參數(shù)是一個(gè)指針的地址,用來使該指針指向未用于轉(zhuǎn)換的第一個(gè)字符,我們可以根據(jù)這個(gè)指針是否為NULL來判斷這個(gè)字符串是否為浮點(diǎn)。
    (e.g. 如第一個(gè)參數(shù)傳入字符串2.3.4,第二個(gè)參數(shù)這個(gè)指針會(huì)指向第二個(gè)小數(shù)點(diǎn))
  • 精度,找到小數(shù)點(diǎn)(有的話)的位置,看它距字符串結(jié)尾有幾個(gè)字符就好了,不能大于3個(gè)。

P.S. 在網(wǎng)上看到了結(jié)合使用sscanf和sprintf的方法,相當(dāng)?shù)那擅?。忘記了在哪里,讀者可自行查找,或嘗試自己去實(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;
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容