【问题标题】:Infinite loop with scanf in while loop在while循环中使用scanf进行无限循环
【发布时间】:2018-04-05 02:51:32
【问题描述】:

我是 C 的初学者,我试图在数字中设置一个范围,但是当输入超出范围的字母时会出现无限循环(例如:p)。 如果我输入超出范围的数字,它会起作用。 我读到了,我认为这是缓冲区和函数 scanf 的问题,当我按“Enter”时,我包含了 \n。所以我试图通过用字符扫描来清洁,但没有奏效。 我还尝试在 %x 之前放置一个空格 (' '),但没有成功。 我输入无效字母后,scanf被忽略了;如果我输入了一个无效的数字,程序就会工作。

#include <stdio.h>

int main()
{
    int validity, pos; //validity 0:not valid, repeat the loop; validity 1: valid number
    char enter;

    while (validity == 0) {
        printf("Player1 1, type the position in hexadecimal (1 to f):\n");
        scanf(" %x%c", &pos, &enter); //here, the number pos is already in decimal

        if (pos == NULL){
            pos = 99; //if the letter typed is improper, I set 99, because is out of range
        }

        if(pos<=15 && pos >=0){
            validity = 1;
        } else {
            printf("Invalid number, out of range\n");
            validity = 0;
        }
    }
}

【问题讨论】:

  • 在使用pos之前检查scanf(" %x%c", &amp;pos, &amp;enter)的返回值。至少是 1 个吗?
  • “我试图用一个字符扫描来清理,但是没有用”——代码不这样做。如果"%x" 成功,scanf() 只会移动到"%c"

标签: c


【解决方案1】:

循环中的第一次,validity 根本没有定义值。

可能是1,可能是0,可能是65,532

你应该给它一个初始值。

int validity = 0, pos; //validity 0:not valid, repeat the loop; validity 1: valid number

您将pos 声明为int;它永远不会是NULL。它将具有整数值。

这行没有意义:

if (pos == NULL){

你也应该初始化那个变量。

int validity = 0, pos = 99; //validity 0:not valid, repeat the loop; validity 1: valid number

【讨论】:

  • NULL 只是一个零宏。当它被预处理时,该行将显示为if (pos == 0) { 编辑:虽然我同意它不应该这样写,只是指出它在技术上是有效的
  • 你把新手弄糊涂了。 NULL 不仅是零的宏,它还具有 void* 类型,除非在特殊情况下,否则不应将 void*int 进行比较。
  • 你是对的,我很抱歉。我保证我的意图是教学而不是迂腐
【解决方案2】:

C 没有原始数据类型的默认值。因此在行中

int validity, pos;

您可能应该将validity 设置为某个默认值,例如 0,这样无论输入是什么(有效或无效),循环都至少运行一次。或者在这种情况下使用do while 循环似乎是一个更合乎逻辑的决定。

do
{
 //Your code
} while(validity == 0);

在这种情况下,您不必担心将默认值设置为 validity

正如@abelenky 之前指出的那样,在pos 中检查NULL 在技术上也是一个坏主意。你也可以跳过这部分

if (pos == NULL)
{ 
  pos = 99;
}

由于pos 被声明为int,如果pos 的值不在0 到15 之间,那么这部分代码会自动将其声明为无效。

if(pos<=15 && pos >=0)
{ 
  validity = 1;
} 
else 
{ 
  printf("Invalid number, out of range\n");
  validity = 0;
}

因此没有必要再做一个块来检查它的有效性。

【讨论】:

    【解决方案3】:

    死循环的原因是,如果你输入一个字母,后面的“\n”会作为下一个循环中scanf(...)函数的输入。所以你可以简单地添加“getchar()”来修复它。注意忽略数字后的“\n”。

    不同的是,当你输入一个超出范围的数字时,它可以用十六进制解析,你可以打印出来查看。但是字母不能(必须在 a-f 之间)。

    你可以参考这个:

    #include <stdio.h>
    int main(int argc, char *argv[])
    {
    
       int validity=0, pos=99;
       while (validity == 0){
           printf("Player1 1, type the position in hexadecimal (1 to f):\n");      
           scanf("%x", &pos); 
    
           if(pos<=15 && pos >=0){
              validity = 1;
           }else {
              printf("Invalid number, out of range\n");
              getchar();
           }
       }
    }
    

    祝你好运。

    【讨论】:

      猜你喜欢
      • 2016-06-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-06-25
      • 2022-01-22
      • 2012-04-09
      • 2014-11-13
      • 2014-03-29
      相关资源
      最近更新 更多