【问题标题】:Is there a better way to parse a line of text like this?有没有更好的方法来解析这样的一行文本?
【发布时间】:2011-12-02 22:59:36
【问题描述】:

我有一个文本文件,其中的文本行有一个字符串,另一个字符串后跟最多 4 个整数, 例如:

clear "clear water.png" 5 7
wet "wet water.png" 9 5 33 17
soft "soft rain falling.png" 

我看到的唯一方式是:

读取直到找到空间

将字符串设置为湿

读到双引号

读到第二个双引号

将第二个字符串设置为湿水.png

虽然不是行尾

读到空格

将字符串放入字符串流

将得到的整数推入 int 的向量中

有没有更好的方法来做到这一点?

谢谢

【问题讨论】:

  • 在逻辑、简单性、性能等方面更好?

标签: c++ string parsing


【解决方案1】:

这是 scanf 和公司真正闪耀的任务。

char first_string[33], second_string[129];

sscanf(input_string, 
    "%32s%*[^\"]%*c%128[^\"]%*c %d %d %d %d", 
    first_string, 
    second_string, 
    &first_int, 
    &second_int,
    &third_int,
    &fourth_int);

您可能希望在 if 语句中执行此操作,以便您可以测试返回值,告诉您有多少字段转换(例如,这样您就知道最后读取了多少整数)。

编辑:也许一些解释会有所帮助。让我们剖析一下:

%32s 将字符串读取到第一个空格(或 32 个字符,以先到者为准)。
%*[^\"] 忽略直到第一个 " 的输入。
%*c 忽略输入的一个字节(引用本身)
%128[^\"] 读取引号中的字符串(即,直到下一个引号字符)。
%*c 忽略结束引号 %d 读取一个 int(我们已经做了四次)。

每个%d 之前的空格确实是不必要的——它会跳过空格,但如果没有空格,%d 无论如何都会跳过前导空格。我将它们包括在内纯粹是为了使其更具可读性。

【讨论】:

  • 我觉得这是一个很好的答案!
  • 不得不对此表示赞同,尽管我对 scanf 的评价不高,而且它不是惯用的 C++。
  • @ybungalobill:您认为它有什么不标准的地方?如果您正在考虑%[^\"],那您就错了——这是标准 C 的一部分的扫描集转换。它也不是新的——虽然不在 K&R1 中,但它从一开始就在标准中,因为到那时它已经很普遍了。
  • @JerryCoffin:嗯,没有 C89 标准,但按照 C99,你是对的。不知道这个。谢谢!
【解决方案2】:

丑陋,没有错误检查,但不依赖任何非标准库:

string s;
while(getline(fin, s))
{
    string word, quoted_string;
    vector<int> vec;

    istringstream line(s);
    line >> word;
    line.ignore(numeric_limits<streamsize>::max(), '"');
    getline(line, quoted_string, '"');
    int n;
    while(line >> n) vec.push_back(n);

    // do something with word, quoted_string and vec...
}

【讨论】:

    【解决方案3】:

    根据输入字符串的限制,您可以尝试在double-quote 上拆分,然后在space 上拆分。

    【讨论】:

      【解决方案4】:

      是的

      使用getline 一次读取一行。使用a regular expression library 解析行。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-02-23
        • 1970-01-01
        • 2011-01-24
        • 2011-10-23
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多