我在文件中留下以下一行文字,我希望用一位数解析一位数字:
10001111001000101001010001100000101110000102
然而,当我使用格式说明符%d时,fscanf返回EOF指标而不是数字。这与我使用%s的情况形成鲜明对比,因为它会返回我期望的内容,尽管它会一次性完成所有内容并且在字符串中。
所以当我改变(以及他从int到char [250]的类型)
if (fscanf(f, "%d", &character) != EOF)
到
if (fscanf(f, "%s", &character) != EOF)
答案 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
那个。