2016-11-16 65 views
4

所以在代碼中,我正在讀來自用戶的選項,然後再決定是否執行規定動作以下位:如何停止輸入字符卡在緩衝區中? ç

printf("Do you want to execute %s: ", exe); 

char input = getchar(); 

if (input == 'y') { 
    return execute(exe); 
} return 0; 

我遇到的問題是該行char input = getchar()一個字符後(我假設輸入密鑰或換行符)卡在stdin中,並且從我的​​函數調用fgets()(從stdin讀取)將消耗此卡住的字符,並且不會提示用戶輸入所需的內容。

現在我可以定義下面的函數來「吃」的任何雜散字符我,如果調用​​之前調用...

void iflush() { 
    int c; 

    while ((c = getchar()) != EOF && c != '\n') { 
     continue; 
    } 
} 

...這解決了這個問題。但我仍然想知道爲什麼這首先發生?是否有更合適的方式從得到沒有造成這種流浪的性格,然後弄亂我的其他方法?我對C很陌生,很想確定我正在學習良好的習慣。

看起來很奇怪,我不得不添加一個輔助方法,即使很簡單,以防止我的程序中的錯誤只是記錄一些用戶輸入。我試過使用fgetc()也是同樣的問題。

+0

你試過'fflush(stdin);'在你調用'getchar()'的語句之後? – VHS

+0

是啊,沒有做任何事情 – transiti0nary

+5

@VHS你知道這是一個非常糟糕的建議嗎? 'fflush(stdin);'調用未定義的行爲。 –

回答

3

我還想知道爲什麼這是發生在第一個地方?

這是因爲當你可以用字符%c(或fgetc()),它沒有忽視AY的空白字符的輸入流。 某些格式說明符(例如%d)會忽略輸入流中留下的任何空格。所以,這不是問題。但%c不會忽略它。因此,你通常使用那些「吃」功能。

想象一下,如果你正在掃描一個空白字符(如空間,換行符等),你怎麼能夠使用scanf()來掃描它? 顯然,有不同的和更好的方式,如使用fgets()

我對C很陌生,很想確定自己正在學習良好的習慣。

我的建議是完全避免scanf()。請使用fgets()來讀取一行,然後使用sscanf()解析該行。請閱讀:Why does everyone say not to use scanf? What should I use instead?

有一件事要注意有關fgets()是,如果你輸入緩衝區有足夠的空間,那麼它會讀取換行符爲好, 你想避免在大多數用戶輸入。所以,你需要檢查最後一個字符是否是換行符,然後刪除它。

可以使用strcspn()功能,如實現這一目標:

char line[256]; 
if (fgets(line, sizeof line, stdin) == NULL) { 
    /* handle failure */ 
} 
line[strcspn(line, "\n")] = 0; /* remove the newline char if present */ 

如果你的主要興趣是讀書只是一個字符,那麼陣列3個字符就足夠了。仍然使用更大的緩衝區不會傷害:

char line[256]; 
char ch; 
if (fgets(line, sizeof line, stdin) == NULL) { 
    /* handle failure */ 
} 
if (sscanf(line, "%c", &ch) != 1) { 
    /* handle failure */   
} 
/* Now you can use 'ch' to check if it's 'y' */ 
+0

非常好,除了「只讀一個字符,然後數組2個字符就足夠了」。通常閱讀一個'char',人們不會計算'\ n'。可能需要至少3個字符,換行符和空字符。建議緩衝區大小兩倍,你認爲最大值應該是。 256是很好的用戶輸入。 – chux

+0

如果緩衝區中沒有空間,'fgets()'只會存儲'\ n'。所以,2就足夠了:1個字符和零字節。所以當讀取一個字符(即使是換行符)時,2個字節的緩衝區大小已經足夠了。 – usr

+0

沒錯,然而'\ n''仍然在'stdin'中用於下一個輸入操作 - 如果一個用戶在'「y \ n」'下只讀取「一個」字符,OP似乎想避免這種情況。如果代碼需要一次讀取一個字符,包括'\ n'',只需使用'fgetc()' - 這會處理讀取空字符,這對'fgets()'有問題。 – chux