Преобразование между wchar_t char в кодовой странице ANSI

Если я нахожусь в среде только с кодовой страницей ANSI.

Это преобразование wide char в char:

char ansi_cstr[size_of_ansi_str];
WideCharToMultiByte(CP_ACP, 0, ansi_wstr.c_str(), -1, ansi_str, size_of_ansi_str, 0, 0);
std::string ansi_str = std::string(ansi_cstr);

равно следующему

std::string ansi_str = std::string(ansi_wstr.begin(), ansi_wstr.end());

и с char по wide char

wchar_t ansi_wcstr[size_of_ansi_str];
MultiByteToWideChar(CP_ACP, 0, ansi_str.c_str(), -1, ansi_wcstr, size_of_ansi_str);
std::wstring ansi_wstr = std::wstring(ansi_wcstr);

равно

std::wstring ansi_wstr = std::wstring(ansi_str.begin(), ansi_str.end());

Остаются ли эти два случая одинаковыми в среде только кодовой страницы ansi?


person Chen OT    schedule 15.05.2014    source источник
comment
Настоящий вопрос заключается в том, почему вы будете использовать кодовые страницы ANSI в 2014 году?   -  person Cody Gray    schedule 15.05.2014
comment
Еще хуже: кодовая страница ANSI только. Я думаю, что первой Windows с поддержкой Unicode (через Unicows) была Windows 95, так что это будет Windows 3.1 1994 года. 20-летней давности. К слову об унаследованной разработке. С другой стороны, мы все еще видим здесь вопросы по Turbo C++.   -  person MSalters    schedule 15.05.2014
comment
Windows 95/98/ME были ОС на базе Ansi. UCS-2 использовался в NT4, а затем был заменен на UTF-16 в Windows 2000. Две линейки продуктов не были объединены в единую ОС Unicode до XP.   -  person Remy Lebeau    schedule 16.05.2014
comment
@CodyGray Может быть, потому, что даже в 2018 году многие DBF шейп-файлов все еще используют идентификатор языкового драйвера 0x57?   -  person Rodrigo    schedule 29.11.2018


Ответы (2)


Не существует такой вещи, как среда кодовой страницы ANSI. Есть десятки.

Два ваших «быстрых» преобразования неверны во всех из них.

Преобразование из ASCII char в UTF-16 wchar_t будет работать с вашим последним методом, но он не работает со второй половиной большинства кодовых страниц ANSI. Лучше всего он работает с западноевропейской кодовой страницей, где ошибается всего ~32 символа. Например. знак евро € всегда будет неправильно преобразован.

person MSalters    schedule 15.05.2014

WideCharToMultiByte(CP_ACP, 0, ansi_wstr.c_str(), -1, ansi_str, size_of_ansi_str, 0, 0);

НЕ совпадает с

std::string ansi_str = std::string(ansi_wstr.begin(), ansi_wstr.end());

WideCharToMultiByte() выполняет реальное преобразование из UTF-16 в ANSI, используя кодовую страницу, на которую ссылается CP_ACP на этом ПК (которая может быть разной на каждом ПК в зависимости от региональных настроек пользователя). std::string(begin, end) просто перебирает исходный контейнер, приведя каждый элемент к типу char, и вообще не выполняет никакого преобразования кодовой страницы.

Так же:

MultiByteToWideChar(CP_ACP, 0, ansi_str.c_str(), -1, ansi_wcstr, size_of_ansi_str);

НЕ совпадает с

std::wstring ansi_wstr = std::wstring(ansi_str.begin(), ansi_str.end());

По той же причине. MultiByteToWideChar() выполняет реальное преобразование из ANSI в UTF-16 с использованием кодовой страницы CP_ACP, тогда как std::wstring(begin, end) просто приводит исходные элементы к wchar_t без какого-либо преобразования.

Приведение типов будет эквивалентно преобразованиям API, ТОЛЬКО если в исходных строках используются символы ASCII в диапазоне 0x00-0x7F. Но если они используют символы, отличные от ASCII, все ставки сняты.

person Remy Lebeau    schedule 16.05.2014