16

17 bool caseInsCompare(const string& s1, const string& s2) {

18  return((s1.size() == s2.size()) &&

19   equal(s1.begin(), s1.end(), s2.begin(), caseInsCharCompareN));

20 }

21

22 bool caseInsCompare(const wstring& s1, const wstring& s2) {

23  return((s1.size() == s2.size())

24  equal(s1.begin(), s1.end(), s2.begin(), caseInsCharCompareW));

25 }

26

27 int main() {

28  string s1 = 'In the BEGINNING...';

29  string s2 = 'In the beginning...';

30  wstring ws1 = L'The END';

31  wstring ws2 = L'the end';

32

33  if (caseInsCompare(s1, s2))

34   cout << 'Equal! ';

35

36  if (caseInsCompare(ws1, ws2))

37   cout << 'Equal! ';

38 }

Обсуждение

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

Строки 9-15 примера 4.21 определяют функции, которые выполняют сравнение — caseInsCharCompareN и caseInsCharCompareW. Они для преобразования символов к верхнему регистру используют toupper и towupper, а затем сообщают, равны ли они.

После написания этих функций сравнения настает время использовать стандартный алгоритм, выполняющий применение этих функций сравнения к произвольной последовательности символов. Именно это делают функции caseInsCompare, определенные в строках 17-25 и использующие equal. Здесь сделано две перегрузки — по одной для каждого типа интересующих нас символов. Они обе делают одно и то же, но каждая использует для своего типа символов соответствующую функцию сравнения. Для этого примера я перегрузил две обычные функции, но этот же эффект может быть достигнут и с помощью шаблонов. Для пояснений обратитесь к врезке «Следует ли использовать шаблон?».

equal сравнивает две последовательности на равенство. Имеется две версии: одна использует operator==, а другая использует переданный ей функциональный объект двоичного предиката (т.е. такой, который принимает два аргумента и возвращает bool). В примере 4.21 caseInsCharCompareN и W — это функции двоичного предиката.

Но это не всё, что требуется сделать; также требуется сравнить размеры. Рассмотрим объявление equal.

template<typename InputIterator1, typename InputIterator2,

 typename BinaryPredicate>

bool equal(InputIterator1 first, InputIterator1 last1,

 InputIterator2 first2, BinaryPredicate pred);

Пусть 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<char>)) {

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

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

4.14. Выполнение поиска строк без учета регистра

Проблема

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

Решение

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

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

#include <string>

#include <iostream>

#include <algorithm>

#include <iterator>

#include <cctype>

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

}

Добавить отзыв
ВСЕ ОТЗЫВЫ О КНИГЕ В ИЗБРАННОЕ

0

Вы можете отметить интересные вам фрагменты текста, которые будут доступны по уникальной ссылке в адресной строке браузера.

Отметить Добавить цитату