Как напечатать строку Unicode в Zig?

Я пытался закодировать строковую структуру Unicode, и хотя стандартная библиотека предоставляет unicode модуль, похоже, он не предоставляет способ распечатать фрагмент u16. Я пробовал это:

const std = @import("std");
const unicode = std.unicode;
const stdout = std.io.getStdOut().outStream();

pub fn main() !void {
    const unicode_str = unicode.utf8ToUtf16LeStringLiteral(" hello! ");
    try stdout.print("{}\n", .{unicode_str});
}

Это выводит:

[12:0]u16@202e9c

Есть ли способ распечатать строку юникода ([]u16) без преобразования его обратно в строку, отличную от Unicode ([]u8)?

1 ответ

И то и другое []const u8 и []const u16хранить закодированные кодовые точки Unicode. Кодовые точки Unicode попадают в диапазон 0..1114112, поэтому фактическая строка Unicode с одним индексом массива для каждой кодовой точки должна быть []const u21. И utf-8, и utf-16 требуют кодирования для кодовых точек, которые не подходят. Если нет причины совместимости для utf-16 (например, некоторых функций Windows), вам, вероятно, следует использовать []const u8 строки юникода.

Чтобы напечатать utf-16 в потоке utf-8, вам необходимо декодировать utf-16 и перекодировать его в utf-8. В настоящее время нет спецификатора форматирования, который бы делал это автоматически.

Вы можете преобразовать всю строку сразу, требуя выделения:

const utf8string = try std.unicode.utf16leToUtf8Alloc(alloc, utf16le);

Или без выделения:

var writer = std.io.getStdOut().writer();
var it = std.unicode.Utf16LeIterator.init(utf16le);
while (try it.nextCodepoint()) |codepoint| {
    var buf: [4]u8 = [_]u8{undefined} ** 4;
    const len = try std.unicode.utf8Encode(codepoint, &buf);
    try writer.writeAll(buf[0..len]);
}

Обратите внимание, что это будет очень медленно без использования буферизованной записи, если вы пишете где-то, для чего требуется системный вызов.

Другие вопросы по тегам