}
Этот код производит следующий вывод.
s = SHAZAM
ws = WHAM
s = shazam
ws = wham
Кто-то может подумать, что стандартный класс string
содержит метод, преобразующий всю строку к верхнему или нижнему регистру, но на самом деле это не так. Если требуется преобразовать строку символов к верхнему или нижнему регистру, это требуется делать самостоятельно.
Неудивительно, что имеется несколько способов преобразования регистра строки (и когда я говорю «строки», то имею в виду последовательность символов как узких, так и широких). Простейшим способом сделать это является использование одной из четырех функций преобразования символов toupper
, towupper
, tolower
и towlower
. Первая форма этих функций работает с узкими символами, а вторая форма (с дополнительной буквой w
) является ее эквивалентом для широких символов.
Каждая из этих функций преобразует регистр символа, используя текущие правила локали для преобразования регистра. Верхний и нижний регистры зависят от символов, используемых в текущей локали. Некоторые символы не имеют верхнего или нижнего регистра, и в этом случае указанные функции возвращают переданный им символ. За дополнительной информацией о локалях обратитесь к главе 13. Возможности C++ по работе с различными локалями довольно сложны, и я не могут уделить им сейчас достаточно места.
Выполнение собственно преобразования символов просто. Рассмотрим функцию toUpper
из примера 4.20.
void toUpper(basic_string<char>& s) {
for (basic_string<char>::iterator p = s.begin();
p != s.end(); ++p) {
*p = toupper(*p);
}
}
Строка, выделенная жирным, выполняет всю работу. Версия для широких символов почти идентична.
void toUpper(basic_string<wchar_t>& s) {
for (basic_string<wchar_t>::iterator p = s.begin();
p != s.end(); ++p) {
*p = towupper(*p);
}
}
Я перегрузил toupper
для различных типов символов потому, что не существует общей функции 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. За полным объяснением обратитесь к обсуждению ниже.
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) {
14 return(towupper(a) == towupper(b));
15 }