Выражение:Строковый итератор, не разыменуемый

StackOverflow https://stackoverflow.com/questions/1061966

  •  21-08-2019
  •  | 
  •  

Вопрос

Мне трудно использовать std::string:: итераторы в C ++.Этот код компилируется нормально (по-прежнему не получается корректный вывод, но это моя вина:TODO, алгоритм исправления) в Dev-C ++, и я не получаю ошибок во время выполнения.Ошибка связана с Visual Studio Express 2008 C ++, где я получаю сообщение об ошибке, указывающее на < xstring>:"Выражение:строковый итератор не разыменуемый" и указывает на строку 112 из < xstring> файл.

Моя отладка подсказывает мне, что я, возможно, пытаюсь выполнить разыменование после конца входного предложения, но я не вижу, где именно.Кто-нибудь может пролить немного света?

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;    
}
Это было полезно?

Решение

Во-первых, используйте operator!=() для итераторов, а не operator<():

while (it != sentence.end())

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

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

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

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


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

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

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

Другие советы

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

изменения в

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

таким образом, второе выражение не вычисляется, если первое имеет значение false.

   if (nextWordLength > distanceFromWidth)

вероятно, следует сменить на

   if (it == sentence.end())
         break;
   if (nextWordLength > distanceFromWidth)

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

*it = '\n';

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

it != sentence.end()

Если it == sentence.end(), то *it = ' ' не вылетит

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top