Подтвердить что ты не робот

Объяснение функции обрезки строки

Я столкнулся с приведенным ниже кодом, но мне нужна помощь в понимании кода. Предположим, что строка s имеет пробелы с обеих сторон.

string trim(string const& s){
   auto front = find_if_not(begin(s), end(s), isspace);
   auto back = find_if_not(rbegin(s), rend(s), isspace);
   return string { front, back.base() };
}

Автор утверждал, что обратные точки заканчиваются в конце последнего пространства, тогда как фронт указывает на первый небелый пробел. Поэтому был вызван back.base(), но я не понимаю, почему.

Также, что фигурные скобки, следующие за строкой в ​​операторе return, представляют?

4b9b3361

Ответ 1

Скобки - это новая инициализация С++ 11.

.base() и обратные итераторы

.base() - вернуть базовый итератор (back является reverse_iterator), чтобы правильно построить новую строку из допустимого диапазона.

Изображение. Нормальные позиции итератора строки (это немного сложнее, чем это относительно того, как rend() работает, но концептуально в любом случае...)

        begin                                 end
          v                                    v
        -------------------------------------
        | sp | sp | A | B | C | D | sp | sp |
        -------------------------------------
      ^                                   ^
    rend                                rbegin

Как только ваши две петли поиска закончатся, результат этих итераторов в этой последовательности будет располагаться по адресу:

                  front
                    v
        -------------------------------------
        | sp | sp | A | B | C | D | sp | sp |
        -------------------------------------
                                ^
                              back

Если мы возьмем только эти итераторы и построим из них последовательность (мы не можем, поскольку они не соответствуют типам, но независимо, предположили, что мы могли бы), результатом будет "копирование, начинающееся с A, остановка при D" , но он не будет включать D в результирующие данные.

Введите член back() обратного итератора. Он возвращает не-обратный итератор класса прямого итератора, который позиционируется в элементе "рядом с" итератором назад; то есть.

                  front
                    v
        -------------------------------------
        | sp | sp | A | B | C | D | sp | sp |
        -------------------------------------
                                    ^
                               back.base()

Теперь, когда мы скопируем наш диапазон { front, back.base() }, мы скопируем его начиная с A и остановимся в первом пространстве (но не включая его), тем самым включив D, который мы бы пропустили.

На самом деле это небольшой фрагмент кода, кстати.

Дополнительная проверка

Добавлены некоторые базовые проверки исходного кода.

В попытке сохранить дух исходного кода (использование С++ 1y/С++ 14), добавив некоторые базовые проверки только для пустых и белых пробелов,

string trim_check(string const& s)
{
  auto is_space = [](char c) { return isspace(c, locale()); };
  auto front = find_if_not(begin(s), end(s), is_space);
  auto back = find_if_not(rbegin(s), make_reverse_iterator(front), is_space);
  return string { front, back.base() };
}