D Строковые литералы Unicode: не может печатать определенный символ Unicode

Я просто пытаюсь забрать D, пришедший из C++. Я уверен, что это что-то очень простое, но я не могу найти какую-либо документацию, чтобы помочь мне. Я пытаюсь напечатать символ а, который является U+00E0. Я пытаюсь присвоить этот символ переменной, а затем использовать write() вывести его на консоль.

Мне сообщают на этом сайте, что U + 00E0 кодируется как 0xC3 0xA0 в UTF-8, 0x00E0 в UTF-16 и 0x000000E0 в UTF-32.

Обратите внимание, что для всего, что я пробовал, я пытался заменить string с char[] а также wstring с wchar[], Я также пробовал с и без w или же d суффиксы после широких строк.

Эти методы возвращают ошибку компилятора "Недопустимый конечный код":

string str = "à";
wstring str = "à"w;
dstring str = "à"d;

Эти методы печатают совершенно другой символ (Ò U + 00D2):

string str = "\xE0";
string str = hexString!"E0";

И все эти методы выдают то, что выглядит как ˧á (примечание á à!), То есть UTF-16 0x2E7 0x00E1:

string str = "\xC3\xA0";
wstring str = "\u00E0"w;
dstring str = "\U000000E0"d;

Есть идеи?

2 ответа

Решение

Я подтвердил, что это работает на моей Windows-коробке, поэтому сейчас напишу это как ответ.

В исходном коде, если вы копируете / вставляете символы напрямую, убедитесь, что ваш редактор сохраняет их в кодировке utf8. На этом настаивает D-компилятор, поэтому, если он выдает ошибку компиляции о чем-то, возможно, именно поэтому. Я никогда не использовал c:b, но старый ответ в сети сказал, что edit->encodings... это настройка где-то в редакторе.

Или вы можете заменить символы в вашем исходном коде на \uxxxx в строках. НЕ используйте шестнадцатеричную вещь, то есть для двоичных байтов, но ваш пример "\u00E0" это хорошо, и будет работать для любого типа строки (не только для wstring, как в вашем примере).

Затем со стороны вывода это зависит от вашей цели, потому что программа просто выводит байты, и программа-получатель должна правильно ее интерпретировать. Так как вы сказали, что находитесь в Windows, ключ должен установить кодовую страницу консоли в utf-8, чтобы она знала, что вы пытаетесь сделать. Действительно, та же самая функция C может быть вызвана и из D. Ведущий к этой программе:

import core.sys.windows.windows;
import std.stdio;

void main() {
    SetConsoleOutputCP(65001);
    writeln("Hi \u00E0");
}

печать успешно. В старых версиях Windows вам может потребоваться изменить свой шрифт, чтобы увидеть символ (в отличие от общего окна, которое он показывает, потому что некоторые шрифты не имеют всех символов), но в моем окне Windows 10 он просто работал с шрифт по умолчанию.

Кстати, технически кодовая страница консоли является общей настройкой (после запуска программы и ее выхода вы все равно можете нажать свойства в окне консоли и увидеть отраженные там изменения), и вам, возможно, следует вернуть ее обратно при выходе из программы. Вы можете получить это при запуске с помощью функции get ( https://docs.microsoft.com/en-us/windows/console/getconsoleoutputcp), сохранить ее в локальной переменной и установить обратно при выходе. Вы могли бы auto ccp = GetConsoleOutputCP(); SetConsoleOutputCP(65005;) scope(exit) SetConsoleOutputCP(ccp); прямо при запуске - выход из области будет запущен при выходе из функции, так что делать это в main было бы довольно удобно. Просто добавьте проверку ошибок, если хотите.

Документы Microsoft ничего не говорят об их установке, так что, вероятно, это на самом деле не имеет значения, но я все же хочу упомянуть об этом на всякий случай. Но также знание того, что он используется и сохраняется, может помочь в отладке - если он работает после того, как вы прокомментируете его, это не потому, что код не нужен, а просто потому, что он был установлен ранее и еще не установлен!

Обратите внимание, что запуск его из IDE может не совпадать, потому что IDE часто направляют вывод, а не запускают его прямо в консоль Windows. Если это произойдет, позвольте мне знать, и мы можем напечатать кое-что об этом для будущих читателей. Но вы также можете открыть свою собственную копию консоли (запустить программу за пределами IDE), и она должна отображаться правильно для вас.

Исходный код D должен быть закодирован как UTF-8. Я предполагаю, что вы помещаете символ UTF-16 в исходный файл UTF-8.

Например

import std.stdio;
void main() {
    writeln(cast(char)0xC3, cast(char)0xA0);
}

Будет выводить как UTF-8 персонажа, которого вы ищете.

Что вы можете затем жестко кодировать так:

import std.stdio;
void main() {
    string str = "à";
    writeln(str);
}
Другие вопросы по тегам