[英]C fscanf reports EOF if parsed for a digit but not for a string
我希望将一位数字逐位解析的文件中保留以下文本行:
10001111001000101001010001100000101110000102
但是,当我使用格式说明符%d时,fscanf返回EOF指示符而不是数字。 这与我使用%s的情况形成对比,尽管它一次完成所有操作并以字符串形式返回期望值。
因此,当我更改(以及他从int到char [250]的类型)时,
if (fscanf(f, "%d", &character) != EOF)
至
if (fscanf(f, "%s", &character) != EOF)
如果要逐位扫描,则需要使用"%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,除非其中一个是正确的。
scanf
系列函数中的"%d"
格式说明符将使该函数查找数字序列,该序列以遇到的第一个非数字字符终止。 在您的情况下,使用"%d"
将立即消耗所有数字。
如果"%d"
没有这样做,那么您将只能用它读取一位数字,这几乎不是任何格式化输入。
"%s"
格式说明符使字符序列被占用,该字符序列将以空格字符或文件结尾终止。
您在这里寻找的是逐字符读取输入的内容。 您可以使用"%c"
格式说明符来实现。 之后,您可以将获得的字符解释为数字值。
例如; 您可以读取第一个'1'
字符,然后从中减去'0'
字符,这将产生'1' - '0' == 1
,这就是您想要的东西。
fscanf
返回失败时分配的输入项目数或EOF
。 那只是一个问题。 另一个是它将继续使用输入字符串中的字符,直到遇到\\0
字符或非数字(在%d
情况下)为止。 传递单个字符的地址也不是一件有效的事情。 您可以改为执行以下操作:
char *p;
for (p=&input_string[0]; isdigit(*p); p++) {
int digit = (int)(*p - '0');
/* process digit */
}
如果要使用scanf
函数之一,请创建一个包含两个字符的字符串-正在处理的数字和\\0
。 然后sscanf
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.