C fscanf报告EOF,如果解析数字而不是字符串

时间:2014-04-18 23:55:53

标签: c formatting printf scanf

我在文件中留下以下一行文字,我希望用一位数解析一位数字:

10001111001000101001010001100000101110000102

然而,当我使用格式说明符%d时,fscanf返回EOF指标而不是数字。这与我使用%s的情况形成鲜明对比,因为它会返回我期望的内容,尽管它会一次性完成所有内容并且在字符串中。

所以当我改变(以及他从int到char [250]的类型)

if (fscanf(f, "%d", &character) != EOF)

if (fscanf(f, "%s", &character) != EOF)

3 个答案:

答案 0 :(得分:4)

如果您想逐位扫描,则需要使用"%1d"作为格式。

否则,它将整行(除了换行符)作为数字读取,并在将大十进制数转换为32位int时调用未定义的行为。请注意,d的助记符不是'数字'而是'十进制',而不是八进制的'o',十六进制的'x'和十进制的十进制,十进制或十六进制的整数的'i'普通前缀(八进制为0,十六进制为0x,否则为十进制。

为什么它返回EOF仍然不完全清楚,但是对于未定义的行为,任何响应都是有效的。

标准(ISO / IEC 9898:2011第7.21.6.2节 fscanf()功能,第10段)说(在相关部分中):

  

如果此对象没有合适的类型,或者无法在对象中表示转换结果,则行为未定义。

在错误条件下有很多关于行为的措辞,但这是关键的一个。由于行为未定义,因此获得EOF是一种有效且相对良性的响应。调查文件流是否处于feof(f)ferror(f)返回true的状态会很有趣。没有明显的原因,除非你通常不会从fscanf()获得EOF,除非一个或另一个是真的。

答案 1 :(得分:1)

"%d"族函数内的

scanf格式说明符将使函数查找数字序列,该数字序列以第一个非数字字符遭遇结束。在您的情况下,使用"%d"会立即消耗所有数字。

如果"%d"没有这样做,那么您只能用它读取一位数字,这几乎不是任何格式化输入。

"%s" format-specifier导致字符序列被消耗,即以空白字符或文件结尾终止。

您在这里寻找的是逐个字符地阅读输入。您可以使用"%c" format-specifier执行此操作。之后,您可以将获得的字符解释为其数字值。

例如;你可以阅读第一个'1'字符,然后从中减去一个'0'字符,这会产生'1' - '0' == 1,这就是你想要的东西。

答案 2 :(得分:0)

fscanf返回分配的输入项目数,如果失败则返回EOF。这只是一个问题。另一个是它将继续消耗输入字符串中的字符,直到遇到\0字符或非数字(在%d情况下)。传递单个字符的地址也不是一个有效的方法。您可以执行以下操作:

char *p;
for (p=&input_string[0]; isdigit(*p); p++) {
    int digit = (int)(*p - '0');
    /* process digit */
}

如果要使用其中一个scanf函数,请创建一个包含两个字符的字符串 - 正在处理的数字和\0。然后sscanf那个。