一个可能的起点是重载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"!
添加任何一个都相当容易,但您还没有说要支持哪个(如果有的话),所以我暂时省略了。