2014-10-11 71 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/

相关问题