0

C++でstd::string::iteratorsを使用するのに苦労しています。このコードは、Dev-C ++で正常にコンパイルされ(それでも正しい出力は得られませんが、それは私のせいです:TODO、アルゴリズムの修正)、ランタイムエラーは発生しません。エラーはVisualStudioExpress 2008 C ++で発生し、<xstring>を指すエラーが発生します: "Expression:string iterator not dereferencable"、および<xstring>ファイルの行112を指します。

デバッグの結果、入力された文の終わりを超えて逆参照しようとしている可能性がありますが、どこにあるのかわかりません。誰かが光を当てることができますか?

std::string wordWrap(std::string sentence, int width)
{    
    std::string::iterator it = sentence.begin();

    //remember how long next word is
    int nextWordLength = 0;
    int distanceFromWidth = width;

    while (it < sentence.end())
    {
       while (*it != ' ' && it != sentence.end())
       {
          nextWordLength++;
          distanceFromWidth--;
          it++;
       }

       if (nextWordLength > distanceFromWidth)
       {
          *it = '\n';
          distanceFromWidth = width;
          nextWordLength = 0;
       }

       //skip the space
       it++;

   }

   return sentence;    
}
4

3 に答える 3

15

まず、operator<() ではなく、イテレータで operator!=() を使用します。

while (it != sentence.end())

第二に、これは逆です:while (*it != ' ' && it != sentence.end())

イテレータが有効かどうかを確認するよりも、イテレータで何かをします。むしろ、最初に有効かどうかを確認する必要があります。

while (it != sentence.end() && *it != ' ')

第三に、これはクラッシュとは関係ありませんが、iterator++ よりも ++iterator を使用する必要があります。


第 4 に、主な問題は次のとおりです。

*it = '\n';

先行チェックによりwhile (it != sentence.end()、最後にいる間にイテレータの逆参照に到達する可能性があります。修正はこれを行うことです:

if (it != sentence.end() && nextWordLength > distanceFromWidth)

だから今、あなたが終わりに達したなら、あなたはやめます。


以前の問題を修正した後、唯一の問題は次のとおりです。

//skip the space
++it;

これは、スキップする文字が実際にはスペースであることを前提としています。しかし、文字列の最後はどうですか? この関数を次の文字列で実行します。

"a test string " // <- space at end

そしてそれは成功します。スペースをスキップし、イテレータをに配置end()すると、ループが終了し、成功します。

ただし、最後に到達し、最後をスキップしているため、スペースがないとクラッシュします。修正するには、チェックを追加します。

//skip the space
if (it != sentence.end())
{
    ++it;
}

この最終的なコードは次のようになります。

std::string wordWrap(std::string sentence, int width)
{    
    std::string::iterator it = sentence.begin();

    //remember how long next word is
    int nextWordLength = 0;
    int distanceFromWidth = width;

    while (it != sentence.end())
    {
        while (it != sentence.end() && *it != ' ')
        {
            nextWordLength++;
            distanceFromWidth--;
            ++it;
        }

        if (it != sentence.end() && nextWordLength > distanceFromWidth)
        {
            *it = '\n';
            distanceFromWidth = width;
            nextWordLength = 0;
        }

        //skip the space
        if (it != sentence.end())
        {
            ++it;
        }

    }

    return sentence;    
}

これには多くの冗長なチェックがあるように見えることに気付くかもしれません。これは修正できます。

std::string wordWrap(std::string sentence, int width)
{    
    std::string::iterator it = sentence.begin();

    //remember how long next word is
    int nextWordLength = 0;
    int distanceFromWidth = width;

    while (it != sentence.end())
    {
        while (*it != ' ')
        {
            nextWordLength++;
            distanceFromWidth--;

            ++it;

            // check if done
            if (it == sentence.end())
            {
                return sentence;
            }
        }

        if (nextWordLength > distanceFromWidth)
        {
            *it = '\n';
            distanceFromWidth = width;
            nextWordLength = 0;
        }

        //skip the space
        ++it;
    }

    return sentence;    
}

うまくいけば、それは役に立ちます!

于 2009-06-30T06:27:21.487 に答える
5
while (*it != ' ' && it != sentence.end())

に変更

while (it != sentence.end() && *it != ' ')

したがって、最初の式がfalseの場合、2番目の式は評価されません。

   if (nextWordLength > distanceFromWidth)

おそらくに変更する必要があります

   if (it == sentence.end())
         break;
   if (nextWordLength > distanceFromWidth)
于 2009-06-30T06:10:46.990 に答える
0

ほぼ間違いなく、エラーは次の結果です。

*it = '\n';

前のwhileループでは、停止条件の1つが次のとおりです。

it != sentence.end()

it == statement.end() の場合、*it = '\n' は飛びません

他にもエラーがありますが、それが現在の問題の原因です。

于 2009-06-30T07:31:13.020 に答える