Почему не работает моя функция обрезки? - PullRequest
1 голос
/ 20 августа 2010
void trim(string &str)
{
    string::iterator it = str.begin();
    string::iterator end = str.end() - 1;

    // trim at the starting
    for(; it != str.end() && isspace(*it); it++)
        ;
    str.replace(str.begin(), it, "");

    // trim at the end
    for(; end >= str.begin() && isspace(*end); end--)
        ;
    str.replace(str.end(), end, ""); // i get the out_of_range exception here
}

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

Почему?

Ответы [ 5 ]

7 голосов
/ 20 августа 2010

Изменение строки делает недействительными итераторы в строку. Один из способов исправить это - изменить строку только один раз. Кстати, это также может быть быстрее:

void trim(std::string &str)
{
    std::string::size_type begin=0;
    while(begin<str.size() && isspace(str[begin]))
      ++begin;
    std::string::size_type end=str.size()-1;
    while(end>begin && isspace(str[end]))
      --end;
    str = str.substr(begin, end - begin + 1)
}
3 голосов
/ 20 августа 2010

Я бы предложил просто использовать boost :: trim

2 голосов
/ 20 августа 2010

Итераторы верны только до тех пор, пока вы не измените строку. Как только вы измените строку, конечный итератор обязательно станет недействительным.

Вам необходимо повторно выбирать итераторы после каждого действия, которое может изменить строку.

0 голосов
/ 20 августа 2010

Проблема в том, что вы сохраняете итератор до последнего символа в строке и используете его только после того, как вы (потенциально) удалили символы из строки, поэтому сохраненный итератор теперь недопустим (не указывая ни на какой последний символ). больше).

Это поможет объявить переменные как можно ближе к их первому использованию. В частности, итераторы, как правило, становятся недействительными настолько легко, что вам вообще следует избегать их удержания дольше, чем необходимо.

Итак, инициализируйте конечный итератор после удаления начальных пробелов. (Можно также рассмотреть вопрос об удалении завершающих пробелов.)


Могу ли я также предложить использовать функцию-член erase для удаления символов из строки.

Могут быть и другие ошибки при удалении конечных пробелов, но вы можете это выяснить, когда попадете туда.

0 голосов
/ 20 августа 2010

str.end () не относится ни к какой позиции со строкой; следовательно, если вы попытаетесь разыменовать его, вы получите исключение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...