C++. Сборник рецептов
Шрифт:
std::string s = "There was a group named Kiss in the 70s";
std::string::iterator p =
std::adjacent_find(s.begin, s.end);
Результатом будет итератор, указывающий на первый из двух смежных элементов.
Если вам требуется написать собственный алгоритм работы со строками, не используйте
basic_string
так, как это делается со строками в стиле С, используя для доступа к элементам operator[]
. Используйте существующие методы. Каждая функция поиска принимает параметр size_type
, указывающий индекс, с которого должен начаться
Пример 4.16. Подсчет уникальных символов
#include <string>
#include <iostream>
template<typename T>
int countUnique(const std::basic_string<T>& s) {
using std::basic_string;
basic_string<T> chars;
for (typename basic_string<T>::const_iterator p = s.begin;
p != s.end; ++p) {
if (chars.find(*p) == basic.string<T>::npos)
chars += *p;
}
return(chars.length);
}
int main {
std: :string s = "Abracadabra'";
std::cout << countUnique(s) << '\n';
}
Функции поиска очень часто оказываются полезными. Когда требуется найти что- либо в строке типа
string
, они должны быть первым, что следует использовать. 4.10. Поиск n-го вхождения подстроки
Проблема
Имея источник
source
и шаблон pattern
типа string
, требуется найти n
– е вхождение pattern
в source
. Решение
Для поиска последовательных вхождений искомой подстроки используйте метод
find
. Пример 4.17 содержит простую функцию nthSubstr
. Пример 4.17. Поиск n-го вхождения подстроки
#include <string>
#include <iostream>
using namespace std;
int nthSubstr(int n, const strings s,
const strings p) {
string::size_type i = s.find(p); // Найти первое вхождение
int j;
for (j = 1; j < n && i != string::npos; ++j)
i = s.find(p, i+1); // Найти следующее вхождение
if (j == n) return(i);
else return(-1);
}
int main (
string s = "the wind, the sea, the sky, the trees";
string p = "the";
cout << nthSubstr(1, s, p) << '\n';
cout << nthSubstr(2, s, p) << '\n';
cout << nthSubstr(5, s, p) << '\n';
}
Обсуждение
В
функциюnthSubstr
, имеющую вид, показанный в примере 4.17, можно внести пару улучшений. Во-первых, ее можно сделать общей, сделав из нее вместо обычной функции шаблон функции. Во-вторых, можно добавить параметр, позволяющий учитывать подстроки, которые перекрываются друг с другом. Под перекрывающимися подстроками я понимаю такие, у которых начало строки соответствует части конца такой же строки, как в строке «abracadabra», где последние четыре символа такие же, как и первые четыре. Это демонстрируется в примере 4.18. Пример 4.18. Улучшенная версия nthSubstr
#include <string>
#include <iostream>
using namespace std;
template<typename T>
int nthSubstrg(int n, const basic_string<T>& s,
const basic_string<T>& p, bool repeats = false) {
string::size_type i = s.find(p);
string::size_type adv = (repeats) ? 1 : p.length;
int j;
for (j = 1; j < n && i != basic_string<T>::npos; ++j)
i = s.find(p, i+adv);
if (j == n)
return(i);
else
return(-1);
}
int main {
string s = AGATGCCATATATATACGATATCCTTA";
string p = "ATAT";
cout << p << " без повторений встречается в позиции "
<< nthSubstrg(3, s, p) << '\n';
cout << p << " с повторениями встречается в позиции "
<< nthSubstrg(3, s, p, true) << '\n';
}
Вывод для строк, использованных в примере 4.18, выглядит так.
ATAT без повторений встречается в позиции 18
ATAT с повторениями встречается в позиции 11
Смотри также
Рецепт 4.9.
4.11. Удаление подстроки из строки
Проблема
Требуется удалить из строки подстроку.
Решение
Используйте методы
basic_string find
, erase
и length
: std::string t = "Banana Republic";
std::string s = "nana";
std::string::size_type i = t.find(s);
if (i != std::string::npos) t.erase(i, s.length);
Этот код удаляет
s.length
элементов, начиная с индекса, по которому find
находит первое вхождение подстроки.
Поделиться с друзьями: