C:scanf没有在无限while循环中停止

时间:2018-11-26 04:14:52

标签: c while-loop scanf

我想实现一个简单的代码,以在输入类型不是整数时打印错误消息。

下面是示例代码。

int num;
while (1) {
    printf("Input the value of integer: ");
    int result = scanf(" %d", &num);
    if (result == 0) {
        printf("ERROR-Not an integer.\n");
    }
    else if (num < 0) {
         printf("ERROR- Not positive.\n");    
    }else{ 
        break;   
    }
}

在此代码中,如果该值不是整数,则“ scanf”将询问该数字。

但是,当输入的数据不是整数时,此函数不会中断。

也许问题出在缓冲区的值。 “ fflush”将是解决方案,但我不想使用它。

3 个答案:

答案 0 :(得分:3)

问题是您在匹配失败情况下无法清空stdin。您正在寻找整数输入。如果用户输入的不是整数,则发生匹配失败。发生 matching failure 时,将从stdin中提取字符,并且导致导致 matching 的字符留在输入缓冲区中(此处为stdin未读-如果您尝试再次阅读而又没有再次清除stdin的情况下再次等着您……如果您循环输入,那么您知道会发生什么。 ..

(亲爱的……我试图读取int并失败了,但我一直尝试并且失败了-帮助?)

如何解决?

很简单,您必须在匹配失败后清空stdin 。您的工作比大多数人要好得多-您正在检查退货,但是您有一个难题要补充-当发生匹配失败时,empty_stdin()的功能很简单。一种非常可移植且非常简单的方法是简单地提取所有字符,直到遇到换行符或EOF,例如:

void empty_stdin(void) {
    int c = getchar();

    while (c != '\n' && c != EOF)
        c = getchar();
}

将示例中的所有内容放在一起,您可以:

#include <stdio.h>

void empty_stdin(void) {
    int c = getchar();

    while (c != '\n' && c != EOF)
        c = getchar();
}

int main (void) {
    int num;
    while (1) {
        printf("Input the value of integer: ");

        int result = scanf(" %d", &num);

        if (result == EOF) {    /* handle ctrl+d (ctrl+z on win) */
            printf (" user canceled input (manual EOF)\n");
            break;
        }
        else if (result == 0) { /* matching failure */
            printf("ERROR-Not an integer.\n");
            empty_stdin();      /* remove offending characters */
        }
        else if (num < 0) {
            printf ("ERROR- Not positive.\n");    
        }
        else        /* positive number enetered */
            break;
    }

    return 0;
}

({@David Bowling在评论中已经说明,space中前导" %d"是不必要的,因为所有数字转换都消耗前导空白)

使用/输出示例

$ ./bin/scanf_empty
Input the value of integer: foo
ERROR-Not an integer.
Input the value of integer: -1
ERROR- Not positive.
Input the value of integer: bar
ERROR-Not an integer.
Input the value of integer: 1

测试手册EOF的情况(用户按下 Ctrl + d (或 Ctrl + z 窗口)

$ ./bin/scanf_empty
Input the value of integer:  user canceled input (manual EOF)

仔细检查一下,如果还有其他问题,请告诉我。

答案 1 :(得分:1)

#include <stdio.h>

int main()
{
    int num;
    int result;

    while (printf("Please input an unsigned integer: "),
           (result = scanf(" %d", &num)) != 1 || num < 0 )
    {                                 //  ║          ╚══ was successful but negative
        if (result != 1) //  <════════════╝ 1 conversion was requested
             fputs("ERROR: Not an integer.\n", stderr);  // write error messages
        else fputs("ERROR: Not positive.\n", stderr);   // to stderr

        int ch;  // the following loop *) reads garbage that might be left in stdin
        while ((ch = getchar()) != '\n' && ch != EOF);  // so the next scanf() won't
    }                                                   // fail because of it.
    printf("You entered: %d\n", num);
}

*)计划B:

scanf("%*[^\n]");  // this scanset matches all characters except newline
getchar();        // remove the newline

*)计划C:

scanf("%*[^\n]");  // this scanset matches all characters except newline
scanf("%*c");     // remove the newline

示例对话框:

Please input an unsigned integer: foo
ERROR: Not an integer.
Please input an unsigned integer: bar
ERROR: Not an integer.
Please input an unsigned integer: -75
ERROR: Not positive.
Please input an unsigned integer: 42
You entered: 42

答案 2 :(得分:-1)

您需要在每次scanf之前/之后清除stdin。我个人以前更喜欢。

  

fseek(stdin,0,SEEK_END);

int num;
while (1) {
    fseek(stdin, 0, SEEK_END);
    printf("Input the value of integer: ");
    int result = scanf_s(" %d", &num);
    if (result == 0) {
        printf("ERROR-Not an integer.\n");
    }
    else if (num < 0) {
        printf("ERROR- Not positive.\n");
    }
    else {
        break;
    }
}