检查输入开头的空格字符

问题描述 投票:0回答:1

我需要使用 scanf() 结果验证输入是否存在任何无效字符,包括空白字符。

我写了这个函数:

bool is_input_valid(double* inp_ptr) {
bool isInputValid = false;
char newline = 0;
int result = scanf("%lf%c", inp_ptr, &newline);
rewind(stdin);
if (result == 2 && newline == '\n') {
   isInputValid = true; 
}
else {
   printf("Error! Invalid input format!\n");
   rewind(stdin);
}
return isInputValid;
}

问题是它不适用于输入开头的空格(因此当我输入 [134] 时,它被视为有效输入)。我该如何修改我的函数来处理这种情况?

c validation scanf
1个回答
0
投票

与许多

scanf
说明符一样,
%lf
会消耗并丢弃所有前导空白字符,这使得检测起来很麻烦。一般来说,使用
scanf
会让你的输入流处于糟糕的状态。

旁白:远离 scanf() 的初学者指南

一般建议是,您最好使用

fgets
将整行输入读取到缓冲区中,并使用
strtod
解析该值,这样可以提供更多控制并提供更强大的错误处理。

strtod
does 允许可选的前导空格(按
isspace
分类),因此需要明确检查。

一个相当完整的例子:

#include <ctype.h>
#include <errno.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>

bool is_input_valid(double *inp_ptr) {
    char buffer[4096];

    /* EOF / input error, or leading white space */
    if (!fgets(buffer, sizeof buffer, stdin) || isspace((unsigned char) *buffer))
        return false;

    char *endp;
    errno = 0;
    double value = strtod(buffer, &endp);

    if (inp_ptr)
        *inp_ptr = value;

    /* value did not go out of range,
     * something was parsed, and
     * parsing was terminated by LF or null-byte
     */
    return ERANGE != errno && buffer != endp && ('\n' == *endp || !*endp);
}

int main(void)
{
    while (1) {
        double value;

        printf(":: ");

        if (is_input_valid(&value))
            printf("-> %lf\n", value);
        else {
            if (ferror(stdin) || feof(stdin))
                break;

            puts("-> invalid input");
        }
    }
}
:: abc
-> invalid input
:: 123.456abc
-> invalid input
::     123.456
-> invalid input
:: 123.456
-> 123.456000
:: 0x123
-> 291.000000
:: 

不过,我倾向于将 I/O 和验证分开。

© www.soinside.com 2019 - 2024. All rights reserved.