Выражение:Строковый итератор, не разыменуемый
-
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 = ' ' не вылетит
Есть и другие ошибки, но это та, которая вызывает вашу текущую проблему.