如何将 scanf 的输入限制为整数和浮点数(一般为数字)

How do I limit the input of scanf to integers and floats (numbers in general)

我目前正在大学学习C编程,我得到了编写程序的任务 列出任意函数ax^2+bx+c的0 / x轴的截取点。

为了确保输入正确(int、float等)我运行下面的while循环。在此之前 a 被定义为双精度。

printf("Input for a=");

while (scanf("%lf", &a) == 0)
{
    fflush(stdin);
    scanf("%lf", &a);
    printf("Incorrect Input! New Input needed.\n"); 
    printf("a=");
}

我知道 fflush(stdin) 运算符仅在出现第二个输入函数时才清除缓冲区,因此循环内的 fflush 不会清除缓冲区,因此循环的条件是总是正确的,因此我创建了一个无限循环。

我的教授也禁止使用goto,这就是我来这里的原因,因为我想不出一个合理的方案来解决这个问题。 我也尝试过但失败了:

do
{
    printf("\nInput for a= ");
    scanf("%lf", &a);
}

while (isdigit(a));
{
    printf("Thank you.\n");
}

通过这种安排,我收到了失败通知:Expression c >= -1 && <= 255。我想这与错误的变量定义(双精度、数字)等有关。

但是我最初的问题是这个问题是否有一个优雅的解决方案或者至少有任何解决方案。

Lukas,我还没有 100% 清楚你的:

"Im am asking how to distinguish between all numbers and every other possible input for scanf."

scanf 可以根据使用的 转换说明符 提供到单个给定类型的转换,因此您不能同时读取 intfloat 具有相同的 scanf 语句和单个转换说明符。 (现在您可以阅读一行,例如 fgets 然后使用备用 sscanf 语句并检查剩余的字符来做到这一点)

也就是说,我想我明白你在问什么,并且可以回答 fflush 和阅读价值问题。

首先,在使用 scanf 时,您必须 检查 return 并处理三种情况。 (1) EOF,用户用Ctrl+d取消输入(或windows上的Ctrl+z) ; (2) 发生匹配输入失败导致return小于转换说明符的数量 使用过;最后 (3) 良好的输入案例(您可以在其中进行任何额外的检查,例如正数、小于 100 等)

虽然 fflush(stdin) 在大多数系统上是未定义的行为,但有许多实现允许它。 (主要是 windows,但 Linux 允许它用于 seekable 流,例如在 stdin 上重定向的文件)最重要的是,没有它是不可移植的注意事项,因此最好提供 getchar() 的简单等效项,例如

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

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

至于 scanf,正如我在评论中提到的那样,将 scanf 调用包含在一个无限循环中要容易得多,只有当输入满足所有约束时,您才可以中断该循环。一个需要整数输入的简单示例是:

int getint (int *value, const char *prompt)
{
    /* loop continually until good input or canceled */
    for (;;) {
        int rtn;
        fputs (prompt, stdout);     /* display prompt */
        rtn = scanf ("%d", value);

        if (rtn == EOF) {   /* user generated manual EOF */
            fputs ("<user canceled input>\n", stderr);
            return 0;
        }
        empty_stdin();  /* all other cases - empty input buffer */
        if (rtn == 1)   /* good input, break */
            break;
        /* otherwise matching failure */
        fputs ("  error: invalid integer input.\n", stderr);
    }
    return *value;  /* value also availale through pointer */
}

将它放在一个简单的例子中,你将有:

#include <stdio.h>

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

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

int getint (int *value, const char *prompt)
{
    /* loop continually until good input or canceled */
    for (;;) {
        int rtn;
        fputs (prompt, stdout);     /* display prompt */
        rtn = scanf ("%d", value);

        if (rtn == EOF) {   /* user generated manual EOF */
            fputs ("<user canceled input>\n", stderr);
            return 0;
        }
        empty_stdin();  /* all other cases - empty input buffer */
        if (rtn == 1)   /* good input, break */
            break;
        /* otherwise matching failure */
        fputs ("  error: invalid integer input.\n", stderr);
    }
    return *value;  /* value also availale through pointer */
}

int main (void) {

    int v,
        i = getint (&v, "enter integer value: ");

    if (i)
        printf ("\ninteger: %d\n", v);

    return 0;
}

例子Use/Output

现在您可以在其中尽最大努力打破您编写的任何输入例程。如果你发现问题,就去修复它,然后再尝试破解它。

上面的代码允许相当稳健地输入任何一种给定类型的值,例如

$ ./bin/scanfint
enter integer value: no
  error: invalid integer input.
enter integer value: apples, banannas, and pears
  error: invalid integer input.
enter integer value: 21

integer: 21

检查一下,如果您的问题略有不同,或者您对答案还有其他疑问,请告诉我。