2012-12-04 69 views
5

新的這裏,我有一個非常簡單的問題。我在C中做了一個簡單的程序,它要求用戶輸入一個字符選擇。他們輸入結果後,程序返回到菜單。然而,它似乎需要某種類型的幽靈輸入,就好像該字符有一些未知的值。我需要將char設置回其默認狀態。C - 用戶單個字符輸入呈現奇怪的結果

代碼:

/* display menu for user */ 
void menu() { 

    printf("\n- - - Phone Book Database - - -\n"); 
    printf("\nSelect an action:\n\n"); 
    printf("\tc:\tCreate a database entry.\n"); 
    printf("\ts:\tSearch the database entries.\n"); 
    printf("\td:\tDelete a database entry.\n"); 
    printf("\tq:\tQuit program.\n\n"); 

    printf("Enter choice: "); 
    menu_choice = getchar(); 

    if(menu_choice != 'c' && menu_choice != 's' 
     && menu_choice != 'd' && menu_choice != 'q') { 
      printf("\n\n\tInvalid choice.\n"); 
      menu(); 
    } 
    //fflush(stdin); 
} 

下面是一個例子輸出:

- - - Phone Book Database - - - 

Select an action: 

    c: Create a database entry. 
    s: Search the database entries. 
    d: Delete a database entry. 
    q: Quit program. 

Enter choice: c 

Enter name: test 

Enter address: test 

Enter number: 3 

- - - Phone Book Database - - - 

Select an action: 

    c: Create a database entry. 
    s: Search the database entries. 
    d: Delete a database entry. 
    q: Quit program. 

Enter choice: 
    Invalid choice. 

- - - Phone Book Database - - - 

Select an action: 

    c: Create a database entry. 
    s: Search the database entries. 
    d: Delete a database entry. 
    q: Quit program. 

Enter choice: q 

輸入C作爲輸入調用下面的函數

/* creates a new record in array */ 
void create_record() { 
    char name[MAX]; 
    char address[MAX]; 
    int number; 

    rec_num++; /* add 1 to marker for record placement */ 

    printf("\nEnter name: "); 
    scanf("%s", name); 

    printf("\nEnter address: "); 
    scanf("%s", address); 

    printf("\nEnter number: "); 
    scanf("%d", &number); 

    strcpy(record[rec_num].name, name); 
    strcpy(record[rec_num].address, address); 
    record[rec_num].number = number; 
} 
+0

當'c'被選擇時你會做什麼? – Xymostech

+0

@Xymostech當選擇c時,它會調用另一個函數來創建數據庫條目。我爲每個字段使用一個結構數組。這很好,但當回到menu()函數時,它將某些東西當作答案並呈現「無效的選擇」。如你看到的。 –

+0

它看起來像其他功能沒有正確輸入輸入,所以有多餘的輸入留在緩衝區中,當你回到菜單時,已經選擇了一些東西。我們可以看到你所說的功能的代碼嗎? – Xymostech

回答

4

看起來你已經有了你的答案,並且正在評論,這是正確的;使用getchar()將宣讀stdin

printf("Enter choice: "); 
menu_choice = getchar(); 

一個字符當我到了這個提示在控制檯,然後輸入c<enter key>它引起兩個char的去stdin'c''\n'

首次getchar();運行時,它拿起'c'離開換行符。在第二次迭代時,拾取'\n'而不等待用戶的任何內容;因此似乎好像有「鬼魂輸入」。

我只想指出,無論何時您從用戶那裏獲得輸入,並且結果都不符合您的預期,只需將其轉回以驗證發生了什麼就可以了,如下所示:

if(menu_choice != 'c' && menu_choice != 's' 
    && menu_choice != 'd' && menu_choice != 'q') { 
     printf("\n\n\tYou entered %c (%d).\n", menu_choice, menu_choice); 
     printf("\tThat's an invalid choice.\n"); 
     menu(); 
} 

會顯示您:

You entered 
(10). 
That's an invalid choice. 

事實上,它是在一個不同的線之間,以及檢查針對ASCII表小數結果你會看到10 是換行符,這可能有助於引導你o結果。

編輯:用於消費換行符

1選項 -

printf("what character?"); 
c = getchar(); // Get the character from stdin 
getchar();  // consume the newline character that was left 

第二個選項:

printf("what character?"); 
scanf("%c ", &c); // Get the character from stdin, note the space after the %c 
        // that will allow any special characters including \t and \n 

如果你只是想獲得的字符,然後在&最終消費'\n',你必須添加和轉義換行符:

printf("what character?"); 
scanf("%c\\n", &c); 
+0

非常有幫助。它並沒有解決我的問題,但它確實讓我對這個工作有了進一步的理解。謝謝! –

+1

@JamesManes - 是的,我沒有真正提到*如何修復它,發生了什麼......回想起來,我爲您的興趣添加了一些「快速」修復(請參閱編輯到我的文章)。第二個選擇是更好的,因爲它允許更多的靈活性 – Mike

+0

我看着它,並開始使用getchar()選項。使用的scanf(「%C」 &c");失敗。按下回車鍵進行選擇,將只是讓終端新行後,我可以繼續打,但被輸出新線,沒有輸入一遍又一遍。 –

-1

雜散字符,幾乎肯定「\ n'在輸入命令後留在輸入緩衝區中。

要刪除它,你可以添加:

fflush(stdin) 

...您的通話getchar()之前。

+0

我試過了,它不起作用。無論如何,我聽說在這種情況下使用fflush(stdin)是非常不恰當的。 –

+1

@JamesManes C99 7.21.5.2p2,除了輸出流,更新流或NULL以外的任何其他操作都是未定義的行爲,而不僅僅是「不適當」。 [不要這樣做](http://stackoverflow.com/questions/2979209/using-fflushstdin)。 – WhozCraig

+0

@WhozCraig不知道這是未定義的行爲。我會記住這一點。你會驚訝有多少人在其他網站上向我推薦它! –

0

返回字符'\ n'可能被保留在stdin中,以便下次您繞過它時getchar()正在讀取此內容。

嘗試使用調試器查看getchar()獲取的值,或者只是將其打印出來。

這可能是getchar()不是您的應用程序的絕佳選擇,並且scanf()會做得更好,這樣所有stdin都會被提取出來,並且在您下次出現時它應該是空的。很明顯,您需要爲scanf提供不止一個字符才能寫入,就像在其他代碼中一樣。

然後您可以簡單地查看數組中的第一個字符以獲取您的字符。

2

正如其他人指出的那樣,這是換行符。只需添加另一個

(void) getchar(); /* read and discard newline */ 

只要你只想讀一個字符。

+0

非常感謝你。我在每個函數的最後添加了這個函數,它完全解決了我的問題。這可能不是最好的方式,但它有效。我會尋找另一種解決方案,但在此期間使用它。 –