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

时间:2010-04-01 19:03:41

标签: 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;
}

有人提到这会在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;
}

stringstreamstring支持,因此我们不必担心与从文件中读取相关的任何问题。此处没有类型转换,因为getline只是读取直到它看到行分隔符或EOF。因此,我们无法获得boost::lexical_cast之类的任何错误。

除了没有分配足够可能出错的内存之外,我根本无法想到一些东西,但是在std::bad_alloc甚至发生之前,它只会抛出std::getline。我错过了什么?

1 个答案:

答案 0 :(得分:6)

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

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

但是,实际发生的事情可能会有些混乱。由于 getline 使用 delim - 已终止字段而非 delim - 已分隔字段,因此输入像"a\nb\n"这样的数据有两个而不是三个字段,这可能会令人惊讶。对于行而言,这是完全合理的(并且是POSIX标准),但是在分割后,您希望在'-'中找到{{1>}的 delim 多少个字段? / p>


顺便说一句,这是我write split

的方式
"a-b-"

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

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;
}
相关问题