如何在C中使用fscanf检查匹配失败

时间:2018-08-08 15:42:26

标签: c error-handling scanf

我希望能够在不停止读取的情况下确定正在读取的文件是否包含错误的数据类型。

例如:在这里我想存储文件中的一些整数,但是如果我的文件中有一些字符,它将停止循环。我不知道如何避免这种情况以及如何返回匹配类型的错误。

int main (void) {
    FILE* input_file = fopen("toto.txt", "r");

    int a [10];

    if (input_file != NULL) {
        int i =0;
        while (fscanf(input_file, "%d", &a[i]) == 1) {
            //do something
        }
        fclose(input_file);
    }
    else {
        printf ("open failed.");
        }
    return 0;
}

2 个答案:

答案 0 :(得分:2)

如果scanf无法使用格式项转换输入,它将返回而不消耗导致错误的字符。返回值要么是成功转换的次数,要么是EOF,如果在没有成功转换的情况下遇到文件结尾(或读取错误)。

如果您的格式只有一个转换项,则只有三个可能的返回值:

EOF  End of input (or read error)
0    Invalid character
1    Succesful conversion

在第二种情况下,如果要继续解析,则需要使用错误的字符,可以使用scanf("%*c");来完成。

scanf并不是用于解析输入的非常精确的工具。例如,它不会区分

223abc

223 abc

两者都将被视为成功的%d转换,但没有成功;无法判断是否存在空格。

如果您对各种限制都满意,请继续使用它,但如果要进行实际的输入验证,最终将遇到一堵砖墙,唯一的解决方案是“使用其他工具”。 / p>

答案 1 :(得分:1)

如果要处理错误,可以查看如下结构:

    int i = 0;
    int rc;
    while ((rc = fscanf(input_file, "%d", &a[i])) != EOF)
    {
        if (rc == 1)
        {
            …success…
            i++;
        }
        else
        {
            …deal with error…
        }
    }

通常,我鼓励在循环条件下使用fscanf(…) != 1;如果有问题,它将停止循环。但是,如果要处理错误并继续循环,则此条件更合适。如何处理错误取决于您。您可以跳过并忽略(或报告)下一个空格或下一个换行符。或者,您可能会在文本中查找与数字不匹配的命令或其他信息。

您应该考虑的一种选择是使用fgets()或POSIX getline()读取一行数据,然后使用sscanf()解析该行。这种方法至少有两个主要优点:

  • 您可以报告给出错误的整个行,而不仅仅是报告fscanf()已部分消耗掉该错误时留下的残骸。
  • 您可以用多种不同的方式解析相同的数据,这可能是有利的。