我有一个文件,它有固定宽度的列,这些列是2和4位整数、一些浮点和字符串的混合。全都混在一起了。结果是一个扫描格式,运行在页面之外。。。
fscanf(file, "%2d%2d%2d%2d%4d%4d%4d%1s%1d%4d%1s%1d%4d%1s%1d%4d%1s%1d%4d%1s%1d%4d%1s%1d%4d%1s%1d%2d%1s%1d%2d%1s%1d%4d%1s%1d%4d%1s%1d%3d%1s%1d%4d%1s%1d%3d%1s%1d%3d%1s%1d%4d%1s%1d%5ld%1s%1d%1d%1d%1d%1d%1d%1d%1d%1d%1d%1d%3d%1s%1d%3d%1s%1d%3d%1s%1d%2d%1s%1d",
这甚至不包括变量列表!
关于如何使其可维护的建议?我应该连续做几次吗?或者人们在这种情况下有没有一个标准的解决方案?
更新:我在第一篇文章中包含了原始数据,但显然是在编辑过程中删掉的。有问题的数据称为TMY2,您可以找到定义和示例格式字符串here。还有一种新的格式TMY3,它使用CVS,所以我有很多很好的例子来说明如何解析它。
最佳答案
具有固定宽度列的混合文件。。。。
如何使其可维护?
步骤1,使用fgets()
将行读入一个大缓冲区。不要使用fscanf()
@Andrew Henle
#define MY_BUF_N 400
char buf[MY_BUF_N * 2]; // make buffer 2x aticipated max size
if (fgets(buf, sizeof buf, file) == NULL) {
Handle_EOF_or_Error();
}
根据重复模式识别组:
#define FMT_PRE "%2d%2d%2d%2d%4d%4d"
#define FMT_5 "%4ld%1s%1d"
#define FMT_4 "%4d%1s%1d"
#define FMT_3 "%4d%1s%1d"
#define FMT_2 "%4d%1s%1d"
#define FMT_MID "%1d%1d%1d%1d%1d%1d%1d%1d%1d%1d"
使用字符串文字连接。@jxh
#define FMT_ALL FMT_PRE \
FMT_4 FMT_4 FMT_4 FMT_4 FMT_4 FMT_4 \
FMT_2 FMT_2 FMT_4 FMT_4 FMT_3 FMT_4 \
FMT_4 FMT_4 FMT_3 FMT_3 FMT_4 FMT_5 \
FMT_MID \
FMT_3 FMT_3 FMT_3 FMT_2
使用
" %n"
测试整个扫描是否成功int n = 0;
sscanf(FMT_ALL " %n", ...
...
... /* variable list laid out like the format statements. */
...
&n);
测试
n
// Did scan reach the end?
if (n == 0) {
Handle_incomplete_scan();
}
// Was there any remaining junk?
if (buf[n] != '\0') {
Handle_junk_at_the_end();
}
添加其他测试以验证对象是否在范围内。
总的来说,我会重写。@PeterJ_01在使用
fgets()
的步骤1之后,使用使用strtol()
的助手函数按顺序分析数据。size_t i = 0; // Index in buffer
if (parse_int(&object1, buf, &i, min_value, max_value)) error();
if (parse_int(&object1, buf, &i, min_value, max_value)) error();
...
if (parse_string(object7, sizeof object7, buf, &i)) error();
....
if (parse_long(&object12, buf, &i, min_value, max_value)) error();
...
关于c - 我应该分解长的scanf使其可维护吗?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/49804428/