Широкие символы и L-строки

Помимо обычных символов, имеющих тип char, язык C++ поддерживает широкие символы, имеющие тип wchar_t. Строки, состоящие из широких символов, мы будем называть L-строками. Для более удобной работы с L-строками можно воспользоваться шаблонным классом wstring.

Прежде чем мы начнем рассматривать широкие символы и L-строки, попробуйте запустить этот код и сравните результат:

// #include <iostream>
// #include <cwchar>
wchar_t str[] = L"строка string";
for (int i = 0, len = (int)std::wcslen(str); i < len; ++i) {
   std::wcout << (unsigned)str[i] << ' ';
}
std::wcout << std::endl;
// 1089 1090 1088 1086 1082 1072 32 115 116 114 105 110 103

Если получили точно такие же числа, то можно начать изучение. Если же числа отличаются, то следует проверить кодировку файла с программой — она должна быть windows-1251. Хотя на самом деле кодировка файлов по умолчанию в MinGW должна быть UTF-8, но в этом случае вы не сможете работать с обычными строками, т. к. русские буквы в кодировке UTF-8 кодируются двумя байтами, а не одним. Чтобы избежать проблем с русскими буквами, для файлов мы используем кодировку windows-1251, а не UTF-8.

Если при компиляции получили эту ошибку:

error: converting to execution character set: Illegal byte sequence

то следует явным образом указать кодировку файла с программой и кодировку символов в C-строке. Для этого в MinGW предназначены следующие флаги:

  • -finput-charset — задает кодировку файла с программой;
  • -fexec-charset — определяет кодировку символов в C-строке;
  • -fwide-exec-charset — задает кодировку символов в L-строке.

Команда компиляции в командной строке должна выглядеть так:

C:\book>g++ -Wall -Wconversion -O3 -finput-charset=cp1251 
            -fexec-charset=cp1251 -o test.exe test.cpp

C:\book>test.exe
1089 1090 1088 1086 1082 1072 32 115 116 114 105 110 103

Если получили следующую ошибку:

cc1.exe: error: no iconv implementation, cannot convert from cp1251 to UTF-8

то нужно либо сменить компилятор, т. к. он собран без поддержки библиотеки iconv, либо использовать для файлов кодировку UTF-8 и не указывать флаги -finput-charset и -fexec-charset при компиляции.

Чтобы задать флаги в Eclipse, в свойствах проекта из списка слева выбираем пункт C/C++ Build | Settings. На отобразившейся вкладке из списка Configuration выбираем пункт All configurations, а затем на вкладке Tool Settings из списка выбираем пункт GCC C++ Compiler | Miscellaneous (см. рис. 1.35). В поле Other flags через пробел к имеющемуся значению добавляем следующие инструкции:

-finput-charset=cp1251 -fexec-charset=cp1251

Содержимое поля Other flags после изменения должно быть таким:

-c -fmessage-length=0 -finput-charset=cp1251 -fexec-charset=cp1251

Эти флаги должны быть в окне Console при компиляции в Eclipse:

20:48:14 **** Incremental Build of configuration Debug for project
Test64 ****
Info: Internal Builder is used for build
g++ -O0 -g3 -Wall -Wconversion -c -fmessage-length=0 
-finput-charset=cp1251 -fexec-charset=cp1251 -o "src\\Test64.o" 
"..\\src\\Test64.cpp" 
g++ -o Test64.exe "src\\Test64.o" 

20:48:15 Build Finished. 0 errors, 0 warnings. (took 782ms)

Объявление и инициализация широкого символа

Широкие символы объявляются с помощью типа wchar_t. Выведем диапазон допустимых значений:

// #include <cwchar>
std::wcout << WCHAR_MIN << std::endl;                   // 0
std::wcout << WCHAR_MAX << std::endl;                   // 65535
// #include <limits>
wchar_t min = std::numeric_limits<wchar_t>::min();
wchar_t max = std::numeric_limits<wchar_t>::max();
std::wcout << static_cast<unsigned>(min) << std::endl;  // 0
std::wcout << static_cast<unsigned>(max) << std::endl;  // 65535

Тип wchar_t занимает в памяти два байта. Обратите внимание: не следует рассчитывать, что при использовании другого компилятора тип wchar_t будет объявлен точно также. Для определения размера типа wchar_t всегда используйте оператор sizeof:

std::wcout << sizeof(wchar_t) << std::endl; // 2

Кроме того, существует тип wint_t:

typedef unsigned short wint_t;

Диапазон допустимых значений содержится в макросах WINT_MIN и WINT_MAX:

std::wcout << sizeof(wint_t) << std::endl;  // 2
// #include <stdint.h>
std::wcout << WINT_MIN << std::endl;        // 0
std::wcout << WINT_MAX << std::endl;        // 65535

Переменной, имеющей тип wchar_t, можно присвоить числовое значение (код символа) или указать символ внутри апострофов, перед которыми добавлена буква L. Внутри апострофов можно указать специальные символы, например, \n, \t и др. Пример объявления и инициализации широкого символа:

wchar_t ch1 = 1087, ch2 = L'п', ch3 = L'\u043F';
std::wcout << static_cast<unsigned>(ch1) << std::endl; // 1087
std::wcout << static_cast<unsigned>(ch2) << std::endl; // 1087
std::wcout << static_cast<unsigned>(ch3) << std::endl; // 1087

Коды первых 128 символов совпадают с кодами символов в кодировке ASCII (см. табл. 7.1). Коды русских букв приведены в табл. 8.1. Обратите внимание на то, что коды букв «ё» и «Ё» выпадают из последовательности кодов.

Учебник C++ (MinGW-W64)
Учебник C++ (MinGW-W64) в формате PDF

Помощь сайту

ЮMoney (Yandex-деньги): 410011140483022

ПАО Сбербанк:
Счет: 40817810855006152256
Реквизиты банка:
Наименование: СЕВЕРО-ЗАПАДНЫЙ БАНК ПАО СБЕРБАНК
Корреспондентский счет: 30101810500000000653
БИК: 044030653
КПП: 784243001
ОКПО: 09171401
ОКОНХ: 96130
Скриншот реквизитов