9

単純な文字列分割に使用する一般的なコードは次のようになります。

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;
}

Astringstreamは によってサポートされているstringため、ファイルからの読み取りに関連する問題について心配する必要はありません。getline行区切りまたはEOF. boost::lexical_castそのため、何かが心配しなければならないようなエラーを取得することはできません。

問題が発生する可能性のある十分なメモリの割り当てに失敗する以外に、何かを考えることはできませんが、イベントが発生するstd::bad_alloc前に問題が発生するだけstd::getlineです。私は何が欠けていますか?

4

1 に答える 1

6

この人がどのようなエラーが発生すると考えているのか、私には想像できません。説明を求めるべきです。あなたが述べたように、スローされて飲み込まれない割り当てエラーを除いて、何も問題はありません。

あなたが直接見逃しているss.fail()のは、whileループの後に真であることが保証されていることだけです。これがテストされている条件だからです。(はではなくbool(stream)と同等です。) 予想どおり、も true になり、失敗が EOF によるものであることを示します。!stream.fail() stream.good()ss.eof()

ただし、実際に何が起こっているのかについては、多少の混乱があるかもしれません。getlinedelim区切られたフィールドではなくdelim区切られたフィールドを使用するため、 のような入力データ"a\nb\n"には 3 つのフィールドではなく 2 つのフィールドがあり、これは驚くべきことです。行の場合、これは完全に理にかなっています (そして POSIX 標準です) が、分割後にで区切ら'-'れたフィールドはいくつあると予想されますか?"a-b-"


ちなみに、splitの書き方 は次のとおりです。

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;
}

これにより、最初の場所で iostream に関するすべての問題が回避され、余分なコピーが回避されます (文字列ストリームのバッキング文字列に加えて、substr によって返される一時は、サポートされている場合、移動セマンティクスに C++0x 右辺値参照を使用することさえできます)。分割に期待する動作(あなたのものとは異なります)であり、任意のコンテナで動作します。

deque<string> c;
split("a-b-", '-', back_inserter(c));
// c == {"a", "b", ""}
于 2010-04-01T20:43:40.830 に答える