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

时间:2018-12-11 14:55:03

标签: c scanf fflush

我目前在大学里正在学习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不会清除缓冲区,因此循环的条件始终为true,因此我创建了一个无限循环。

我的教授也禁止使用goto,这就是为什么我在这里,因为我无法提出解决该问题的合理方法。 我也尝试过并失败了:

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

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

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

无论如何,我最初的问题是,有一个优雅的解决方案,或者最好是任何解决方案。谢谢你。

1 个答案:

答案 0 :(得分:3)

卢卡斯,我还不是100%清楚,而您:

  

“我正在问如何区分所有数字和scanf的所有其他可能输入。”

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

也就是说,我想我理解您的要求,并且可以回答fflush和阅读值问题。

首先,在使用scanf时,您必须检查退货并处理三种情况。 (1)EOF,用户使用 Ctrl + d (或Windows上的 Ctrl + z )取消输入; (2)发生 matching input 失败,导致返回的收益少于所使用的转化说明符的数量;最后是(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;
}

使用/输出示例

现在您可以在哪里尽力破坏您编写的任何输入例程。如果发现问题,请修复并尝试再次解决。

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

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

仔细研究一下,让我知道您的问题是否稍有不同,或者您对答案还有其他疑问。