Пусть n — это расстояние между first1 и last1, или, другими словами, длина первого диапазона. equal возвращает true, если первые n элементов обеих последовательностей равны. Это означает, что если есть две последовательности, где первые n элементов равны, но вторая содержит больше чем n элементов, то equal вернет true. Чтобы избежать такой ошибки требуется проверять размер.

Эту логику не обязательно инкапсулировать в функцию. Ваш или клиентский код может просто вызвать алгоритм напрямую, но проще запомнить и написать такое:

if (caseInsCompare(s1, s2)) { // они равны, делаем что-нибудь

чем такое:

if ((s1.size() == s2.size()) &&

std::equal(s1.begin(), s1.end(s2.begin(), caseInsCharCompare)) {

 // они равны, делаем что-нибудь

когда требуется выполнить сравнение строк без учета регистра.

<p>4.14. Выполнение поиска строк без учета регистра</p>Проблема

Требуется найти в строке подстроку, не учитывая разницу в регистре.

Решение

Используйте стандартные алгоритмы transform и search, определенные в , а также свои собственные функции сравнения символов, аналогичные уже показанным. Пример 4.22 показывает, как это делается.

Пример 4.22. Поиск строк без учета регистра

#include

#include

#include

#include

#include

using namespace std;

inline bool caseInsCharCompSingle(char a. char b) {

 return(toupper(a) == b);

}

string::const_iterator caseInsFind(string& s, const string& p) {

 string tmp;

 transform(p.begin( ), p.end(), // Преобразуем шаблон

  back_inserter(tmp),           // к верхнему регистру

  toupper);

 return(search(s.begin(), s.end(), // Возвращаем итератор.

  tmp.begin(), tmp.end(),          // возвращаемый из

  caseInsCharCompSingle));         // search

}

int main() {

 string s = "row, row, row, your boat";

 string p = "YOUR";

 string::const_iterator ir = caseInsFind(s, p);

 if (it != s.end()) {

  cout << "Нашли!\n;

 }

}

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

Обсуждение

Пример 4.22 демонстрирует обычный ход действий при работе со стандартными алгоритмами. Создайте функцию, которая выполняет работу, а затем подключите ее как объект функции к наиболее подходящему алгоритму. Здесь работу выполняет функция charInsCharCompSingle, но в отличие от примера 4.21 эта функция сравнения символов переводит к верхнему регистру только первый аргумент. Это сделано потому, что немного далее в caseInsFind я перед использованием строки шаблона в поиске преобразую ее к верхнему регистру полностью и тем самым избегаю многократного преобразования символов строки шаблона к верхнему регистру.

После того как функция сравнения будет готова, используйте для поиска стандартные алгоритмы transform и search. transform используется для преобразования к верхнему регистру всего шаблона (но не целевой строки). После этого используйте для поиска места вхождения подстроки search совместно с функцией сравнения.

Помните, что стандартные алгоритмы работают с последовательностями, а не со строками. Это общие алгоритмы, которые в основном (но не только) работают со стандартными контейнерами, но не делают никаких предположений о содержимом этих контейнеров. Все стандартные алгоритмы требуют передачи им функции сравнения (а в случае их отсутствия используют операторы по умолчанию), которые тем или иным способом сравнивают два элемента и возвращают bool, указывающий, дало ли сравнение истину или ложь.

В примере 4.22 есть одна вещь, которая выглядит странно. Вы видите, что caseInsCompare возвращает const_iterator, как в

string::const_iterator caseInsFind(const string& s,

 const string& p)

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

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