2014-10-11 40 views
0

我正在研究這個示例練習,並且所有事情都按照我的意願工作,但有一種行爲我不明白。scanf驗證位於並等待另一個輸入。爲什麼?

當提供輸入:如果我連續無效輸入一切似乎很好。但如果我在第一個問題的情況下輸入了一個不同於1,2,3的數字,或者在第二個問題的情況下輸入了一個1,2,那麼程序就會坐在那裏直到給出新的輸入。如果另一個無效條目被創建,它將返回錯誤「無效條目」消息,並且如果輸入了一個合適的數字,那麼一切都會順利進行。

我不明白爲什麼它停下來等待第二個輸入...任何人?

謝謝你們。

#include <stdio.h> 

static int getInt(const char *prompt) 
{ 
    int value; 
    printf("%s",prompt); 
    while (scanf("%d", &value) !=1) 
    { 
     printf("Your entry is invalid.\nGive it another try: %s", prompt); 
     getchar(); 
     scanf("%d", &value); 
    } 
    return value; 
} 

int main() { 

int wood_type, table_size, table_price; 

printf("Please enter "); 
wood_type = getInt("1 for Pine, 2 for Oak, and 3 for Mahogany: "); 

printf("Please enter "); 
table_size = getInt("1 for large, 2 for small: "); 

printf("\n"); 

switch (wood_type) { 
    case 1: 
     table_price = (table_size == 1)? 135:100; 
     printf("The cost of for your new table is: $%i", table_price); 
     break; 

    case 2: 
     table_price = (table_size == 1)? 260:225; 
     printf("The cost of for your new table is: $%i", table_price); 
     break; 

    case 3: 
     table_price = (table_size == 1)? 345:310; 
     printf("The cost of for your new table is: $%i", table_price); 
     break; 

    default: 
     table_price = 0; 
     printf("The cost of for your new table is: $%i", table_price); 
     break; 

} 
} 
+0

兄弟,我無法將你的代碼運行良好,理解您的問題在我的機器..如果我在第一排第二個它打印提供1或2或3,然後1或2一些現金..如果輸入1行不是1 2 3打印0和最後如果在第一行我的輸入是1 2 3和第二行它不是1或2然後也打印一些金額。我錯過了什麼。我讀了你的代碼並在我的機器上試過。我想我不明白你的問題 – Asis 2014-10-11 15:18:01

+0

對於第一個輸入,嘗試輸入一個字母,然後輸入數字5。輸入5後,它會讓我掛在那裏,直到我輸入另一個字母,或1,2或3。 – 2014-10-11 15:22:18

+0

哦!是啊掛我...大聲笑 – Asis 2014-10-11 15:24:19

回答

2

您很可能需要刷新輸入緩衝區(尤其是在函數中調用多個scanf)。在scanf之後,換行符'\n'保留在輸入緩衝區中。 fflush確實不是這樣做,所以你需要手動做。一個簡單的do...while循環工作。試試看:

編輯:

static int getInt(const char *prompt) 
{ 
    int value; 
    int c; 

    while (printf (prompt) && scanf("%d", &value) != 1) 
    { 
     do { c = getchar(); } while (c != '\n' && c != EOF);    // flush input 
     printf ("Invalid Entry, Try Again..."); 
    } 

    return value; 
} 

如果輸入什麼你得到的空行是scanf正常行爲。它正在等待輸入(一些輸入)。如果您希望例程在按下[Enter]鍵的情況下立即再次提示,則需要使用另一個例程來讀取stdin,如(getlinefgets)。 getline是首選,因爲它返回讀取的字符數(您可以測試)。然後可以使用atoi(在<stdlib.h>中)將字符串值轉換爲整數。這將爲您提供所需的靈活性。

例如:

int newgetInt (char *prompt) 
{ 
    char *line = NULL;  /* pointer to use with getline()  */ 
    ssize_t read = 0;  /* number of characters read   */ 
    size_t n = 0;   /* numer of chars to read, 0 no limit */ 
    static int num = 0;  /* number result      */ 

    while (printf ("\n %s ", prompt) && (read = getline (&line, &n, stdin)) != -1) 
    { 
     if ((num = atoi (line))) 
      break; 
     else 
      printf ("Invalid Input, Try Again...\n"); 
    } 

    return num; 
} 
+0

:(我試過,但事實上變得更糟......現在,當我輸入一個不是1,2,3的數字時,它實際上需要兩個無效條目才能返回錯誤消息... 我認爲這就是我在循環中爲getchar()所做的事情(擺脫「\ n」留下的痕跡) – 2014-10-11 15:10:48

+0

我看到這個問題 - 堅持一秒鐘,我會有一個答案:) – 2014-10-11 15:11:27

+0

非常感謝!非常感謝!把printf作爲while語句的一部分而不是在循環代碼中的區別是什麼?Xcode引發了一個警告,提示可能不會在那裏初始化值...什麼是這樣的嗎? – 2014-10-11 15:40:37

0

如果輸入一些無效的輸入,它停留在輸入緩衝區。 無效輸入必須在scanf函數完成之前提取。

更好的方法是獲得整行輸入然後在該行上工作。

首先,把該輸入線成使用fgets()臨時數組, 然後使用sscanf()(安全比scanf,因爲它針對守衛溢出)。

#include <stdio.h> 

int main(int argc, const char * argv[]) { 

    char tempbuff[50]; 
    int result, d , value; 

    do 
    { 
     printf("Give me a number: "); 
     fgets(tempbuff, sizeof(tempbuff), stdin); //gets string, puts it into tempbuff via stdin 

     result = sscanf(tempbuff, "%d", &value);  //result of taking buffer scanning it into value 

     if (result < 1){        //scanf can return 0, # of matched conversions, 
                //(1 in this case), or EOF. 
      printf("You didn't type a number!\n"); 
     } 
    }while (result < 1); 

    //some code 

    return 0; 
} 

知識來自:http://www.giannistsakiris.com/2008/02/07/scanf-and-why-you-should-avoid-using-it/

相關問題