用空格解析一个字符串

时间:2016-08-03 04:12:56

标签: c++ string parsing

我在一个文件中有行,每行中的每行都用空格分隔。这是一个简化的线条示例:

208 "Person" "Anne Myers" "unsigned long" "hello" -1 false false false

在单个字段中,某些单词由空格分隔。即“安妮迈尔斯”。这是解析的问题。

有什么建议吗?输出应该是9个字段,以便进一步处理。 在我的情况下,用某些字符替换字段内的空格是不可行的。

编辑:所有行都遵循相同的字段顺序。

1 个答案:

答案 0 :(得分:0)

一个可能的起点是一个重载operator>>以便以这种格式正确读取数据的类型:

class field { 
    std::string content;
public:
    friend std::istream &operator>>(std::istream &is, field &f) { 
        char ch;

        // skip whitespace, then read one character
        is >> ch;

        // If it's a quote, read to the next quote
        if (ch == '"')
            std::getline(is, f.content, '"');
        else {
            // otherwise put it back, and read until white-space:
            is.unget();
            std::getline(is, f.content);
        }
        return is;
    }

    // While we're at it, I'm going to define output so we can see what was 
    // read in a single field easily:
    friend std::ostream &operator<<(std::ostream &os, field const &f) { 
        return os << "[" << f.content << "]";
    }
};

然后我们可以为单行定义记录类型,将该类型用于适当的字段:

struct foo { 
    int a;
    field b;
    field c;
    field d;
    field e;
    int f;
    bool g, h, i;

    friend std::istream &operator>>(std::istream &is, foo &f) { 
        return is >> std::boolalpha 
                  >> f.a 
                  >> f.b 
                  >> f.c 
                  >> f.d 
                  >> f.e 
                  >> f.f 
                  >> f.g 
                  >> f.h 
                  >> f.i;
    }

    friend std::ostream &operator<<(std::ostream &os, foo &f) { 
        return os << std::boolalpha 
                  << f.a << " " 
                  << f.b 
                  << f.c 
                  << f.d 
                  << f.e << " " 
                  << f.f  << " "
                  << f.g << " " 
                  << f.h << " " 
                  << f.i;
    }
};

然后我们可以测试阅读和写一条记录:

int main() { 
    std::istringstream in
        { R"(208 "Person" "Anne Myers" "unsigned long" "hello" -1 false false false)" };

    foo f;

    in >> f;
    std::cout << f;
}

结果:

208 [Person][Anne Myers][unsigned long][hello] -1 false false false

这(目前)不会尝试处理也包含引号的字段。这可能是使用类似C的约定,我们使用反斜杠转义引号,或类似CSV的约定,其中我们通过在输入中的一行中放入两个引号来包含一个引号。

例如:

"Bill said: ""Go away""!"

...将被解析为一个字段,包含文本:

Bill said: "Go away"!

要么很容易添加,要么你没有说要支持哪个(如果有的话),所以我暂时把它留了出来。