Выбрать главу

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

Как и в рецепте 4.6, превращение join в общий шаблон функции очень просто. Все, что требуется сделать, — это изменить заголовок, параметризовав тип символов, как здесь:

template<typename T>

void join(const std::vector<std::basic_string<T> >& v, T c,

 std::basic_string<T>& s)

Но vector может оказаться не единственным возможным входом функции. Вам может потребоваться объединить строки в стиле С. Класс string C++ предпочтительнее строк в стиле С, так что если возникает такая задача, объединяйте их в C++ string. После этого всегда можно получить версию С, вызвав метод string c_str, который возвращает указатель const на завершающийся нулем массив символов.

Пример 4.14 предлагает общую версию join, которая объединяет массив символов в string. Так как новая общая версия параметризована по типу символов, она будет работать как для массивов узких, так и для массивов широких символов.

Пример 4.14 Объединение строк в стиле C

#include <string>

#include <iostream>

const static int MAGIC_NUMBER = 4;

template<typename T>

void join(T* arr[], size_t n, T c, std::basic_string<T>& s) {

 s.clear();

 for (int i = 0; i < n; ++i) {

  if (arr[i] != NULL)

   s += arr[i];

  if (i < n-1) s += c;

 }

}

int main() {

 std::wstring ws;

 wchar_t* arr[MAGIC_NUMBER];

 arr[0] = L"you";

 arr[1] = L"ate";

 arr[2] = L"my";

 arr[3] = L"breakfast";

 join(arr, MAGIC_NUMBER, L'/', ws);

}

4.9. Поиск в строках

Проблема

Требуется выполнить поиск в строке. Это может быть поиск одного символа, другой строки или одного из (или одного не из) неупорядоченного набора символов. И по каким-либо причинам требуется выполнять поиск в определенном порядке, например первое или последнее вхождение или первое или последнее вхождения относительно какого- либо положения в строке.

Решение

Используйте один из методов «find» из basic_string. Почти все методы поиска начинаются со слова «find», и их имена говорят достаточно о том, что они делают. Пример 4.15 показывает, как работают некоторые из этих методов поиска.

Пример 4.15. Поиск строк

#include <string>

#include <iostream>

int main() {

 std::string s = "Charles Darwin";

 std::cout << s.find("ar") << '\n'; // Поиск от

                                    // начала

 std::cout << s.rfind("ar") << "\n"; // Поиск с конца

 std::cout << s.find_first_of("swi") // Найти первое вхождение одного

  << '\n'; // из этих символов

 std::cout << s.find_first_not_of("Charles") // Найти первое,

  << '\n';                                   // что не входит в этот

                                             // набор

 std::cout << s.find_last_of("abg") << '\n'; // Найти первое вхождение любого

                                             // из этих символов,

                                             // начиная с конца

 std::cout << s.find_last_not_of("aDinrw") // Найти первое,

  << '\n';                                 // что не входит в этот

                                           // набор, начиная с конца

}

Все эти методы поиска обсуждаются более подробно в разделе «Обсуждение».

Обсуждение

Имеется шесть различных методов для поиска в строках, каждый из которых предоставляет четыре перегруженных варианта. Эти перегрузки позволяют использовать либо параметр basic_string, либо charT* (charT — это символьный тип). Каждый имеет параметр pos типа basic_string::size_type, который позволяет указать индекс, с которого следует начать поиск, и есть перегрузка с параметром n типа size_type, который позволяет выполнить поиск только n символов из набора.

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

Табл. 4.2. Методы для поиска строк

Метод Описание
size_type find(const basic_string& str, size_type pos = 0) const; Возвращает индекс первого вхождения символа или подстроки начиная с начала или индекса, указанного в параметре pos.
size_type find (const charT* s, size_type pos, size_type n) const; size_type find (const charT* s, size_type pos = 0) const; size_type find(charT c, size_type pos = 0) const; Если указан n, то при поиске используются первые n символов целевой строки
size_type rfind(...) Находит первое вхождение символа или подстроки, начиная с конца строки и двигаясь к ее началу. Другими словами делает то же, что и find, но начинает поиск с конца строки
size_type find_first_of(...) Находит первое вхождение любого символа из набора, переданного как basic_string или указатель на символы. Если указан n, то ищутся только первые n символов используемого набора
size_type find_last_of(...) Находит последнее вхождение любого символа из набора, переданного как basic_string или указатель на символы. Если указан n, то ищутся только первые n символов используемого набора
size_type find_first_not_of(...) Находит первое вхождение любого символа, не входящего в набор, переданный как basic_string или указатель на символы. Если указан n, то принимаются во внимание только первые n символов используемого набора
size_type find_last_not_of(...) Находит последнее вхождение любого символа, не входящего в набор, переданный как basic_string или указатель на символы. Если указан n, то принимаются во внимание только первые n символов используемого набора