для различных типов символов потому, что не существует общей функции
toupper
, преобразующей регистр символов (при условии, что не используются возможности заголовочного файла
<locale>
, который
я описываю ниже). Две простые функции, как приведенные выше, выполняют всю работу.
Однако есть и другой способ выполнить эту задачу, и фактором, оказывающим влияние на выбор этого способа, является необходимость использовать явные локали. Следующие версии
toUpper
и
toLower
преобразуют регистр строк независимо от типа их символов, но при условии, что указанная локаль (а по умолчанию текущая) поддерживает преобразование регистра для данного типа символов.
template<typename С>
void toUpper2(basic_string<C>& s, const locale& loc = locale) {
typename basic_string<C>::iterator p;
for (p = s.begin; p ! = s.end; ++p) {
*p = use_facet<ctype<C> >(loc).toupper(*p);
}
}
template<typename C>
void tolower2(basic_string<C>& s, const locale& loc = locale) {
typename basic_string<C>::iterator p;
for (p = s.begin, p ! = s.end(++p) {
*p = use_facet<ctype<C> >(loc).tolower(*p);
}
}
Строки, выделенные жирным, выполняют всю работу. Функционально они работают точно так же, как и функции для верхнего и нижнего регистров, использованные в примере 4.20, за исключением того, что они используют для этого возможности интернационализации из заголовочного файла
<locale>
. За более подробным обсуждением локалей и возможностей интернационализации обратитесь к главе 13.
4.13. Выполнение сравнения строк без учета регистра
Проблема
Имеются две строки и требуется узнать, не равны ли они, не учитывая регистр их символов. Например, «cat» не равно «dog», но «Cat» должна быть равна «cat», «CAT» или «caT».
Решение
Сравните строки, используя стандартный алгоритм
equal
(определенный в
<algorithm>
), и создайте свою собственную функцию сравнения, которая использует для сравнения версий с верхним регистром символов функцию
toupper
из
<cctype>
(или
towupper
из
<cwctype>
для широких символов). Пример 4.21 показывает обобщенное решение. Также он демонстрирует использование и гибкость STL. За полным объяснением обратитесь к обсуждению ниже.
Пример 4.21. Сравнение строк без учета регистра
1 #include <string>
2 #include <iostream>
3 #include <algorithm>
4 #include <cctype>
5 #include <cwctype>
6
7 using namespace std;
8
9 inline bool caseInsCharCompareN(char a, char b) {
10 return(toupper(a) == toupper(b));
11 }
12
13 inline bool caseInsCharCompareW(wchar_t a, wchar_t b) {
частью сравнения строк без учета регистра является проверка равенства каждой соответствующей пары символов, так что давайте начнем обсуждение с него. Так как я в этом подходе использую стандартный алгоритм
equal
, но хочу использовать свой особый критерий сравнения, я должен создать отдельную функцию, выполняющую это сравнение.
Строки 9-15 примера 4.21 определяют функции, которые выполняют сравнение —
caseInsCharCompareN
и
caseInsCharCompareW
. Они для преобразования символов к верхнему регистру используют
toupper
и
towupper
, а затем сообщают, равны ли они.
После написания этих функций сравнения настает время использовать стандартный алгоритм, выполняющий применение этих функций сравнения к произвольной последовательности символов. Именно это делают функции
caseInsCompare
, определенные в строках 17-25 и использующие
equal
. Здесь сделано две перегрузки — по одной для каждого типа интересующих нас символов. Они обе делают одно и то же, но каждая использует для своего типа символов соответствующую функцию сравнения. Для этого примера я перегрузил две обычные функции, но этот же эффект может быть достигнут и с помощью шаблонов. Для пояснений обратитесь к врезке «Следует ли использовать шаблон?».