2010-09-18 28 views
2

我是相當新的C很抱歉,如果這是一個愚蠢的問題,但是當我運行下面的代碼:gets()接受輸入而實際上沒有給它任何輸入?

#include <stdio.h> 

int main() { 
    int i; 
    int test[10]; 
    char string[81]; 

    for(i = 0; i < 10; i++){ 
     scanf("%d", &test[i]); 
    } 

    for(i=0; i < 7; i++){ 
     gets(string); 
     printf("String was entered\n"); 
    } 

} 

並輸入任何10位,行「字符串輸入了」將即使打印我沒有在命令窗口中輸入字符串。誰能解釋爲什麼?有沒有辦法阻止它發生?

謝謝!

+1

使用'gets'幾乎自動有未定義的行爲的任何程序。 .. – 2010-09-18 01:30:11

+0

即使沒有閱讀比標題更進一步,我知道你正在使用(濫用)scanf – pmg 2010-09-18 09:20:20

+0

@pmg你能詳細說明嗎?爲什麼這是濫用scanf? – Sam 2010-09-19 00:03:20

回答

4

在使用scanf讀取數據後,換行符仍然位於輸入隊列中等待讀取。 gets讀取換行,並停止

請注意,這是一個壞主意使用gets(因爲它達到了該行的結束!):它提供了沒有辦法把多少字符獲取讀入緩衝區的限制,所以如果你輸入的字符多於緩衝區中的字符數,你最終會溢出緩衝區,導致數據損壞,應用程序崩潰,巨大的安全漏洞和/或任何其他不可預知的結果。對於一個安全的選擇,你可以使用fgets,而不是與stdin

fgets(string, sizeof(string), stdin); 

(請注意,你可能想使用某種類型的符號常量的string的大小,這樣你就不再重複了在多個地方 - 或者當數組定義可見時使用sizeof(string)

+0

感謝您的回答!有什麼方法可以清除輸入隊列,以便獲取(或fgets?)沒有任何可讀的內容? – Sam 2010-09-18 01:25:11

+0

@Sam:不,如果你想清除它可能意味着你做錯了什麼。 – 2010-09-18 01:31:25

+1

@Sam:隔行掃描調用'fgets'和'scanf'會很痛苦。 :-)處理它的一個方法就是使用其中一個(如果你使用'fgets',你可以使用'sscanf'解析每條線,按照RBerteig的建議。 – 2010-09-18 01:32:42

3

猜測,scanf()未消耗必須鍵入的換行符,以便它可以處理要在字符串之前獲得的十個整數。因此,在scanf()的最後一次調用之後,gets()正面臨一個以換行符開頭的輸入緩衝區。 Presto,它已經達到了它的規格,因此它不會將任何內容複製到緩衝區並返回。

一般而言,scanf()gets()是新代碼的不好選擇。他們都有問題,使他們痛苦地使用權利,甚至使用危險。

具體來說,gets()沒有也不能檢查它的輸出緩衝區大小,所以它很容易覆蓋緩衝區後發生的任何內存。這種方式存在全球化狀態或堆棧腐敗。如果它是堆棧,那麼可以利用它來獲得程序的控制權並使其執行任意代碼。這不是一件好事。

消耗輸入流fgets()(其緩衝區大小有限制),並使用sscanf()和其他函數一次讀取就可以解析它。

0

下面的代碼應工作

#include <stdio.h> 
int main() { 
int i; 
    int test[10]; 
char string[81],s[1]; 
for(i = 0; i < 10; i++){ 
    scanf("%d", &test[i]); 
} 

gets(s); 

for(i=0; i < 7; i++){ 
    gets(string); 
    printf("String was entered\n"); 
} 

} 

char數組S [1]被用來捕捉換行符向左的scanf unproessed