【问题标题】:Read tab separated content line by line with last column empty string使用最后一列空字符串逐行读取制表符分隔的内容
【发布时间】:2018-01-23 16:57:22
【问题描述】:

我有这样的文件格式

1.9969199999999998  2.4613199999999997  130.81278270000001  AA
2.4613199999999997  2.5541999999999998  138.59131554109211  BB
2.5541999999999998  2.9953799999999995  146.83238401449094  CC
...........................

我必须将前三列读为float,最后一列读为C 中的char 数组。所有列都是制表符分隔的,每行末尾都有一个换行符。 fscanf(fp1, "%f\t%f\t%f\t%s\n", ...) 一切正常,直到我在每行末尾都有一些文本(字符字符串部分)。

在某些情况下,我在文件中有一个空字符串,而不是 AA/BB/CC。这种情况怎么处理。我尝试了fscanf(fp1, "%f\t%f\t%f\t%s[^\n]\n", ...) 和许多其他方法,但我无法找出正确的方法。你能帮帮我吗?

【问题讨论】:

  • 别说“没用”,真的,真的烦人。而是说它做了你不希望它做什么,或者更具体地说,它没有做什么你确实想要它。
  • 使用float 而不是double 将丢弃显示的一半数字。 float 得到 6-7 个十进制数字; double 得到 15 位以上的数字。
  • 至于您的主要问题:使用fgets() 读取行,然后使用sscanf() 解析读取的行。这样可以避免混淆。当输入是基于行但不够规则时,不要使用fscanf() 和家人来读取数据——他们文件读取scanf() 函数不关心换行符,即使你这样做。 (请注意,sscanf() 将返回 3 或 4,表示行尾是否有字符串。始终测试来自 scanf() 和朋友的返回值 - 但要小心。)
  • 我,我不会使用任何 *scanf 系列来解决这类问题。我会使用fgets 读取整行,然后将每一行拆分为制表符分隔的字段。将一行拆分为字段(基于分隔符)很简单——您可以为此使用strtokstrsep。 (或见eskimo.com/~scs/cclass/notes/sx10h.html。)
  • @tadman 很抱歉选错了词。编辑问题!感谢您指出:)

标签: c fileparsing


【解决方案1】:

使用float 而不是double 将丢弃大约一半的数字。 float 得到 6-7 个十进制数字; double 得到 15 位以上的数字。

至于您的主要问题:使用fgets()(或POSIX getline()) 读取行,然后 sscanf() 解析读取的行。这样可以避免混淆。当输入是基于行但不够规则时,不要使用 fscanf() 和家人来读取数据 - 文件读取 scanf() 函数不关心换行,即使你这样做。

注意sscanf() 将返回 3 或 4,表示行尾是否有字符串(或 EOF012,如果给出一个空字符串,或者一个不以数字开头的字符串,或者一个只包含一个或两个数字的字符串)。始终测试来自scanf() 和朋友的返回值——但要小心。查找您期望的值的数量(本例中为 3 或 4),而不是“非 EOF”。

这大致导致:

#include <stdio.h>

int main(void)
{
    double d[3];
    char text[20];
    char line[4096];

    while (fgets(line, sizeof(line), stdin) != 0)
    {
        int rc = sscanf(line, "%lf %lf %lf %19s", &d[0], &d[1], &d[2], &text[0]);
        if (rc == 4)
            printf("%13.6f  %13.6f  %13.6f  [%s]\n", d[0], d[1], d[2], text);
        else if (rc == 3)
            printf("%13.6f  %13.6f  %13.6f  -NA-\n", d[0], d[1], d[2]);
        else
            printf("Format error: return code %d\n", rc);
    }
    return 0;
}

如果将此文件作为标准输入:

1.9969199999999998  2.4613199999999997  130.81278270000001  AA
2.4613199999999997  2.5541999999999998  138.59131554109211  BB
2.5541999999999998  2.9953799999999995  146.83238401449094  CC
19.20212223242525  29.3031323334353637 3940.41424344454647
19.20212223242525  29.3031323334353637 3940.41424344454647  PolyVinyl-PolySaccharide

输出是:

 1.996920       2.461320     130.812783  [AA]
 2.461320       2.554200     138.591316  [BB]
 2.554200       2.995380     146.832384  [CC]
19.202122      29.303132    3940.414243  -NA-
19.202122      29.303132    3940.414243  [PolyVinyl-PolySacch]

您可以调整输出格式以适合自己。请注意,即使文本长度超过 19 个字符,%19s 也会避免缓冲区溢出。

【讨论】:

  • 解释得很好..谢谢!
猜你喜欢
  • 1970-01-01
  • 2019-08-30
  • 2010-11-08
  • 1970-01-01
  • 2017-04-23
  • 1970-01-01
  • 2011-10-06
  • 1970-01-01
相关资源
最近更新 更多