scanf函数不会执行对第二次 [英] Scanf won't execute for second time

查看:148
本文介绍了scanf函数不会执行对第二次的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想: - 如果用户输入一个无效的值要重新读入的值。但问题是, scanf()的执行只有一次,不会执行其他任何时间和程序卡具有无限循环。

I am trying:- To re-read the value if user enters an invalid value. But the problem is scanf() executes only once and won't execute any other time and programs gets stuck with an infinite loop.

#include<stdio.h>
#include<math.h>
main()
{
    unsigned int a;
    unsigned int b = pow(2,M-1);
    unsigned int c;
    int x;

    printf("b = %i",b);

    input:
    fflush(stdin);
    fflush(stdout);
    printf("\nEnter any integer: ");
    x = scanf("%u",&a);

    printf("%u",a);
    if(x==0) 
        goto input;

    printf("\na = %i",a);

    c = a & b;

    printf("\nc = %i",c);

    if(c)
        printf("\nthe bit %i is set",M);
    else
        printf("\nthe bit %i is not set",M);
}

我以前%U 使用空间添加尝试和​​也试过 fflush(标准输入),但毫无效果。

I've tried using adding space before %u and also tried fflush(stdin) but nothing worked.

编辑:我知道这是不推荐使用goto,但我必须这样做这种方式。 (使用循环不是一个选项)。 M是我定义使用GCC命令行编译时该宏。

I know that the use of goto is not recommended but I have to do it this way. (Using loop is not an option). M is a macro which I define using the gcc command line at compile time.

推荐答案

注意: fflush(标准输入); 可不确定的行为。阅读:为什么 fflush(标准输入) 是错的?

Caution: fflush(stdin); may be undefined behavior. Read: Why fflush(stdin) is wrong?

INT fflush(FILE * ostream的); 结果
  在的ostream 指向一个输出流或更新流,其中,
  最近一次操作是没有输入, fflush 函数使任何
  该流未写入的数据被传递到主机环境
  要被写入该文件;否则,行为未定义

int fflush(FILE *ostream);
The ostream points to an output stream or an update stream in which the most recent operation was not input, the fflush function causes any unwritten data for that stream to be delivered to the host environment to be written to the file; otherwise, the behavior is Undefined.

您可以尝试一个循环,并一直读到 EOF \\ n 给出的此FAQ条目而不是 fflush(标准输入)因为我已经在我的回答以下建议。

You can try a loop and read until EOF or \n given this FAQ entry instead of fflush(stdin) as I have suggested below in my answer.

编辑:感谢@ 乔纳森·莱弗勒的:

有其中 fflush(标准输入)完全定义(如非标准扩展平台)平台。主例子是统称为Windows系统中的公知的家庭。微软的 INT fflush规范(FILE *流); 如果为您开放,投入, fflush 清除内容缓冲区

There are platforms where fflush(stdin) is fully defined (as a non-standard extension on that platform). The primary example is a well-known family of systems known collectively as Windows. Microsoft's specification of int fflush( FILE *stream ); If the stream is open for input, fflush clears the contents of the buffer.

我在你的code额外的疑问;是什么 M 中前pression unsigned int类型B = POW(2,M-1); ?它应该是一个错误,如果你不定义它。你发布完整的code?

I have additional doubt in your code; what is M in expression unsigned int b = pow(2,M-1);? It should be an error if you don't define it. Are you posting complete code?

关于你的错误检测逻辑:

如果用户输入无效重读的价值

re-read the value if user enters an invalid

没有, scanf()的不返回错误code。它返回成功转换次数。

No, scanf() does not return an error code. It returns the number of successful conversions.

INT scanf函数(为const char *格式,...);

  返回值结果
  如果成功,该函数返回成功填补参数列表中的项目数。该计数可以匹配
  项的预期数量或少(甚至为零)由于匹配
  失败,一个读错误,或者档案结尾的范围。

如果读取错误发生或到达档案结尾时
  阅读,适当的指标设置(的feof FERROR )。并且,如果任
  发生的所有数据可以被成功读取之前,返回 EOF

If a reading error happens or the end-of-file is reached while reading, the proper indicator is set (feof or ferror). And, if either happens before any data could be successfully read, EOF is returned.

如果编码错误发生跨preting宽字符时,
  函数集错误号 EILSEQ

If an encoding error happens interpreting wide characters, the function sets errno to EILSEQ.

因此​​,实际上根据错误遇到的返回值可以是零,EOF。您应该使用 INT FERROR(FILE *流); 错误号 宏错误检测(检查在链接中给出的例子)。

So actually depending on the error encountered the return value may be zero, EOF. You should use int ferror ( FILE * stream ); and errno macro for error detection (check the example given at link).

由于错误的可能的输入无效的可以是:

Errors possible because of invalid input can be:

EILSEQ :输入字节序列没有形成有效的字符结果。
   EINVAL :没有足够的论据;或格式为NULL。结果
   ERANGE :一个整数转换会超出可以存储在相应的整数类型的大小。

EILSEQ: Input byte sequence does not form a valid character.
EINVAL: Not enough arguments; or format is NULL.
ERANGE: An integer conversion would exceed the size that can be stored in the corresponding integer type.

scanf函数手动。

原因无限循环:

,系统跟踪哪些输入迄今已见过。到 scanf函数每个呼叫从那里最后一个停止匹配输入回升。这意味着,如果以previous scanf函数发生错误,它未能匹配输入仍留有未读,因为是用户输入的领先。如果不注意丢弃错误输入,并且环路被用于读取输入,程序可以被夹在一个无限循环。

The system keeps track of which input has been seen so far. Every call to scanf picks up from where the last one stopped matching input. This means that if an error occurred with the previous scanf, the input it failed to match is still left unread, as if the user typed ahead. If care isn't taken to discard error input, and a loop is used to read the input, your program can get caught in an infinite loop.

因此​​,例如,在code:

So for example in your code:

x = scanf("%u", &a);
      //   ^
      //  need a number to be input

但是,假如你不输入一个数字,但例如输入了一个无效的字符串(而不是一个数字,像你说的)。这将导致 scanf()的函数试图匹配一个无符号整数时要失败(%U) ,字剩下未读。因此,通过循环下一次,在 scanf()的不等待新的用户输入,它会尝试把名了。

But suppose you don't input a number but an invalid string is entered e.g. "name" (instead of a number, as you say). This will cause the scanf() function to be fail when attempting to match an unsigned integer ("%u"), and the word "name" is left unread. So the next time through the loop, the scanf() doesn't wait for fresh user input, it tries to convert "name" again.

同样,如果输入的是 29.67 中,%U 将只有前两个字符匹配(在 29 ),在离开 0.67 作为下次调用未读输入scanf()的

Similarly if the input were 29.67, the "%u" will match the first two characters only (the 29), leaving the .67 as unread input for the next call to scanf().

即使输入是正确的,因为 29 ,结束输入新行仍留有未读。通常情况下这不是一个问题,因为大部分转换自动跳过领先的空白,如从previous行其后的换行符。然而,一些转换(%C%[)不跳过任何前导空格,所以你必须做手工。

Even if the input is correct, as 29, the newline that ended the input is still left unread. Normally that isn't a problem since most conversions automatically skip leading white-space such as the trailing newline from the previous line. However some conversions ("%c" and "%[") don't skip any leading white-space, so you have to do it manually.

为了避免这种无限循环中的一个建议:

(记住:我推荐使用 FERROR(),误差值是preferable检测无效的输入。此外,它只是用于学习目的,如果您需要实现一个重要的应用程序,你应该使用与fgets(STR)而不是 scanf()的其次是解析 STR 输入验证输入是否有效)

(remember: as I recommended the use of ferror(), error-value is preferable to detect invalid input. Additionally, it's just for learning purpose and if you need to implement a serious application you should use fgets(str) instead of scanf() followed by that parse str input to verify whether input is valid)

input:
    //fflush(stdout); //use if needed, as \n used in printf no need of fflush-stdout
    printf("\nEnter any integer: ");
    x = scanf("%u", &a); // always wait for new symbols
    printf("%u", a);

    if(x == 0){ // x=0, if error occurred
        // read all unread chars 
        while ((ch = getchar()) != '\n' && ch != EOF);
        goto input;
    }

这只是可能会与你的code(对我的工作,你的code + GCC)工作的建议。但是,如果你错误地使用这种技术可能会留下一个bug在code:

It's just a suggestion that will possibly work with your code (worked for me, your code + gcc). But if you use this technique incorrectly it may leave a bug in your code:

我如何刷新输入缓冲区?

如果您确信不需要的数据是在输入流中,你可以使用
  以下的一些code片段的将其删除。但是,如果
  调用这些当在输入流中没有数据,程序将
  等到有,它给你意想不到的结果。

If you are sure that unwanted data is in the input stream, you can use some of the following code snippets to remove them. However, if you call these when there is no data in the input stream, the program will wait until there is, which gives you undesirable results.

这篇关于scanf函数不会执行对第二次的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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