如何使用C代码拒绝非数字输入?

时间:2015-12-07 19:01:25

标签: c cs50

我使用cs50.io(c)制作了一个代码。唯一的问题是每当我在终端中检查50时,我收到一条错误消息,指出拒绝非数字输入+预期输入......这是我的代码,下面是终端中的错误。任何帮助都将很高兴。

#include <stdio.h>

int main() {
    float celsius, fahrenheit;

    printf("\nEnter temp in Celsius : ");
    scanf("%f", &celsius);

    fahrenheit = (1.8 * celsius) + 32;
    printf("F: %.1f\n", fahrenheit);

    return (0);     
}

https://sandbox.cs50.net/checks/ef786d6473b2409381a7161c725f8776

3 个答案:

答案 0 :(得分:3)

您可以查看scanf()的返回值Read the manual scanf(3)

float value;
if (scanf("%f", &value) != 1)
    fprintf(stderr, "non numeric input rejected.\n");
else
    fprintf(stderr, "good the input is a number `%f'.\n", value);

缺点是,scanf()通常很难处理后续输入,因为它会忽略空格字符,您需要从stdin手动删除它们。

我喜欢的方式是,

char buffer[100];
float value;
char *endptr;
if (fgets(buffer, sizeof(buffer), stdin) == NULL)
    return -1; // Something went wrong (Ctrl+Z/Ctrl+D -> EOF) perhaps
// Check if non numeric characters are present.
value = strtod(buffer, &endptr);
if (((isspace(*endptr) != 0) && (*endptr != '\0')) || (buffer == endptr))
    fprintf(stderr, "non numeric input rejected.\n"); // ^ no conversion happened
else
    fprintf(stderr, "good the input is a number `%f'.\n", value);

但是,这并不完美,因为"123.456 example"将被视为数值。严格处理是可能的,但需要更多的工作。但我认为你明白了这些例子。

答案 1 :(得分:2)

简单地检查scanf("%f",...);的返回值的问题是,您不会捕获跟随其他有效字符的无效字符。此解决方案比其他解决方案更简单,并且在数字输入之前,中间或之后捕获无效字符:

已编辑:按@ WeatherVane's - comment

char baddet; // a dummy var used merely for detecting bad scanf() conversions

.
.
.

if (scanf("%f%c", &celcius, &baddet) != 2 || baddet != '\n')
{
   printf("Invalid numeric conversion (non-numeric characters in the input).\n");
   exit(1);
}

如果任何非数字字符跟随有效的数字字符,则baddet中会捕获第一个此类字符。在您的情况下, 应该 捕获换行符;在其他情况下(例如处理命令行参数),您可能希望没有空格跟随数字字符;在这种情况下,scanf()的返回值应为1,而baddet中的值实际上并不重要(尽管将其地址传递给scanf()仍然很重要,以防万一是否有任何非数字字符跟随其他数字输入字符。)

答案 2 :(得分:0)

编辑:在您发布的代码中,没有检查scanf是否真的有效。当我输入foo代码时,代码仍然没有从文本转换为float celsius。但是celsius从未初始化,因此行为未定义。在我的情况下,代码打印32.0,因为celsius 刚刚发生,其值为0.0

您应该检查scanf是否按预期执行,在您的示例中,它应该返回值1。您还可以通过扫描以下字符来检查终止将文本转换为float的字符是否是您所期望的字符,如下所示。

#include <stdio.h>

int main(void) {
    float celsius, fahrenheit;
    char nextch;

    printf("\nEnter temp in Celsius : ");
    if (scanf("%f%c", &celsius, &nextch) != 2 || nextch != '\n') {
        printf("Bad entry\n");
    }
    else
    {
        fahrenheit = 1.8 * celsius + 32;
        printf("F: %.1f\n", fahrenheit);
    }
    return 0;     
}

函数scanf现在有2个格式说明符,因此其返回值应为2,并且后面的字符将被检查为newline