3

重複の可能性:
C++で文字列を分割する

関数の動作を模倣する関数を作成しようとしてgetline()いますが、区切り文字を使用して文字列をトークンに分割するオプションがあります。この関数は、2つの文字列(2つ目は参照によって渡されます)とchar区切り文字のタイプを受け入れます。最初の文字列の各文字をループし、それを2番目の文字列にコピーし、区切り文字に到達するとループを停止します。true最初の文字列の区切り文字の後の文字数が多い場合などに返されますfalse。最後の文字の位置は静的変数に保存されています。何らかの理由で、プログラムは無限ループに入り、何も実行していません。

const int LINE_SIZE = 160;
bool strSplit(string sFirst, string & sLast, char cDelim) {
    static int iCount = 0;
    for(int i = iCount; i < LINE_SIZE; i++) {
        if(sFirst[i] != cDelim)
            sLast[i-iCount] = sFirst[i];
        else {
            iCount = i+1;
            return true;
        }
    }
    return false;
}

この関数は次のように使用されます。

while(strSplit(sLine, sToken, '|')) {
    cout << sToken << endl;
}

なぜそれは無限ループに入り、なぜそれは機能しないのですか?istringstream可能であれば、を使用せずに解決策に興味があることを追加する必要があります。

4

4 に答える 4

5

それはまさにあなたが求めたものではありませんが、検討std::istringstreamしましたstd::getlineか?

// UNTESTED
std::istringstream iss(sLine);
while(std::getline(iss, sToken, '|')) {
  std::cout << sToken << "\n";
}

編集

なぜ無限ループに陥り、なぜ機能しないのでしょうか?

わかりません。十分な情報が提供されていません。SSCCEを作成して投稿してみてください。

次の行は非常に疑わしいと言えます。

       sLast[i-iCount] = sFirst[i];

この行は、次の条件のいずれかで未定義の動作 (おそらく、あなたが見たものを含む) を引き起こします:

  • i >= sFirst.size()
  • i-iCount >= sLast.size()
  • i-iCount < 0

これらの条件はすべて真であると思われます。たとえば、渡された文字列が 160 行より短い場合、またはiCount最初の区切り文字のオフセットより大きくなった場合、未定義の動作が発生します。

于 2012-09-12T16:55:28.197 に答える
3

LINE_SIZEおそらくオブジェクト内の文字数よりも大きいstringため、コードは文字列のストレージの最後から実行され、ほとんどすべてが発生する可能性があります.

自分でロールバックする代わりに、string::find必要なことを行います。

std::string::size_type pos = 0;
std::string::size_type new_pos = sFirst.find('|', pos);

への呼び出しfindは、'|' の最初のオカレンスを検索します。それは位置「pos」以降です。成功すると、'|' のインデックスが返されます。それが見つかったこと。失敗した場合は、 を返しますstd::string::npos。ループで使用し、一致するたびに [pos, new_pos) のテキストをターゲット文字列にコピーし、 に更新posnew_pos + 1ます。

于 2012-09-12T17:09:26.257 に答える
1

strSplit()返されないのは関数だと確信していますか、whileそれとも無限の呼び出し元ループですか?

呼び出し元のループは次のようにすべきではありません:

while(strSplit(sLine, sToken, '|')) {
    cout << sToken << endl;
    cin >> sLine >> endl;
}

- 編集 -

の値がtrue を返すsLineようなものである場合、ループは無限になります。そのため、ループの反復ごとに の値を変更する何かを行います。たとえば、 ..strSplit()whilesLinecin

于 2012-09-12T16:57:29.007 に答える
0

これをチェックしてください

std::vector<std::string> spliString(const std::string &str, 
                                    const std::string &separator)
{
    vector<string>      ret;
    string::size_type   strLen = str.length();
    char                *buff;
    char                *pch;

    buff = new char[strLen + 1];
    buff[strLen] = '\0';
    std::copy(str.begin(), str.end(), buff);

    pch = strtok(buff, separator.c_str());
    while(pch != NULL)
    {
        ret.push_back(string(pch));
        pch = strtok(NULL, separator.c_str());
    }

    delete[] buff;

    return ret;
}
于 2012-09-12T17:01:36.363 に答える