Выражение: Итератор строки не может быть разыменован - PullRequest
0 голосов
/ 30 июня 2009

Мне трудно использовать std :: string :: iterators в C ++. Этот код прекрасно компилируется (все еще не получает правильный вывод, но это моя ошибка: TODO, алгоритм исправления) в Dev-C ++, и я не получаю ошибок во время выполнения. Ошибка в Visual Studio Express 2008 C ++, где я получаю сообщение об ошибке, указывающее на : «Выражение: итератор строки не разыменовывается» и указывает на строку 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;    
}

Ответы [ 3 ]

15 голосов
/ 30 июня 2009

Во-первых, используйте оператор! = () На итераторах, а не оператор <(): </p>

while (it != sentence.end())

Во-вторых, это в обратном направлении: while (*it != ' ' && it != sentence.end())

Вы делаете что-то с итератором, чем проверяете, действителен ли итератор. Скорее, вы должны сначала проверить, действительно ли он действителен:

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

В-третьих, вы должны использовать итератор ++ вместо итератора ++, хотя это не связано с вашим сбоем.


В-четвертых, главная проблема здесь:

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

Надеюсь, это поможет!

5 голосов
/ 30 июня 2009
while (*it != ' ' && it != sentence.end())

изменяется на

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

поэтому второе выражение не оценивается, если первое, если ложно.

   if (nextWordLength > distanceFromWidth)

должно измениться на

   if (it == sentence.end())
         break;
   if (nextWordLength > distanceFromWidth)
0 голосов
/ 30 июня 2009

Почти наверняка ваша ошибка является результатом:

*it = '\n';

Так как в предыдущем цикле while одно из ваших условий остановки:

it != sentence.end()

Если это == предложение.end (), то * оно = '\ n' не полетит

Есть еще ошибки, но это та, которая вызывает вашу текущую проблему.

...