Чтение онлайн

ЖАНРЫ

C++. Сборник рецептов

Когсуэлл Джефф

Шрифт:

Seq

Это тип, удовлетворяющий требованиям к последовательностям стандарта C++.

Coll

Это тип, удовлетворяющий менее строгим требованиям, чем стандартная последовательность. Для того чтобы узнать, каким требованиям удовлетворяет коллекция, обратитесь к определениям Boost String Algorithms.

Pred

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

OutIt

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

Табл. 4.1.

Шаблоны функций обрезки строк Boost

Объявление Описание
template<typename Seq> void trim(Seq& s, const locale& loc = locale);
Обрезает пробелы с обоих концов строки, используя для классификации пробельных символов функцию классификации локали
template<typename Seq, typename Pred> void trim_if(Seq& s, Pred p);
Обрезает с обоих концов последовательности s элементы для которых
p(*it)
равно
true
, где
it
— это итератор, указывающий на элемент последовательности. Обрезка прекращается, когда
p(*it) = false
template<typename Seq> Seq trim_copy(const Seq& s, const locale& loc = locale);
Делает то же самое, что и
trim
, но вместо изменения
s
возвращает новую последовательность, содержащую обрезанные результаты
template<typename Seq, typename Pred> Seq trim_copy_if(const Seq& s, Pred p);
Делает то же самое, что и
trim_if
, но вместо изменения
s
возвращает новую последовательность, содержащую обрезанные результаты
template<typename OutIt, typename Coll, typename Pred> OutIt trim_copy_if(OutIt out, const Coll& c, Pred p);
Делает то же, что и предыдущая версия
trim_copy_if
, но с некоторыми отличиями. Во-первых, она дает гарантию строгой безопасности исключений. Во-вторых, она в качестве первого аргумента принимает выходной итератор и возвращает выходной итератор, указывающий на одну позицию после конца результирующей последовательности. Наконец, она принимает тип коллекции, а не последовательности. За дополнительной информацией обратитесь к списку перед этой таблицей
trim_left trim_right
Работает как
trim
, но только для левого или правого конца строки
trim_left_if trim_right_if
Работает как
trim_if
, но только для левого или правого конца строки
trim_left_copy trim_right_copy
Работает как
trim_сору
, но только для левого или правого конца строки
trim_left_copy_if trim_right_copy_if
Работает как
trim_copy_if
, но только для левого или правого конца строки. Обе функции имеют две версии — одна работает с последовательностью, а другая — с коллекцией

Первые четыре шаблона функции, описанные в табл. 4.1, — это базовая функциональность функций обрезки библиотеки String Algorithms. Остальные являются вариациями на их тему. Чтобы увидеть некоторые из них в действии, посмотрите на пример 4.5. Он показывает некоторые преимущества от использования этих функций перед методами

string
.

Пример 4.5. Использование функций обрезки строк Boost

#include <iostream>

#include <string>

#include <boost/algorithm/string.hpp>

using namespace std;

using namespace boost;

int main {

 string s1 = " ведущие пробелы?";

 trim_left(s1); // Обрезка оригинальной строки

 string s2 = trim_left_copy(s1); // Обрезка, но оригинал остается без изменений

 cout << "s1 = " << s1 << endl;

 cout << "s2 = " << s2 << endl;

 s1 = "YYYYboostXXX";

 s2 = trim_copy_if(s1, is_any_of("XY")); // Используется предикат

 trim_if(s1, is_any_of("XY"));

 cout << "s1 = " << s1 << endl;

 cout << "s2 = " << s2 << endl;

 s1 = "1234
числа 9876";

 s2 = trim_copy_if(s1, is_digit);

 cout << "s1 = " << s1 << endl;

 cout << "s2 = " << s2 << endl;

 // Вложенные вызовы функций обрезки

 s1 = " ****Обрезка!*** ";

 s2 = trim_copy_if(trim_copy(s1), is_any_of("*"));

 cout << "s1 = " << s1 << endl;

 cout << "s2 = " << s2 << endl;

}

Пример 4.5 демонстрирует, как использовать функции обрезки строк Boost. Обычно способ их использования понятен из их названия, так что я не буду вдаваться в описания более подробные, чем даны в табл. 4.1. Единственная функция, имеющаяся в этом примере и отсутствующая в таблице, — это

is_any_of
. Это шаблон функции, который возвращает объект функции-предиката, используемый функциями серии
trim_if
. Она используется, когда требуется обрезать набор символов. Также есть аналогичная функция классификации, которая называется
is_from_range
и принимает два аргумента и возвращает унарный предикат, который возвращает истину, когда символ находится в заданном диапазоне. Например, чтобы обрезать в строке символы с
а
до
d
, требуется сделать что-то, похожее на следующее.

s1 = "abcdXXXabcd";

trim_if(s1, is_from_range('a', 'd'));

cout << "s1 = " << s1 << endl; // Теперь s1 = XXX

Заметьте, что эта конструкция чувствительна к регистру, так как диапазон от

а
до
d
не включает заглавных версий этих букв.

4.3. Хранение строк в последовательности

Проблема

Требуется сохранить набор строк в виде последовательности, которая ведет себя как массив.

Решение

Для хранения строк в виде массива используйте

vector
. Пример 4.6 показывает простой образец.

Пример 4 6. Хранение строк в векторе

#include <string>

#include <vector>

#include <iostream>

using namespace std;

int main {

 vector<string> v;

 string s = "one";

 v.push_back(s);

 s = "two";

 v.push_back(s);

 s = "three";

 v.push_back(s);

 for (int i = 0; i < v.size; ++i) {

cout << v[i] << "\n";

 }

}

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

Обсуждение

vector
— это динамическая последовательность объектов, которая предоставляет произвольный доступ с помощью оператора в стиле массивов
operator[]
. Метод
push_back
при помощи копирующего конструктора копирует свой аргумент, добавляет копию в последний элемент вектора и увеличивает его размер на единицу.
pop_back
выполняет обратную операцию, удаляя последний элемент. Вставка и удаление элементов в конце вектора занимает постоянное время, а время вставки и удаления элементов в середине вектора линейно зависит от его размера. Это основы векторов. Кроме этого, они умеют еще много чего.

В большинстве случаев

vector
должен быть первым выбором вместо массива в стиле С. Во-первых, их размеры изменяются динамически, что означает, что эти размеры увеличиваются по мере необходимости. Не требуется проводить каких-либо исследований для выбора оптимального размера статического массива, как в случае с массивами С, — vector растет по мере надобности, а при необходимости может быть увеличен или уменьшен вручную. Во-вторых,
vector
при использовании метода
at
(но не при использовании
operator[]
) предлагает проверку границ, так что при ссылке на несуществующий индекс программа не обрушится и не продолжит выполнение с неверными данными. Посмотрите на пример 4.7, Он показывает, как работать с индексами, выходящими за границы массива.

Поделиться с друзьями: