Этот сайт использует cookies. Продолжение работы с сайтом означает, что Вы согласны!
Преобразование кодировок
При использовании L-строк все символы кодируются двумя байтами. Не следует рассматривать L-строку, как строку в какой-то кодировке, например, в UTF-16. Думайте об L-строке как о строке в абстрактной кодировке, позволяющей закодировать более 65 тысяч символов. Когда мы говорим о строке в какой-либо кодировке, то мы всегда говорим о C-строке. По умолчанию для проекта мы настроили для C-строк кодировку windows-1251.
Используя функции mbstowcs()
и wcstombs()
, которые мы рассмотрели в предыдущем разделе, можно преобразовать строку из одной однобайтовой кодировки в другую. Кодировка символов C-строки указывается с помощью локали. В этом случае L-строка используется как промежуточная стадия. Преобразуем строку из кодировки windows-1251 в кодировку windows-866 (листинг 8.3).
Листинг 8.3. Преобразование строки из кодировки windows-1251 в кодировку windows-866
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <clocale>
#include <cwchar>
#include <cstdlib>
#include <cstring>
#include <process.h>
int main() {
size_t count = 0;
char cp866[256] = {0};
wchar_t wstr[256] = {0};
char cp1251[] = "строка"; // Исходная строка (windows-1251)
for (int i = 0, len = (int)std::strlen(cp1251); i < len; ++i) {
std::cout << (int)cp1251[i] << ' ';
} // -15 -14 -16 -18 -22 -32
std::cout << std::endl;
// Преобразование C-строки в кодировке windows-1251 в L-строку
_wsetlocale(LC_ALL, L"Russian_Russia.1251");
count = std::mbstowcs(wstr, cp1251, 255);
if (count == (size_t)(-1)) {
std::cout << "Error 1" << std::endl;
exit(1);
}
for (int i = 0, len = (int)std::wcslen(wstr); i < len; ++i) {
std::cout << (int)wstr[i] << ' ';
} // 1089 1090 1088 1086 1082 1072
std::cout << std::endl;
// Преобразование L-строки в C-строку в кодировке windows-866
_wsetlocale(LC_ALL, L"Russian_Russia.866");
count = std::wcstombs(cp866, wstr, 255);
if (count == (size_t)(-1)) {
std::cout << "Error 2" << std::endl;
exit(1);
}
for (int i = 0, len = (int)std::strlen(cp866); i < len; ++i) {
std::cout << (int)cp866[i] << ' ';
} // -31 -30 -32 -82 -86 -96
std::cout << std::endl;
return 0;
}
Для преобразования кодировок в Windows можно воспользоваться следующими функциями из WinAPI (кодировки указаны для русской версии Windows):
CharToOemA()
— преобразует строкуsource
в кодировке windows-1251 в строкуdest
в кодировке windows-866. Прототип функции:
#include <windows.h> /* User32.lib */
WINBOOL CharToOemA(LPCSTR source, LPSTR dest);
CharToOemBuffA()
— преобразует строкуsource
в кодировке windows-1251 в строкуdest
в кодировке windows-866. Количество символов указывается в параметреlength
. Прототип функции:
#include <windows.h> /* User32.lib */
WINBOOL CharToOemBuffA(LPCSTR source, LPSTR dest, DWORD length);
OemToCharA()
— преобразует строкуsource
в кодировке windows-866 в строкуdest
в кодировке windows-1251. Прототип функции:
#include <windows.h> /* User32.lib */
WINBOOL OemToCharA(LPCSTR source, LPSTR dest);
OemToCharBuffA()
— преобразует строкуsource
в кодировке windows-866 в строкуdest
в кодировке windows-1251. Количество символов указывается в параметреlength
. Прототип функции:
#include <windows.h> /* User32.lib */
WINBOOL OemToCharBuffA(LPCSTR source, LPSTR dest, DWORD length);
Пример использования функций CharToOemA()
и OemToCharA()
приведен в листинге 8.4.
Листинг 8.4. Функции CharToOemA()
и OemToCharA()
#include <iostream>
#include <clocale>
#include <cstring>
#include <windows.h>
int main() {
std::setlocale(LC_ALL, "Russian_Russia.1251");
char cp866[256] = {0};
char cp1251[256] = {0};
char str[] = "строка"; // Исходная строка в кодировке windows-1251
// Преобразование windows-1251 в windows-866
CharToOemA(str, cp866);
for (int i = 0, len = (int)std::strlen(cp866); i < len; ++i) {
std::cout << (int)cp866[i] << ' ';
} // -31 -30 -32 -82 -86 -96
std::cout << std::endl;
// Преобразование windows-866 в windows-1251
OemToCharA(cp866, cp1251);
for (int i = 0, len = (int)std::strlen(cp1251); i < len; ++i) {
std::cout << (int)cp1251[i] << ' ';
} // -15 -14 -16 -18 -22 -32
std::cout << std::endl;
return 0;
}
Для преобразования кодировок в Windows можно также воспользоваться следующими функциями из WinAPI:
MultiByteToWideChar()
— преобразует C-строкуlpMultiByteStr
в L-строкуlpWideCharStr
. Прототип функции:
#include <windows.h> /* Kernel32.lib */
int MultiByteToWideChar(UINT codePage, DWORD dwFlags,
LPCCH lpMultiByteStr, int cbMultiByte,
LPWSTR lpWideCharStr, int cchWideChar);
Параметр codePage
задает кодировку C-строки. Примеры указания кодировки: 866
(для кодировки windows-866), 1251
(для windows-1251), 65001
или CP_UTF8
(для UTF-8), 1200
(для UTF-16LE), 1201
(для UTF-16BE), 12000
(для UTF-32LE) и 12001
(для UTF-32BE). Полный список кодировок смотрите в документации.
В параметре dwFlags
можно указать различные флаги (MB_PRECOMPOSED
(1
), MB_ERR_INVALID_CHARS
(8
), MB_COMPOSITE
(2
), MB_USEGLYPHCHARS
(4
)), задающие поведение функции при конверсии, или значение 0
. Полный список и описание флагов смотрите в документации.
Параметр cbMultiByte
задает количество байтов в C-строке lpMultiByteStr
, подлежащих конверсии. Если C-строка завершается нулевым символом, то лучше указать значение –1
. В этом случае размер строки вычисляется автоматически и в L-строку вставляется нулевой символ. Если указано конкретное число, то нулевой символ автоматически в L-строку не вставляется!
Параметр cchWideChar
задает максимальный размер L-строки lpWideCharStr
в символах. Если указать значение 0
, то функция вернет требуемое количество символов. Если указано конкретное значение, то функция вернет количество записанных символов или значение 0
в случае ошибки;
WideCharToMultiByte()
— преобразует L-строкуlpWideCharStr
в C-строкуlpMultiByteStr
. Требуемая кодировка C-строки указывается в параметреcodePage
. Прототип функции:
#include <windows.h> /* Kernel32.lib */
int WideCharToMultiByte(UINT codePage, DWORD dwFlags,
LPCWCH lpWideCharStr, int cchWideChar,
LPSTR lpMultiByteStr, int cbMultiByte,
LPCCH lpDefaultChar, LPBOOL lpUsedDefaultChar);
В параметре dwFlags
можно указать различные флаги (WC_COMPOSITECHECK
(512
), WC_DEFAULTCHAR
(64
), WC_DISCARDNS
(16
), WC_SEPCHARS
(32
), WC_NO_BEST_FIT_CHARS
(1024
)), задающие поведение функции при конверсии, или значение 0
. Полный список и описание флагов смотрите в документации.
Параметр cchWideChar
задает количество символов в L-строке lpWideCharStr
, подлежащих конверсии. Если L-строка завершается нулевым символом, то лучше указать значение –1
. В этом случае размер строки вычисляется автоматически и в C-строку вставляется нулевой символ. Если указано конкретное число, то нулевой символ автоматически в C-строку не вставляется!
Параметр cbMultiByte
задает максимальный размер C-строки lpMultiByteStr
в байтах. Если указать значение 0
, то функция вернет требуемое количество байтов. Если указано конкретное значение, то функция вернет количество записанных байтов или значение 0
в случае ошибки.
В параметре lpDefaultChar
можно задать адрес символа, который будет использоваться, если символ в L-строке не может быть преобразован (символ отсутствует в кодировке codePage
). Если задан нулевой указатель, то будет использоваться символ по умолчанию. При использовании кодировки UTF-8 параметр lpDefaultChar
должен иметь значение NULL
.
Параметр lpUsedDefaultChar
позволяет задать адрес логической переменной. Если параметр не равен значению NULL
, то в переменную будет записано логическое значение Истина
, если какого-либо символа нет в кодировке codePage
, и 0
— в противном случае. При использовании кодировки UTF-8 параметр lpUsedDefaultChar
должен иметь значение NULL
.
Пример использования функций MultiByteToWideChar()
и WideCharToMultiByte()
приведен в листинге 8.5.
Листинг 8.5. Функции MultiByteToWideChar()
и WideCharToMultiByte()
#include <iostream>
#include <clocale>
#include <cstring>
#include <cwchar>
#include <windows.h>
int main() {
std::setlocale(LC_ALL, "Russian_Russia.1251");
int count = 0;
char cp866[256] = {0};
char utf8[256] = {0};
wchar_t wstr[256] = {0};
wchar_t wstr2[256] = {0};
char str[] = "строка str"; // Исходная строка (windows-1251)
for (int i = 0, len = (int)std::strlen(str); i < len; ++i) {
std::cout << (int)str[i] << ' ';
} // -15 -14 -16 -18 -22 -32 32 115 116 114
std::cout << std::endl;
// Узнаем требуемый размер wstr
count = MultiByteToWideChar(1251, 0, str, -1, wstr, 0);
std::cout << "требуется " << count << std::endl; // требуется 11
// Преобразование C-строки в кодировке windows-1251 в L-строку
count = MultiByteToWideChar(1251, 0, str, -1, wstr, 255);
std::cout << "записано " << count << std::endl; // записано 11
for (int i = 0, len = (int)std::wcslen(wstr); i < len; ++i) {
std::cout << (int)wstr[i] << ' ';
} // 1089 1090 1088 1086 1082 1072 32 115 116 114
std::cout << std::endl;
// Узнаем требуемый размер utf8
count = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, utf8, 0,
NULL, NULL);
std::cout << "требуется " << count << std::endl; // требуется 17
// Преобразование L-строки в C-строку в кодировке UTF-8
count = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, utf8, 255,
NULL, NULL);
std::cout << "записано " << count << std::endl; // записано 17
for (int i = 0, len = (int)std::strlen(utf8); i < len; ++i) {
std::cout << (int)utf8[i] << ' ';
} // -47 -127 -47 -126 -47 -128 -48 -66 -48 -70 -48 -80 32 115 116 114
std::cout << std::endl;
// Узнаем требуемый размер wstr2
count = MultiByteToWideChar(CP_UTF8, 0, utf8, -1, wstr2, 0);
std::cout << "требуется " << count << std::endl; // требуется 11
// Преобразование C-строки в кодировке UTF-8 в L-строку
count = MultiByteToWideChar(CP_UTF8, 0, utf8, -1, wstr2, 255);
std::cout << "записано " << count << std::endl; // записано 11
for (int i = 0, len = (int)std::wcslen(wstr2); i < len; ++i) {
std::cout << (int)wstr2[i] << ' ';
} // 1089 1090 1088 1086 1082 1072 32 115 116 114
std::cout << std::endl;
// Узнаем требуемый размер cp866
char ch = '?';
int flag = 1;
// wstr[1] = L'\u0263'; // символа нет в windows-866
count = WideCharToMultiByte(866, 0, wstr, -1, cp866, 0, &ch, &flag);
std::cout << "требуется " << count << std::endl; // требуется 11
// Преобразование L-строки в C-строку в кодировке windows-866
count = WideCharToMultiByte(866, 0, wstr, -1, cp866, 255, &ch, &flag);
std::cout << "записано " << count << std::endl; // записано 11
for (int i = 0, len = (int)std::strlen(cp866); i < len; ++i) {
std::cout << (int)cp866[i] << ' ';
} // -31 -30 -32 -82 -86 -96 32 115 116 114
std::cout << std::endl;
std::cout << flag << std::endl; // 0
return 0;
}
Реквизиты
ЮMoney (Yandex-деньги): 410011140483022
ПАО Сбербанк:
Счет: 40817810855006152256
Реквизиты банка:
Наименование: СЕВЕРО-ЗАПАДНЫЙ БАНК ПАО СБЕРБАНК
Корреспондентский счет: 30101810500000000653
БИК: 044030653
КПП: 784243001
ОКПО: 09171401
ОКОНХ: 96130
Скриншот реквизитов