我有一个文件,它有固定宽度的列,这些列是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/

10-12 16:21