如何编写`std :: istream`运算符

时间:2015-06-26 16:44:39

标签: c++ parsing stream

如果该流包含意外内容,在预期之前结束或未完全消耗,我如何编写一个读取std::istream并设置正确标志的函数?

具体来说,假设我希望流包含一串字母字符后跟一个分隔符,然后是一些数字,如foo:55。我想阅读类似

的内容
struct var {
  std::string name;
  double value;
};

来自溪流。我当然可以将运算符编写为

std::istream& operator>>(std::istream& s, var& x) {
  std::string str;
  s >> str;
  size_t sep = str.find(':');
  x.name  = str.substr(0,sep);
  x.value = atof(str.substr(sep+1).c_str());
  return s;
}

但是我可以不将流内容复制到字符串吗?此外,在str不包含整个流内容的意义上,这不适用于空格。

一周前我问了一个类似的question,但没有回复,可能是因为我在boost::program_options的背景下将其框起来了,这些问题似乎并没有得到多少关注这里。

2 个答案:

答案 0 :(得分:1)

您可以使用std::getline代替s >> str来阅读':',然后直接将数字读入double,如下所示:

std::istream& operator>>(std::istream& s, var& x) {
    // Skip over the leading whitespace
    while (s.peek() == '\n' || s.peek() == ' ') {
        s.get();
    }
    std::getline(s, x.name, ':');
    s >> x.value;
    return s;
}

Demo.

答案 1 :(得分:1)

为什么不让流为您完成工作。您可以使用getline()>>istream::ignore()来阅读输入内容。

std::istream& operator>>(std::istream& s, var& x) {
    // get the string part and through out the :
    std::getline(s, x.name, ':');
    // get the number part
    s >> x.value;
    // consume the newline so the next call to getline won't include it in the string part
    s.ignore(std::numeric_limits<std::streamsize>::max(), '\n')
    return s;
}