c - 如何将 scanf 的输入限制为整数和 float (一般为数字)

标签 c scanf fflush

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

为了确保输入正确(int、float 等),我运行以下命令 while环形。在此之前a被定义为 double 。

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 。我想这与错误的变量定义( double 、数字)等有关。

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

最佳答案

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 时,您必须检查返回并处理三种情况。 (1) EOF,用户使用 Ctrl+d(或 Windows 上的 Ctrl+z)取消输入; (2) 发生匹配输入失败,导致返回的转换说明符数量少于所使用的数量;最后 (3) 良好的输入情况(您进行任何额外的检查,例如肯定、小于 100 等)

虽然 fflush(stdin) 在大多数系统上是未定义的行为,但有许多实现允许它。 (主要是 Windows,但 Linux 允许它用于可查找流,例如在 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;
}

示例使用/输出

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

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

$ ./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

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

关于c - 如何将 scanf 的输入限制为整数和 float (一般为数字),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53726736/

相关文章:

c - 如何区分初始化结构和未初始化结构?

C 奇怪的编译器行为

c - fscanf 无故停止读取文件

c - scanf() 函数中的扫描集有什么区别?

c - 即使有安全措施, scanf 也会被跳过 (getchar())

c - UTF-8 文本到剪贴板 C

c - c中的doxygen : grouping of defines

c - fgets 指令被跳过。为什么?

c - C 中的刷新缓冲区

synchronization - boost::filesystem::copy 之后需要 fflush 或同步吗?