C++. Сборник рецептов - [67]

Шрифт
Интервал

к стандартным алгоритмам является тривиальным. Скажем, вам требуется найти первое вхождение двух одинаковых символов подряд. Для поиска двух одинаковых расположенных рядом («расположенных рядом» означает, что их позиции отличаются на один шаг итератора, т.е. >*iter == *(iter + 1)) символов в строке используйте шаблон функции >adjacent_find.

>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, который подсчитывает число уникальных символов в строке.

Пример 4.16. Подсчет уникальных символов

>#include

>#include


>template

>int countUnique(const std::basic_string& s) {

> using std::basic_string;

> basic_string chars;

> for (typename basic_string::const_iterator p = s.begin();

>  p != s.end(); ++p) {

>  if (chars.find(*p) == basic.string::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

>#include


>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

>#include


>using namespace std;


>template

>int nthSubstrg(int n, const basic_string& s,

> const basic_string& 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::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 находит первое вхождение подстроки.

Обсуждение

На практике встречается огромное количество вариаций на тему поиска и удаления подстрок. Например, может потребоваться удалить все вхождения подстроки, а не одно из них. Или только последнее. Или седьмое. Каждый раз действия будут одни и те же: найдите индекс начала шаблона, который требуется удалить, затем вызовите >erase для этого индекса и n последующих символов, где n — это длина строки шаблона. За описанием различных методов поиска подстрок обратитесь к рецепту 4.9.

Также велика вероятность, что вам потребуется сделать функцию удаления обобщенной, так чтобы ее можно было использовать с любыми типами символов. Пример 4.19 предлагает общую версию, которая удаляет все вхождения шаблона в строке.

Пример 4.19. Удаление всех подстрок из строки (обобщенная версия)

>#include


Рекомендуем почитать
Изучаем Java EE 7

Java Enterprise Edition (Java EE) остается одной из ведущих технологий и платформ на основе Java. Данная книга представляет собой логичное пошаговое руководство, в котором подробно описаны многие спецификации и эталонные реализации Java EE 7. Работа с ними продемонстрирована на практических примерах. В этом фундаментальном издании также используется новейшая версия инструмента GlassFish, предназначенного для развертывания и администрирования примеров кода. Книга написана ведущим специалистом по обработке запросов на спецификацию Java EE, членом наблюдательного совета организации Java Community Process (JCP)


Pro Git

Разработчику часто требуется много сторонних инструментов, чтобы создавать и поддерживать проект. Система Git — один из таких инструментов и используется для контроля промежуточных версий вашего приложения, позволяя вам исправлять ошибки, откатывать к старой версии, разрабатывать проект в команде и сливать его потом. В книге вы узнаете об основах работы с Git: установка, ключевые команды, gitHub и многое другое.В книге рассматриваются следующие темы:основы Git;ветвление в Git;Git на сервере;распределённый Git;GitHub;инструменты Git;настройка Git;Git и другие системы контроля версий.


Java 7

Рассмотрено все необходимое для разработки, компиляции, отладки и запуска приложений Java. Изложены практические приемы использования как традиционных, так и новейших конструкций объектно-ориентированного языка Java, графической библиотеки классов Swing, расширенной библиотеки Java 2D, работа со звуком, печать, способы русификации программ. Приведено полное описание нововведений Java SE 7: двоичная запись чисел, строковые варианты разветвлений, "ромбовидный оператор", NIO2, новые средства многопоточности и др.


Фундаментальные алгоритмы и структуры данных в Delphi

Книга "Фундаментальные алгоритмы и структуры данных в Delphi" представляет собой уникальное учебное и справочное пособие по наиболее распространенным алгоритмам манипулирования данными, которые зарекомендовали себя как надежные и проверенные многими поколениями программистов. По данным журнала "Delphi Informant" за 2002 год, эта книга была признана сообществом разработчиков прикладных приложений на Delphi как «самая лучшая книга по практическому применению всех версий Delphi».В книге подробно рассматриваются базовые понятия алгоритмов и основополагающие структуры данных, алгоритмы сортировки, поиска, хеширования, синтаксического разбора, сжатия данных, а также многие другие темы, тесно связанные с прикладным программированием.


Питон — модули, пакеты, классы, экземпляры

Python - объектно-ориентированный язык сверхвысокого уровня. Python, в отличии от Java, не требует исключительно объектной ориентированности, но классы в Python так просто изучить и так удобно использовать, что даже новые и неискушенные пользователи быстро переходят на ОО-подход.


Как пасти котов. Наставление для программистов, руководящих другими программистами

«Как пасти котов» – это книга о лидерстве и руководстве, о том, как первое совмещать со вторым. Это, если хотите, словарь трудных случаев управления IT-проектами. Программист подобен кошке, которая гуляет сама по себе. Так уж исторически сложилось. Именно поэтому так непросто быть руководителем команды разработчиков. Даже если вы еще месяц назад были блестящим и дисциплинированным программистом и вдруг оказались в роли менеджера, вряд ли вы знаете, с чего надо начать, какой выбрать стиль руководства, как нанимать и увольнять сотрудников, проводить совещания, добиваться своевременного выполнения задач.