Д. Стефенс - C++. Сборник рецептов
- Название:C++. Сборник рецептов
- Автор:
- Жанр:
- Издательство:КУДИЦ-ПРЕСС
- Год:2007
- Город:Москва
- ISBN:5-91136-030-6
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Д. Стефенс - C++. Сборник рецептов краткое содержание
Данная книга написана экспертами по C++ и содержит готовые рецепты решения каждодневных задач для программистов на С++. Один из авторов является создателем библиотеки Boost Iostreams и нескольких других библиотек C++ с открытым исходным кодом. В книге затрагивается множество тем, вот лишь некоторые из них: работа с датой и временем; потоковый ввод/вывод; обработка исключений; работа с классами и объектами; сборка приложений; синтаксический анализ XML-документов; программирование математических задач. Читатель сможет использовать готовые решения, а сэкономленное время и усилия направить на решение конкретных задач.
C++. Сборник рецептов - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
wcout << "ws = " << ws << endl;
}
Этот код производит следующий вывод.
s = SHAZAM
ws = WHAM
s = shazam
ws = wham
Кто-то может подумать, что стандартный класс string
содержит метод, преобразующий всю строку к верхнему или нижнему регистру, но на самом деле это не так. Если требуется преобразовать строку символов к верхнему или нижнему регистру, это требуется делать самостоятельно.
Неудивительно, что имеется несколько способов преобразования регистра строки (и когда я говорю «строки», то имею в виду последовательность символов как узких, так и широких). Простейшим способом сделать это является использование одной из четырех функций преобразования символов toupper
, towupper
, tolower
и towlower
. Первая форма этих функций работает с узкими символами, а вторая форма (с дополнительной буквой w
) является ее эквивалентом для широких символов.
Каждая из этих функций преобразует регистр символа, используя текущие правила локали для преобразования регистра. Верхний и нижний регистры зависят от символов, используемых в текущей локали. Некоторые символы не имеют верхнего или нижнего регистра, и в этом случае указанные функции возвращают переданный им символ. За дополнительной информацией о локалях обратитесь к главе 13. Возможности C++ по работе с различными локалями довольно сложны, и я не могут уделить им сейчас достаточно места.
Выполнение собственно преобразования символов просто. Рассмотрим функцию toUpper
из примера 4.20.
void toUpper(basic_string& s) {
for (basic_string::iterator p = s.begin();
p != s.end(); ++p) {
*p = toupper(*p);
}
}
Строка, выделенная жирным, выполняет всю работу. Версия для широких символов почти идентична.
void toUpper(basic_string& s) {
for (basic_string::iterator p = s.begin();
p != s.end(); ++p) {
*p = towupper(*p);
}
}
Я перегрузил toupper
для различных типов символов потому, что не существует общей функции toupper
, преобразующей регистр символов (при условии, что не используются возможности заголовочного файла , который я описываю ниже). Две простые функции, как приведенные выше, выполняют всю работу.
Однако есть и другой способ выполнить эту задачу, и фактором, оказывающим влияние на выбор этого способа, является необходимость использовать явные локали. Следующие версии toUpper
и toLower
преобразуют регистр строк независимо от типа их символов, но при условии, что указанная локаль (а по умолчанию текущая) поддерживает преобразование регистра для данного типа символов.
template
void toUpper2(basic_string& s, const locale& loc = locale()) {
typename basic_string::iterator p;
for (p = s.begin(); p ! = s.end(); ++p) {
*p = use_facet >(loc).toupper(*p);
}
}
template
void tolower2(basic_string& s, const locale& loc = locale()) {
typename basic_string::iterator p;
for (p = s.begin(), p ! = s.end(++p) {
*p = use_facet >(loc).tolower(*p);
}
}
Строки, выделенные жирным, выполняют всю работу. Функционально они работают точно так же, как и функции для верхнего и нижнего регистров, использованные в примере 4.20, за исключением того, что они используют для этого возможности интернационализации из заголовочного файла . За более подробным обсуждением локалей и возможностей интернационализации обратитесь к главе 13.
4.13. Выполнение сравнения строк без учета регистра
Имеются две строки и требуется узнать, не равны ли они, не учитывая регистр их символов. Например, «cat» не равно «dog», но «Cat» должна быть равна «cat», «CAT» или «caT».
Сравните строки, используя стандартный алгоритм equal
(определенный в ), и создайте свою собственную функцию сравнения, которая использует для сравнения версий с верхним регистром символов функцию toupper
из (или towupper
из для широких символов). Пример 4.21 показывает обобщенное решение. Также он демонстрирует использование и гибкость STL. За полным объяснением обратитесь к обсуждению ниже.
Пример 4.21. Сравнение строк без учета регистра
1 #include
2 #include
3 #include
4 #include
5 #include
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 }
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!\n";
35
36 if (caseInsCompare(ws1, ws2))
37 cout << "Equal!\n";
38 }
Критической частью сравнения строк без учета регистра является проверка равенства каждой соответствующей пары символов, так что давайте начнем обсуждение с него. Так как я в этом подходе использую стандартный алгоритм equal
, но хочу использовать свой особый критерий сравнения, я должен создать отдельную функцию, выполняющую это сравнение.
Строки 9-15 примера 4.21 определяют функции, которые выполняют сравнение — caseInsCharCompareN
и caseInsCharCompareW
. Они для преобразования символов к верхнему регистру используют toupper
и towupper
, а затем сообщают, равны ли они.
После написания этих функций сравнения настает время использовать стандартный алгоритм, выполняющий применение этих функций сравнения к произвольной последовательности символов. Именно это делают функции caseInsCompare
, определенные в строках 17-25 и использующие equal
. Здесь сделано две перегрузки — по одной для каждого типа интересующих нас символов. Они обе делают одно и то же, но каждая использует для своего типа символов соответствующую функцию сравнения. Для этого примера я перегрузил две обычные функции, но этот же эффект может быть достигнут и с помощью шаблонов. Для пояснений обратитесь к врезке «Следует ли использовать шаблон?».
equal
сравнивает две последовательности на равенство. Имеется две версии: одна использует operator==
, а другая использует переданный ей функциональный объект двоичного предиката (т.е. такой, который принимает два аргумента и возвращает bool
). В примере 4.21 caseInsCharCompareN
и W
— это функции двоичного предиката.
Интервал:
Закладка: