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 не включает заглавных версий этих букв.

<p>4.3. Хранение строк в последовательности</p>Проблема

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

Решение

Для хранения строк в виде массива используйте vector. Пример 4.6 показывает простой образец.

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

#include

#include

#include

using namespace std;

int main() {

 vector 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, Он показывает, как работать с индексами, выходящими за границы массива.

Пример 4.7. Проверка границ для векторов

#include

#include

#include

using namespace std;

int main() {

 char carr[] = {'a', 'b', 'c', 'd', 'e'};

 cout << carr[100000] << '\n'; // Оп, кто знает, что дальше

                               // произойдет

 vector v;

 v.push_back('a');

 v.push_back('b');

 v.push_back('c');

 v.push_back('d');

 v push_back('e');

 try {

  cout << v.at(10000) << "\n"; // at проверяет границы и выбрасывает

 } catch(out_of_range& е) {    // out_of_range, если произошел выход за них

  cerr << e.what() << '\n';

 }

}

Перейти на страницу:

Похожие книги