Форматирование при печати
Решил написать маленькую шпаргалку по форматированию значений при печати. А то, как что-то чуть сложнее {d} или {s}, приходится память напрягать, где же я про это читал. Теперь здесь буду читать, может кому-то еще пригодится.
Строка форматирования должна быть известна компилятору на этапе компиляции и может содержать заполнители в следующем формате:
{[аргумент][спецификатор]:[заполнение][выравнивание][ширина].[точность]}
Сформировать строку формата динамически увы не получится. Если нашли как, то поправьте меня в одном из наших чатов.
Препарируем формат
Аргумент
Аргумент — это либо числовой индекс, либо имя поля, которое нужно вставить в итоговую строку. При использовании имени поля необходимо заключить его (имя) в квадратные скобки, например {[score]...}, в отличие от числового индекса, который можно записать, например, как {2...}
Спецификатор
Спецификатор - символ, который определяет, как будет выводиться аргумент.
Спецификаторы:
xиX: вывод числового значения в шестнадцатеричной системе счисления или строки в шестнадцатеричных байтах;s: печатает строку:- для указателей на множество и C-указателей на
[]u8выведет в виде C-строки с завершающим нулём: - для срезов
u8выведет весь срез в виде строки без завершающего нуля;
- для указателей на множество и C-указателей на
t:- для перечислений и размеченных объединений: выводит имя тега;
- для наборов ошибок: выводит имя ошибки;
b64: выведет строку в стандартном форматеbase64;e: вывод значения с плавающей запятой в экспоненциальном представлении;d: вывод десятичного числа;b: вывод целочисленного значения в двоичной системе счисления;o: вывод целочисленного значения в восьмеричной системе счисления;c: вывод целого числа в виде символа ASCII. Целочисленный тип должен содержать максимум 8 бит (u8);u: вывод целого числа в виде последовательности UTF-8. Целочисленный тип должен содержать максимум 21 бит (u21и больше);D: вывод наносекунд в качестве длительности;B: выходные байты в единицах СИ (десятичных);Bi: выходные байты в единицах IEC (двоичные);?: вывод необязательного значения либо в виде распакованного значения, либо как null. За ним может следовать спецификатор формата для базового значения;!: вывод объединенного значения ошибки либо в виде развернутого значения, либо в виде отформатированного значения. За ним может следовать спецификатор формата для базового значения.*: вывод адреса значения в памяти вместо самого значения;any: вывод значения любого типа в формате по умолчанию;f: делегирует вывод методу типа с именем «format» и сигнатуройfn (self: @This(), writer: *std.Io.Writer) std.Io.Writer.Error!void
Заполнение
Заполнение — это один байт, который используется для заполнения отформатированных значений.
Выравнивание
Выравнивание — это один из трех байтов <, ^ или >, которые выравнивают числа по левому, центральному или правому краю соответственно.
Важно помнить, что:
- Не все спецификаторы поддерживают выравнивание.
- Выравнивание не учитывает кодировку Юникод и подходит только для работы с необработанными байтами или ASCII.
Ширина
Ширина — общая ширина поля в байтах для вывода значения. Это относится только к форматированию чисел.
Точность
Точность — количество знаков после запятой для вывода чисел с плавающей запятой.
Прочее
Чтобы напечатать фигурные скобки буквально, напишите их дважды, например {{ или }}.
Обратите внимание, что большинство параметров являются необязательными и могут быть опущены. Также можно не указывать разделители, такие как : и . если все параметры после разделителя опущены.
Единственное исключение — параметр заполнение. Если требуется указать ненулевой символ заполнения одновременно с шириной, необходимо также указать выравнивание, иначе цифра после : будет интерпретироваться как ширина, а не как символ заполнения.
Примеры
const std = @import("std");
pub fn main() !void {
const hour = 10;
const minute = 30;
const second = 45;
const float_val = 125.2465;
const str = "тест";
const not_required: ?u8 = null;
const err = error.OutOfMemory;
const test_struct = TestStruct{ .hour = hour, .minute = minute, .second = second };
// Вывод чисел с выравниванием. Для каждого числ выделяется область из 4 символов
std.debug.print("1) {d: <4}:{d: ^4}:{d: >4}\n ====:====:====\n", .{ hour, minute, second });
// Вывод чисел с выравниванием. Но используются именованный и индексный доступ к переданным значениям
std.debug.print("2) {[second]d: <4}:{[hour]d: ^4.2}:{1d: >4}\n", .{ .hour = hour, .minute = minute, .second = second });
// Вывод текста в шестнадцатеричном формате
std.debug.print("3) Текст \"{s}\" в шестнадцатеричном формате: 0x{0X} - 0x{0x}\n", .{str});
// Вывод ошибки
std.debug.print("4) Имя ошибки: {t}\n", .{err});
// Вывод строки в формате Base64
std.debug.print("5) Текст \"{s}\" в Base64: {0b64}\n", .{str});
// Вывод чисел в различных форматах
std.debug.print("6) Число {d} в экспоненциальном формате: {e}\n", .{ float_val, float_val });
std.debug.print("7) Число {d} в двоичном формате: {b}\n", .{ second, second });
std.debug.print("8) Число {d} в восьмеричном формате: {o}\n", .{ minute, minute });
std.debug.print("9) Число {d} в символьном формате: {c}\n", .{ 0x74, 0x74 });
std.debug.print("10) Число {d} в UTF-8 формате: {u}\n", .{ 0x10346, 0x10346 });
std.debug.print("11) Число {d} в единицах СИ: {B}\n", .{ 125, 125 });
std.debug.print("12) Число {d} в единицах IEC: {Bi}\n", .{ 1024, 1024 });
// Вывод необязательного значения, которе может принимать числовое или значение null
std.debug.print("13) Необязательное значение: {?d}\n", .{not_required});
// Вывод структуры
std.debug.print("14) Структура cо спецификатором \"any\": {any}\n", .{test_struct});
// Делегирование вывода самой структуре
std.debug.print("15) Делегирование вывода самой структуре: {f}\n", .{test_struct});
}
const TestStruct = struct {
hour: u8,
minute: u8,
second: u8,
pub fn format(self: @This(), writer: *std.Io.Writer) std.Io.Writer.Error!void {
try writer.print("{d:0>2}:{d:0>2}:{d:0>2}", .{ self.hour, self.minute, self.second });
}
};