C: scanf 没有在无限循环中停止 [英] C: scanf did not stop in infinite while loop

查看:72
本文介绍了C: scanf 没有在无限循环中停止的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想实现一个简单的代码来打印输入类型不是整数时的错误信息.

I want to implement a simple code to print the error message when the type of input is not an integer.

以下是示例代码.

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"会询问数字.

In this code, if the value is not the integer, "scanf" will ask the number.

然而,当输入不是整数时,这个函数并没有中断.

However, this function did not break when the input is not the integer.

也许问题在于缓冲区上的值.fflush"将是解决方案,但我不想使用它.

Maybe the problem is the value on the buffer. "fflush" would be solution,but I don't want to use it.

推荐答案

问题是在 匹配失败 情况下,您无法清空-stdin.您正在寻找整数输入.如果用户输入除整数以外的任何内容,则会发生匹配失败.当匹配失败发生时,停止从stdin中提取字符,导致匹配失败的字符留在输入缓冲区(stdin 此处) 未读 -- 如果您在没有先清除 stdin 的情况下尝试再次阅读,则等待再次咬您...如果您在循环中输入——好吧,你知道会发生什么......

The problem is you fail to empty-stdin on the matching failure case. You are looking for integer input. If the user enters anything other than an integer, a matching failure occurs. When the matching failure occurs, character extraction from stdin stops and the characters causing the matching failure are left in the input buffer (stdin here) unread -- just waiting to bite you again if you attempt to read again without clearing stdin first... If you are taking input in a loop -- well, you know what happens...

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

(honey... I tried to read an int and it failed, and I kept trying and it kept failing - help??)

如何解决?

很简单,您必须在匹配失败后清空stdin.你做得比大多数人都好——你正在检查返回,但你有一个难题要添加——一个简单的函数来empty_stdin(),当发生匹配失败.一种非常便携且非常简单的方法是简单地提取所有字符,直到遇到换行符或 EOF,例如:

Very simply, you must empty stdin after a matching failure. You are doing much better than most -- you are checking the return, but you have one piece of the puzzle to add -- a simple function to empty_stdin() when a matching failure occurs. A very portable and very simple way is to simply extract all characters until a newline or EOF is encountered, e.g.:

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

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

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

Putting all the pieces together in your example, you could do:

#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" 中是不必要的,因为所有数字转换都会消耗前导空格)

(@David Bowling has already explained in the comments that the leading space in " %d" is unnecessary as all numeric conversions consume leading whitespace)

示例使用/输出

$ ./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窗口)

Testing manual EOF case (user presses Ctrl+d (or Ctrl+z windows)

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

检查一下,如果您还有其他问题,请告诉我.

Look things over and let me know if you have further questions.

这篇关于C: scanf 没有在无限循环中停止的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆