Windows AllocConsole() не позволяет печатать строки в кодировке UTF-16C++

Программы на C++. Форум разработчиков
Ответить
Anonymous
 Windows AllocConsole() не позволяет печатать строки в кодировке UTF-16

Сообщение Anonymous »

Последние несколько часов я боролся с этой проблемой и думаю, что она сводит меня с ума, поэтому решил спросить здесь.

Я работал в приложении Windows. Ему необходимо открыть окно, чтобы оно было скомпилировано в подсистеме Windows (

Код: Выделить всё

/SUBSYSTEM:WINDOWS
в MSVC), это также означает, что он не открывает терминал по умолчанию, но я хочу, чтобы он печатал данные, пока я над ним работаю.
Windows API предоставляет решение для этого: функция AllocConsole, которая, как сказано в документации, "выделяет новую консоль для вызывающего процесса". После его вызова действительно открывается окно консоли, и я могу вывести в него текст после вызова freopen следующим образом:

(Обратите внимание, что freopen > необходим, потому что нам нужно перенаправить все, что мы пишем в стандартный вывод, на «CONOUT$» и т. д.)

Код: Выделить всё

bool AttachCon() {
if (AllocConsole() == FALSE) {
return false;
}

FILE *tmp;
_wfreopen_s(&tmp, L"CONIN$", L"r", stdin);
_wfreopen_s(&tmp, L"CONOUT$", L"w", stdout);
_wfreopen_s(&tmp, L"CONOUT$", L"w", stderr);

return true;
}
Проблема возникает при попытке напечатать строки расширенных символов. По умолчанию терминал Windows использует кодировку символов кодовой страницы 850, что не подходит для того, что мне нужно. После поиска в Интернете вы быстро увидите, что решение представляет собой неясный вызов _setmode с параметром mode, установленным в _O_U16TEXT, например:

Код: Выделить всё

_setmode(_fileno(stdin), _O_U16TEXT);
_setmode(_fileno(stdout), _O_U16TEXT);
_setmode(_fileno(stderr), _O_U16TEXT);
Насколько я понимаю, это в основном сообщает функциям, которые выводят на экран, что текст, который они получат, закодирован так, как указано пользователем, и что на самом деле это не так. измените кодовую страницу в терминале (

Код: Выделить всё

GetConsoleCP
всегда возвращает 850). Затем эти функции автоматически переводят строки из одной кодировки в другую.

Вот в чем проблема: попытка сделать вышеописанное в консольном приложении работает (пока /utf указан флаг -8, подробнее об этом позже), но его нет в приложении для ПК.

Вывод, который я получаю при попытке напечатать L" Тест à" — это T e s t Ó :

T e s t Ó

Обратите внимание, что à — это 0x00E0 в UTF-16, а Ó — это также 0xE0 на кодовой странице 850. Кроме того, по какой-то причине между каждым символом есть странные пробелы (я предполагаю, что это второй байт символа UTF-16).

Это то, что я пробовал и наблюдал на своей машине. :
  • По умолчанию строка wchar_t использует UTF-8, это можно изменить, скомпилировав проект с использованием /utf-8 флаг (который, насколько я могу судить, может быть только устанавливается вручную в Свойствах проекта --> C/C++ --> Командная строка в Visual Studio), при этом устанавливается кодировка UTF-16 (мне кажется, что это наоборот?)
  • Код: Выделить всё

    _setmode
    возвращает предыдущий режим перевода. При первом вызове он возвращает 0x4000, что соответствует _O_TEXT - тексту (переведенному), а во второй раз возвращает 0x10000, что должно соответствовать _O_U16TEXT - UTF16 no BOM (переведенному). ), так как я его устанавливаю, но на самом деле это _O_WTEXT - UTF16 (переведено), (описания взяты из комментариев рядом с определениями в fcntl.h. Попытка вручную записать спецификацию в стандартный вывод ничего не дает.
  • Я пробовал то и это, но ничего не изменилось.
У кого-нибудь есть идеи, что это может быть? что операционная система просто забывает некоторые настройки и Вызов _setmode выполняется неправильно.

Кроме того, если это поможет, я использую Windows 11 24H2, сборка 26100.2605

Заранее спасибо.

Подробнее здесь: https://stackoverflow.com/questions/793 ... ed-strings
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C++»