方式std :: stringstream可以设置失败/坏位吗?

Eva*_*ran 9 c++ stringstream getline

我用于简单字符串拆分的常见代码如下所示:

inline std::vector<std::string> split(const std::string &s, char delim) {
    std::vector<std::string> elems;
    std::stringstream ss(s);
    std::string item;
    while(std::getline(ss, item, delim)) {
        elems.push_back(item);
    }
    return elems;
}
Run Code Online (Sandbox Code Playgroud)

有人提到这会默默地"吞噬"发生的错误std::getline.当然,我同意这种情况.但是我想到了,在实践中我可能会出现什么问题,我需要担心.基本上这一切归结为:

inline std::vector<std::string> split(const std::string &s, char delim) {
    std::vector<std::string> elems;
    std::stringstream ss(s);
    std::string item;
    while(std::getline(ss, item, delim)) {
        elems.push_back(item);
    }

    if(/* what error can I catch here? */) {
        // *** How did we get here!? ***
    }

    return elems;
}
Run Code Online (Sandbox Code Playgroud)

A stringstream由a支持string,因此我们不必担心与从文件读取相关的任何问题.此处没有类型转换,因为getline只需读取直到它看到行分隔符或EOF.所以我们不能得到任何类似的错误boost::lexical_cast.

除了未能分配足够可能出错的内存之外,我根本无法想到一些东西,但这只会std::bad_allocstd::getline偶数发生之前抛出一口井.我错过了什么?

小智 6

我无法想象这个人认为会发生什么错误,你应该让他们解释一下.除了分配错误之外什么都不会出错,正如你所提到的那样,它们被抛出而不被吞没.

我唯一看到你直接遗漏的是ss.fail()在while循环之后保证是真的,因为那是被测试的条件.(bool(stream)相当于!stream.fail(),不是 stream.good().)正如预期的那样,ss.eof()也是如此,表明失败是由于EOF造成的.

但是,对实际发生的事情可能存在一些混淆.因为getline使用delim - 终止字段而不是delim - 分隔字段,所以输入数据"a\nb\n"有两个而不是三个字段,这可能会令人惊讶.对于线,这使得完整意义上的(并且是POSIX标准),但究竟有多少领域,具有DELIM'-',你会期望找到在"a-b-"分割后?


顺便说一句,这是我 分裂的方式:

template<class OutIter>
OutIter split(std::string const& s, char delim, OutIter dest) {
  std::string::size_type begin = 0, end;
  while ((end = s.find(delim, begin)) != s.npos) {
    *dest++ = s.substr(begin, end - begin);
    begin = end + 1;
  }
  *dest++ = s.substr(begin);
  return dest;
}
Run Code Online (Sandbox Code Playgroud)

这首先避免了iostreams的所有问题,避免了额外的副本(字符串流的支持字符串;加上substr返回的temp甚至可以使用C++ 0x rvalue引用来移动语义,如果支持,如所写),具有我期望从split(与你的不同)的行为,并适用于任何容器.

deque<string> c;
split("a-b-", '-', back_inserter(c));
// c == {"a", "b", ""}
Run Code Online (Sandbox Code Playgroud)