C语言-unix环境下的fscanf和sprint命令
我正在尝试读取 30 行 5 列且分隔符为“制表符”的文件。每次我只得到部分行。 在windows环境下运行良好。知道为什么它在 UNIX 中不起作用吗?
while (fscanf(FFMapFile, "%s\t%s\t%s\t%s\t%s\t", fnfMap[i].COS_ID, fnfMap[i].FF_First_Act, fnfMap[i].FF_Next_Act, nfMap[i].Free_FF_allowed, fnfMap[i].FF_Change_Charge) != EOF)
{
sprintf(s,"%s\t%s\t%s\t%s\t%s\t", nfMap[i].COS_ID, fnfMap[i].FF_First_Act, fnfMap[i].FF_Next_Act, fnfMap[i].Free_FF_allowed, fnfMap[i].FF_Change_Charge);
error_log(s,ERROR);
i++; }
I am trying to read file with 30 rows and 5 columns with separator of "tab". Each time I get only part of the rows.
In the windows environment it's working good. Any idea why in unix it is not working?
while (fscanf(FFMapFile, "%s\t%s\t%s\t%s\t%s\t", fnfMap[i].COS_ID, fnfMap[i].FF_First_Act, fnfMap[i].FF_Next_Act, nfMap[i].Free_FF_allowed, fnfMap[i].FF_Change_Charge) != EOF)
{
sprintf(s,"%s\t%s\t%s\t%s\t%s\t", nfMap[i].COS_ID, fnfMap[i].FF_First_Act, fnfMap[i].FF_Next_Act, fnfMap[i].Free_FF_allowed, fnfMap[i].FF_Change_Charge);
error_log(s,ERROR);
i++; }
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
fscanf() 字符串中的 \t 字符不是必需的 - 制表符是空格,因此您也可以说“%s%s%s%s” - 可以想象,两个 scanf 实现对它们的处理方式不同。另外,您应该检查 fscanf 返回的值不是 EOF 但不等于预期的转换次数,这表明存在某种转换错误。
The \t characters in your fscanf() string are not necessary - tabs are whitespaces, so you may just as well say "%s%s%s%s" - conceivably, the two scanf implementations are treating them differently. Also, you should be checking for fscanf returning a value other than EOF but not equal to the number of expected conversions, which would indicate a conversion error of some sort.
更仔细地检查
fscanf()
的返回值;例如,如果匹配 3 个字段,它将返回 3。您可能需要小心各种字符串的大小以避免缓冲区溢出 - 但这可能是另一天的主题。令我震惊的可能性是,格式字符串中的最后一个制表符可能作为换行符更好 - 但 fscanf() 通常对格式字符串和数据中的空白采取相当自由的态度。
这个简化的(但完整的、有效的)代码版本在 MacOS X 上表现或多或少是理智的。
但是,它确实将字符串“
kkkk k
”(由空格分隔的 5 个单个字母)视为等效于由 5 个选项卡分隔。因此,问题在于 C 标准的第 §7.19.6.2 节规定:另外,关于“%s”说明符,它说:
要强制匹配实际选项卡,您必须更加努力。诉诸“将一行读入缓冲区(
fgets()
”)并手动拆分它会更容易。这还允许您在一行上强制使用 5 个单词,如果字段太少或太多,您可能会生成错误或警告。使用fscanf()
,您无法做到这一点。如果您在一行上输入 8 个单词,它会第一次读取前五个单词,然后是该行剩余的三个单词,加上下一行的前两个单词,依此类推。Check the return value from
fscanf()
more carefully; it will return, for example, 3 if it matches 3 fields. You might want to be careful about the sizes of the various strings to avoid buffer overflows - that is, however, probably a subject for another day.The possibility which strikes me is that the last tab in the format string might be better as a newline - but
fscanf()
normally takes a fairly liberal attitude towards white space in the format strings and data.This simplified (but complete, working) version of your code behaves more or less sanely on MacOS X.
However, it did treat a string '
k k k k k
' (5 single letters separated by blanks) as equivalent to separated by 5 tabs. The problem, therefore, is that section §7.19.6.2 of the C standard specifies:Also, with regards to the '%s' specifier, it says:
To force matching of actual tabs, you'd have to work quite a bit harder. It would be much easier to resort to the 'read a line into a buffer (
fgets()
) and split it manually'. This will also allow you to enforce 5 words on a line and you can generate an error or warning if there are too few or too many fields. Withfscanf()
, you cannot do that. If you type 8 words on a line, it will read the first five the first time, then the remaining three words on the line plus the first two on the next, and so on.成功后,
fscanf
返回成功读取的项目数。该计数可以与预期数量匹配,或者在匹配失败的情况下更少。
您应该检查
fscanf
的返回值以查看哪一行未正确解析并检查您的输入数据。On success, the
fscanf
returns the number of items succesfully read.This count can match the expected number or be less in case of a matching failure.
You should check
fscanf
s return value to see which line isn't parsed correctly and examine your input data.