2009-07-25 95 views
1

我有一段代碼提出了一個有趣的問題(在我看來)。scanf()導致奇怪的結果

/*power.c raises numbers to integer powers*/ 
#include <stdio.h> 

double power(double n, int p); 

int main(void) 
{ 
    double x, xpow; /*x is the orginal number and xpow is the result*/ 
    int exp;/*exp is the exponent that x is being raised to */ 

    printf("Enter a number and the positive integer power to which\n the first number will be raised.\n enter q to quit\n"); 

    while(scanf("%lf %d", &x, &exp) ==2) 
    { 
     xpow = power(x, exp); 
     printf("%.3g to the power %d is %.5g\n", x, exp, xpow); 
     printf("enter the next pair of numbers or q to quit.\n"); 
    } 

    printf("Hope you enjoyed your power trip -- bye!\n"); 
    return 0; 
} 

double power(double n, int p) 
{ 
    double pow = 1; 
    int i; 

    for(i = 1; i <= p; i++) 
    { 
     pow *= n; 
    } 
    return pow; 
} 

如果你會發現號的順序輸入的是浮點數,然後十進制數(基本號碼,然後指數)。但是當我用整數基和浮點指數輸入輸入時,它會產生一個奇怪的結果。

[[email protected] ~/code/powerCode]$ ./power 
Enter a number and the positive integer power to which 
the first number will be raised. 
enter q to quit 
1 2.3 
1 to the power 2 is 1 
enter the next pair of numbers or q to quit. 
2 3.4 
0.3 to the power 2 is 0.09 
enter the next pair of numbers or q to quit. 

這似乎推浮點指數的第二號返回到下一個輸入。我希望有人能夠解釋幕後發生的事情。我知道這是scanf()沒有檢查它的數組邊界的工作,但如果有人能給我更深的理解,我會非常感激。 感謝堆棧溢出。 -M.I.

編輯。 只是想感謝大家的意見。任何其他答案都更受歡迎。 再次感謝,S.O.

回答

2

當讀取第一個「2.3」scanf讀入「。」意識到它不再是一個有效的整數並停止。因此,「.3」保留在緩衝區中,然後鍵入「2 3.4」,因此「.3 \ n2 3.4」在緩衝區中。當scanf解析它得到「.3」和「2」就像你的例子所示。

+0

好的,我明白了,謝謝。 – mikeyickey 2009-07-27 14:00:14

7

這是因爲當您使用scanf讀取「2.3」時,掃描正在停止,但不會消耗「。」。在「.3」中。因此,當你下一次調用scanf時,它首先讀入「.3」。

詳細說明,scanf調用不限於一行文本。 scanf()跳過空白,包括製表符,空格和換行符。

2

在C中,scanf()對於來自人類用戶的真實世界輸入基本上沒有用處 - 它用於從數據文件中讀取固定格式的文本。如果您使用的是C++,那麼您應該使用iostream輸入,無論是哪種情況,您都應該根據您的特定輸入要求編寫自己的解析例程。

5

其他人已經回答了您的具體問題,但我想提供一條建議。 從不使用scanf()fscanf()。永遠。認真。

[f]scanf()操作期間的失敗常常使您的文件指針位於不確定的位置。由於大多數用戶的輸入通常基於行(GUI中除外),所以在我看來,使用fgets()sscanf()的選項總是更好。

它具有將輸入指針留在已知點(下一行的開始)的優點,允許您以多種不同方式操作剛纔讀入的行,而不僅僅是由scanf()家庭。

換句話說,如果sscanf()失敗,您仍然可以將該行用於其他目的(用不同的格式字符串重新掃描,甚至只是輸出錯誤),而不必經過stdio體操返回到在文件中開始行(用文件強制,從終端上用stdin不可能)。

+0

scanf/fscanf肯定可用於讀取文件,您可以檢測解析錯誤和中止。例如,如果我是一個必須讀取整數文件的C程序員,我可能會使用它們。 – 2009-07-25 14:04:00

0

我會讀取行並使用sscanf來解析每一行。我同意其他人的觀點,但比sscanf有更好的方法。