使用Scanf查找整数

5

我感觉我在这里漏掉了一些非常明显的东西,但我似乎找不到我的代码问题所在。我正在尝试使用scanf来查找输入是否为整数,如果是,则查找八进制。如果它不是整数,则仅提示用户再次输入。然而,出于某种原因,我只能在相反的情况下使代码工作,即不接受整数,而接受其他任何内容。看起来应该很容易解决,但否则我就会得到无限循环。如果您能提供任何帮助,我们将不胜感激。

#include <stdio.h>
enum state {success,fail,quit};
int status = fail;

int main(void)
{
int n;
char t;
do
{
printf("Enter a number between 0 and 32767: ");

if(scanf("%d%c", &n, &t) != 2 )
status = success;
}
while (status == fail);
if (status == success)
{

int oct1, oct2, oct3, oct4, oct5;

oct1 = ((((n / 8) / 8) / 8) / 8) % 8;
oct2 = (((n / 8) / 8) / 8) % 8;
oct3 = ((n / 8) / 8) % 8;
oct4 = (n / 8) % 8;
oct5 = n % 8;

printf("In octal, your number is: %d%d%d%d%d\n", oct1, oct2, oct3, oct4, oct5);
return 0;
}
}

1
为什么不使用 printf("八进制表示:%o\n", n); - Some programmer dude
顺便说一句:if是不必要的。您可以在其为false时循环,离开循环后(即意味着为true),您会询问“是true吗?” - dhein
从“关于您的错误检测逻辑”中阅读答案:Scanf不会第二次执行 - Grijesh Chauhan
5个回答

1
如果您输入了非数字值,则会出现问题,因为它不会从输入缓冲区中删除,并且在尝试扫描数字时将永远保留在那里。
相反,应该分别读取行,然后尝试从该行获取数字。类似于这样的代码:
for (;;)
{
    printf("Enter a number: ");

    /* Get a line of input from the user */
    char line[128];
    if (fgets(line, sizeof(line), stdin) == NULL)
    {
        /* Error reading */
        perror("fgets");
        break;
    }

    /* The `fgets` function leaves the newline in the string */
    /* Remove it by overwriting it with the string terminator */
    line[strlen(line) - 1] = '\0';

    /* Convert to a number */
    char *endptr = NULL;
    n = strtol(line, &endptr, 10);

    /* Check if a valid number was entered */
    if (endptr == line)
        printf("Not a valid number, please enter again\n");
    else if (endptr < (line + strlen(line)))
        printf("Line begins with a number, but then there is garbage\n");
    else
        break;  /* We got a valid number */
}

如果您不关心可能存在的垃圾数据,可以使用sscanf来简化代码:
for (;;)
{
    printf("Enter a number: ");

    /* Get a line of input from the user */
    char line[128];
    if (fgets(line, sizeof(line), stdin) == NULL)
    {
        /* Error reading */
        perror("fgets");
        break;
    }

    /* Try to get number as an unsigned short */
    if (sscanf(line, " %hu", &n) == 1)
        break;

    printf("Illegal number\n");
}

1
重构了你的代码。
#include <stdio.h>

    int main(void)
    {
    int n;
    char t;
    do
    {
    printf("Enter a number between 0 and 32767: ");
    scanf("%d", &n);
    }
    while( (n < 0) || (n > 32767)) ; //check the range of the input.if not there in this range then re read input.
    printf("In octal, your number is: %o \n", n); //print octal of input with %o format specifier.
    return 0;
    }

0

如果scanf遇到错误,这意味着即使您再次调用scanf,解析错误仍然存在,即它会再次解析旧的用户输入而不采用新的用户输入。

据我所知,不可能使用scanf来查找解析整数时的错误。请使用其他适当的函数,如scanf(“%s”)/ fgets(),然后是strtol。

while (1)
{
    char input[128], *endptr;
    int value;
    scanf("%s", input);
    value = strtol(input, &endptr, 10);
    if (endptr != input)
    {
        break;
    }
    printf("input again\n");
}

0

你所需要的就是这个:

do
{
   printf("Enter a number between 0 and 32767: ");

   if(scanf("%d", &n) == 1 && ((n > 0) && (n < 32767)) )
     status = success;
   else
     while((t=getchar()) !='\n' && t !=EOF) ; //Eat the trailing newline
}while (status == fail);

请查看这里


0

你的代码中只有两个小错误。

首先,

if(scanf("%d%c", &n, &t) != 2 )
  status = success;

应该是

if(scanf("%d%c", &n, &t) == 2 )
  status = success;

这就是为什么它接受非整数的原因。另一件事是,如果出现错误,您必须清空 stdin,以便 scanf 读取新的内容:

if(scanf("%d%c", &n, &t) == 2 )
  status = success;
else
  fflush(stdin);

把这段代码放进你的程序里,它就能工作了。 < p > < em > 编辑: 就像Grijesh指出的那样,不应该使用< code > fflush(stdin) < /code >,所以你需要对重复的< code > scanf 做一些更智能的处理。其他人已经给出了一些可能性,但我保留了这个答案,因为它指出了你最初的逻辑错误。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接