scanf验证位于并等待另一个输入。为什么?

时间:2014-10-11 14:40:34

标签: c

我正在进行这个示例练习,一切都按照我的意愿运作,但有一种我不理解的行为。

提供输入时:如果我连续输入无效条目,一切似乎都很好。但是,如果我在第一个问题的情况下输入不同于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;

}
}

2 个答案:

答案 0 :(得分:2)

您很可能需要刷新输入缓冲区(特别是在函数中有多个scanf调用)。在scanf之后,换行符'\n'仍然在输入缓冲区中。 fflush NOT 执行此操作,因此您需要手动执行此操作。一个简单的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;
}

答案 1 :(得分: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/