Форматирование строк

Материал из Pro-Pawn Wiki
Перейти к: навигация, поиск

В данной статье описаны принципы форматирования, общие для функций format() и printf().

Форматирование производится с помощью спецификаторов в форматной строке. Например, вывод ID интерьера, в котором находится игрок, производится следующим образом:

new interior = GetPlayerInterior(playerid);
printf("Ваш интерьер: %d", interior);

Здесь часть строки "Ваш интерьер: " выведется без изменений, а вместо спецификатора "%d" будет выведено значение переменной interior (т.е. если interior равна нулю, будет выведено "Ваш интерьер: 0").

Форматные спецификаторы имеют следующее строение:
%[флаги][длина][.точность]тип


Типы спецификаторов

Тип(ы) Описание Пример кода Вывод
c Одиночный символ
printf("%c", 'z');
z
d i Целое число (в десятичной системе)
printf("%d", 42);
42
x h Целое число (в шестнадцатеричной системе)
printf("%x", 42);
2A
b Целое число (в двоичной системе)
printf("%b", 42);
101010
f Вещественное число
printf("%f", 42.0);
42.000000
s Строка
printf("%s", "abc");
abc
q Экранируемая строка для защиты от внедрения SQL-кода при работе с SQLite (добавлено в SA-MP 0.3.7 R2)
printf("%q", "abc");
abc
% Символ '%'
printf("100%%");
100%


Длина

Поле "длина" позволяет указать минимальную длину выводимого значения, однако его работа отличается для некоторых спецификаторов. Если длина форматируемого значения в строковом виде меньше указанной в поле минимальной длины, перед значением добавляются пробелы (также символом-заполнителем может быть 0; см. разд. "Флаги"). Если длина значения больше минимальной длины, значение выводится в неизменном виде.

Типы спецификаторов и принцип работы данного поля для каждого из них перечислены в таблице ниже. Спецификаторы, для которых поле "длина" не работает, в таблице не приведены.

Спецификатор(ы) Примечание Пример кода Вывод
%d %i
printf("%4d", 42);
  42 (с 2 пробелами в начале)
%x %h
printf("%4x", 42);
  2A (с 2 пробелами в начале)
%b
printf("%4b", 3);
  11 (с 2 пробелами в начале)
%f Действует только на целую часть числа
printf("%4f", 42.0);
  42.000000 (с 2 пробелами в начале)
%s Пробелы добавляются после строки
printf("%4s", "abc");
abc  (с 1 пробелом в конце)


Точность

Поле "точность" позволяет указать либо максимальную длину строки (спецификатор %s), либо длину дробной части для вещественных чисел (%f). Для остальных типов спецификаторов данное поле игнорируется.

Спецификатор(ы) Пример кода Вывод
%f
printf("%.2f", 42.0);
42.00
%s
printf("%.2s", "ab");
ab


Флаги

При помощи флагов можно изменить поведение форматирования.

Флаг Спецификатор(ы) Описание Пример кода Вывод
0 %d %i %x %h %b Значение дополняется нулями вместо пробелов.
printf("%04d", 42);
0042
- %d %i %x %h %b Выравнивает значение по левому краю (символы-заполнители добавляются не перед значением, а после).

По неизвестной причине удалён в 0.3c R3-1 (в конце поста с релизом лишь сказано, что была исправлена некая "проблема с добавлением пробелов в format())".

printf("%-4d", 42);
42   (с 2 пробелами в конце)


Переменная длина и точность

Также существует возможность задавать переменную длину и точность вывода значений. Для этого следует в полях "длина" и "точность" вместо числа указать символ *, а значения для этих полей передать перед форматируемым значением.
Например, код

printf("%0*d", 4, 42);

означает то же самое, что и

printf("%04d", 42);

и выводит 0042.

Ещё примеры:

printf("%.*f", 2, 42.0);      // Вывод: "42.00"
printf("%.*s", 2, "abc");     // Вывод: "ab"
printf("%*.*f", 4, 2, 42.0);  // Вывод: "  42.00"
printf("%*.*s", 4, 2, "abc"); // Вывод: "ab  "


Bug.png
Баг SA-MP
Упакованные строки (как в форматной строке, так и в форматируемых данных) не поддерживаются.
Минимальное целочисленное значение (cellmin) неправильно выводится с помощью спецификатора %d.
Пример:
printf("%d", cellmin); // Вывод: "--"

Спецификатор %f неправильно выводит особые вещественные значения.
Название Значение Вывод
Отрицательный ноль -0.0 0.000000
Положительная бесконечность Float:0x7F800000, 1.0 / 0.0 0.000000
Отрицательная бесконечность Float:0xFF800000, -1.0 / 0.0 -0.000000
При этом значение NaN ("Not a Number"; Float:0xFFC00000, floatsqroot(-1.0)) выводится правильно: NaN (до версии 0.3c R3-1 выводилось как 0.000000).



См. также: