如何将 scanf 的输入限制为整数和浮点数(一般为数字) [英] How do I limit the input of scanf to integers and floats (numbers in general)

查看:81
本文介绍了如何将 scanf 的输入限制为整数和浮点数(一般为数字)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在大学学习 C 编程,我得到了编写一个程序的任务,该程序将任何函数 ax^2+bx+c 的 0/x 轴的截取点放出.

I am curently learning C Programming in University and I got the task to write a program witch puts out the interception points with 0 / x-axis of any function ax^2+bx+c.

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

In order to make sure that the input is correct (int, float, etc.) I run the following while loop. Prior to that a is definded as 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 不会清除缓冲区并且因此循环的条件始终为真,因此我创建了一个无限循环.

I am aware that the fflush(stdin) operator only clears the buffer when a second input function occurs and therefore the fflush inside the loop does not clear the buffer and therefore the condition of the loop is always true and thus I created an infinite loop.

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

My professor also forbids the use of goto, which is why I am here, because I can't come up with a reasonable solution that solves this problem. I also tried and failed with:

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

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

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

With this arrangement I get the failure notification: Expression c >= -1 && <= 255. I guess this has to do with false variable definition (double, digit) or such.

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

However my original question was whether there is an elegant solution to this problem or at least any solution.

推荐答案

Lukas,我仍然不是 100% 清楚你的:

Lukas, I'm still not 100% clear and your:

我在问如何区分所有数字和 scanf 的所有其他可能的输入."

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

scanf can provide conversion to a single given type based on the conversion specifier used, so you can't read both int and float with the same scanf statement and a single conversion specifier. (now you can read a line with, e.g. fgets and then use alternate sscanf statements and check the remaining characters to do that)

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

That said, I think I understand what you are asking and can answer both the fflush and read of a value questions.

首先,当使用 scanf 时,您必须检查返回并处理三种情况.(1) EOF,用户用Ctrl+d(或Ctrl+z在windows上)取消输入;(2) 发生匹配输入失败,导致返回的转换说明符数量少于使用的数量;最后 (3) 良好的输入案例(在那里​​你施加任何额外的检查,例如肯定的,小于 100 等.)

To begin, when using scanf you must check the return and handle three-cases. (1) EOF, the user cancels input with a Ctrl+d (or Ctrl+z on windows); (2) a matching or input failure occurs resulting in a return of less than the number of conversion specifiers used; and finally (3) the good input case (where you impose any additional checks you have, e.g. positive, less than 100, etc..)

虽然 fflush(stdin) 在大多数系统上是未定义的行为,但有许多实现允许它.(主要是 Windows,但 Linux 允许它用于 seekable 流,例如重定向到 stdin 的文件)底线,它不是没有警告的可移植的,所以最好提供一个与 getchar() 的简单等效,例如

While fflush(stdin) is undefined behavior on most systems, there are a number of implementations that allow it. (primarily windows, but Linux allows it for seekable stream, e.g. a file redirected on stdin) Bottom line, it isn't portable without caveats, so it's best to provide a simple equivalent with getchar(), e.g.

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

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

至于 scanf,正如我在评论中提到的,将 scanf 调用包含在无限循环中要容易得多,只有在输入满足所有条件时才会中断你的约束.一个需要整数输入的简单示例是:

As for scanf, as I mentioned in the comment, it is far easier to enclose the scanf call within an infinite loop which you only break when the input satisfies all your constraints. A simple example requiring integer input would be:

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 */
}

把它放在一个简单的例子中,你会:

Putting it altogether in a simple example, you would have:

#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;
}

示例使用/输出

现在您可以尽最大努力打破您编写的任何输入例程.如果您发现问题,请修复它并再次尝试打破它.

Where you can now do your best to break any input routine you write. If you find a problem, go fix it and try to break it again.

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

The code above allows for fairly robust input of any one given type of value, e.g.

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

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

Look things over and let me know if your question was slightly different, or if you have further questions about the answer.

这篇关于如何将 scanf 的输入限制为整数和浮点数(一般为数字)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆