2010-10-19 18 views
5

我正試圖編寫一個簡單的程序,要求用戶從循環中的菜單中進行選擇。 我使用getchar()來獲取輸入,但是我注意到,當我輸入一個字符並按下'Enter'時,程序會產生兩個循環(就像我按兩次)一個字符作爲輸入,另一個輸入'Enter '作爲輸入。在c上使用getchar()在輸入後得到'Enter'

我該如何解決這個問題?

Thanx。

回答

0

如何

#include <stdio.h> 

/*! getline() reads one line from standard input and copies it to line array 
* (but no more than max chars). 
* It does not place the terminating \n in line array. 
* Returns line length, or 0 for empty line, or EOF for end-of-file. 
*/ 
int getline(char line[], int max) 
{ 
    int nch = 0; 
    int c; 
    max = max - 1;   /* leave room for '\0' */ 

    while ((c = getchar()) != EOF) { 
    if (c == '\n') 
     break; 

    if (nch < max) { 
     line[nch] = c; 
     nch = nch + 1; 
    } 
    } 

    if (c == EOF && nch == 0) 
    return EOF; 

    line[nch] = '\0'; 
    return nch; 
} 

Source

+0

我不能使用字符串或字符數組(它是一門課程的作品) – SnapDragon 2010-10-20 18:06:31

3

您需要閱讀有關規範與非規範輸入。下面的堆棧溢出的問題解決了這個:

canonical-vs-non-canonical-terminal-input

+0

+1 - 您可以通過使用[tcsetattr()](http:// www)來將終端設置爲原始(非規範)模式。 opengroup.org/onlinepubs/000095399/functions/tcsetattr.html)來操作** termios **結構。 – jschmier 2010-10-19 15:23:23

2

添加getchar()getchar()後:P

+0

我想這會工作,但它的安靜麻醉。 – SnapDragon 2010-10-20 18:02:50

+0

在某些情況下,用戶會發現自己不得不按兩次返回,這會產生問題。 – Kaitain 2017-05-05 00:00:51

2

最簡單的方法是從getchar

char c = (char)getchar(); 
if (c != '\n') { 
    ... 
} 
濾除進入鍵,返回值
+0

我想你的意思是getchar()?如果這樣getchar()返回int。 – Nyan 2010-10-19 15:41:25

+0

@Nyan,'getchar''確實返回'int',但通過轉換分配給'char'是合法的。參考http://www.cplusplus.com/reference/clibrary/cstdio/getchar/ – JaredPar 2010-10-19 15:51:45

+1

@Jared:是的,但char限於(最終)256個值,並且您需要(最終)257個值來識別** ALL * *字符**和** EOF。這就是爲什麼'getchar()'返回一個int – pmg 2010-10-19 15:54:08

2

getchar()返回輸入緩衝區中的第一個字符,並將其從輸入緩衝區中刪除。但其他字符仍在輸入緩衝區中(在您的示例中爲\n)。你需要再次調用getchar()之前清除輸入緩衝區:

void clearInputBuffer() // works only if the input buffer is not empty 
{ 
    do 
    { 
     c = getchar(); 
    } while (c != '\n' && c != EOF); 
} 
1

你樣的回答了你自己的問題;你必須以某種方式處理換行符。

有幾種選擇。如果你的菜單選項編號爲,您可以使用scanf()在一個整數值讀取和交換基礎上認爲:

printf("Pick an option: "); 
fflush(stdout); 
scanf("%d", &option); 
switch(option) 
{ 
    case 0 : do_something(); break; 
    case 1 : do_something_else(); break; 
    ... 
    default: bad_option(); break; 
} 

這個方案的優點是%d轉換符跳過任何前導空格,包括換行符,所以你不必擔心任何未讀的\n堵塞輸入流(實際上,大多數轉換說明符跳過前導空格; %c沒有,使其表現很像getchar())。

此選項的缺點是,如果有人在其輸入中輸入一個非數字字符,它將不會被%d轉換說明符讀取,並會一直停留在輸入流中,直到調用getchar()scanf()%s%c轉換說明符。

更好的選擇是將所有輸入作爲字符字符串讀取,使用fgets(),然後根據需要進行解析和驗證。

/** 
* Prints a prompt to stdout and reads an input response, writing 
* the input value to option. 
* 
* @param prompt [in] - prompt written to stdout 
* @param option [out] - option entered by user 
* 
* @return - 1 on success, 0 on failure. If return value is 0, then option 
* is not changed. 
*/ 
int getOption(const char *prompt, char *option) 
{ 
    char input[3]; // option char + newline + 0 terminator 
    int result = 0; 

    printf("%s: ", prompt); 
    fflush(stdout); 

    if (fgets(input, sizeof input, stdin)) 
    { 
    /** 
    * Search for a newline character in the input buffer; if it's not 
    * present, then the user entered more characters than the input buffer 
    * can store. Reject the input, and continue to read from stdin until 
    * we see a newline character; that way we don't leave junk in the 
    * input stream to mess up a future read. 
    */ 
    char *newline = strchr(input, '\n'); 
    if (!newline) 
    { 
     printf("Input string is too long and will be rejected\n"); 
     /** 
     * Continue reading from stdin until we find the newline 
     * character 
     */ 
     while (!newline && fgets(input, sizeof input, stdin)) 
     newline = strchr(input, '\n'); 
    } 
    else 
    { 
     *option = input[0]; 
     result = 1; 
    } 
    } 
    else 
    printf("Received error or EOF on read\n"); 

    return result; 
} 

是的,這是一個愚蠢的菜單選項閱讀很多工作,這就是簡單的版本。歡迎來到C中交互輸入處理的美妙世界。

相關問題