if (p != v.end() - 1) s += c;
}
}
int main() {
vector
vector
string s;
v.push_back(string("fее"));
v.push_back(string("fi"));
v.push_back(string("foe"));
v.push_back(string("fum"));
join(v, '/', s);
cout << s << '\n';
}
Пример 4.13 содержит одну методику, которая несколько отличается от предыдущие примеров. Посмотрите на эту строку.
for (vector
Предыдущие примеры работы со строками использовали iterator'ы без части «const», но здесь без этого не обойтись, так как v объявлен как ссылка на объект const. Если имеется объект контейнера const, то для доступа к его элементам можно использовать только const_iterator. Это так потому, что простой iterator позволяет записывать в объект, на который он указывает, что, конечно, нельзя делать в случае с объектами контейнера типа const.
v объявлен как const по двум причинам. Во-первых, я знаю, что я не собираюсь изменять его содержимое, так что я хочу, чтобы компилятор выдал сообщение об ошибке, если это произойдет. Компилятор гораздо лучше меня в деле поиска таких вещей, особенно когда к такому присвоению приводит тонкая семантическая или синтаксическая ошибка. Во-вторых, я хочу показать пользователям этой функции, что я ничего не делаю с их контейнером, и const — это великолепный способ сделать это. Теперь я просто должен создать обобщенную версию, которая работает с различными типами символов.
Как и в рецепте 4.6, превращение join в общий шаблон функции очень просто. Все, что требуется сделать, — это изменить заголовок, параметризовав тип символов, как здесь:
template
void join(const std::vector
std::basic_string
Но vector может оказаться не единственным возможным входом функции. Вам может потребоваться объединить строки в стиле С. Класс string C++ предпочтительнее строк в стиле С, так что если возникает такая задача, объединяйте их в C++ string. После этого всегда можно получить версию С, вызвав метод string c_str, который возвращает указатель const на завершающийся нулем массив символов.
Пример 4.14 предлагает общую версию join, которая объединяет массив символов в string. Так как новая общая версия параметризована по типу символов, она будет работать как для массивов узких, так и для массивов широких символов.
#include
#include
const static int MAGIC_NUMBER = 4;
template
void join(T* arr[], size_t n, T c, std::basic_string
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 показывает, как работают некоторые из этих методов поиска.
#include
#include
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'; // что не входит в этот
// набор