Что означает «%. * S» в printf?

113

У меня есть фрагмент кода, в котором есть

printf("%.*s\n")

что %.*sзначит?

Шаобо Ван
источник
26
Без дополнительных аргументов это недопустимый printfпризыв.
Эндрю Маршалл

Ответы:

121

Вы можете использовать звездочку ( *) для передачи спецификатора / точности ширины printf()вместо жесткого кодирования в строку формата, т.е.

void f(const char *str, int str_len)
{
  printf("%.*s\n", str_len, str);
}
AusCBloke
источник
4
Следует отметить, что str_lenаргумент должен иметь тип int(или более узкий целочисленный тип, который будет повышен до int). Было бы ошибкой пройти long, size_tи т.д.
MM
10
Стоит упомянуть, что вероятная цель этого кода, особенно при использовании с %s, - напечатать подстроку исходной строки. В этом случае использования strбудет указывать где-то внутри исходной строки (возможно, в начале) и str_lenуказать длину подстроки, которая должна быть напечатана.
Sonic Atom
2
Указав длину, мы можем обойти печать (или sprintf) строки, не имеющей нулевого терминатора, например строки, которая вводится из любого потока или источника на основе файла. С которым я сталкивался гораздо чаще, чем просто печать prettines.
Conrad B
23

Подробнее здесь .

целочисленное значение или *указывающее минимальную ширину поля. Результат дополняется пробелами (по умолчанию), если требуется, слева, если выровнен по правому краю, или справа, если выровнен по левому краю. В случае использования * ширина задается дополнительным аргументом типа int. Если значение аргумента отрицательное, результат будет с указанным флагом - и положительной шириной поля. (Примечание: это минимальная ширина: значение никогда не усекается.)

.за которым следует целое число или *, либо ни то, ни другое не указывает на точность преобразования. В случае использования * точность указывается дополнительным аргументом типа int. Если значение этого аргумента отрицательное, оно игнорируется. Если ни число, ни * не используются, точность принимается равной нулю. См. Таблицу ниже для получения точных сведений о точности.

Итак, если мы попробуем обе спецификации преобразования

#include <stdio.h>

int main() {
    int precision = 8;
    int biggerPrecision = 16;
    const char *greetings = "Hello world";

    printf("|%.8s|\n", greetings);
    printf("|%.*s|\n", precision , greetings);
    printf("|%16s|\n", greetings);
    printf("|%*s|\n", biggerPrecision , greetings);

    return 0;
}

получаем вывод:

|Hello wo|
|Hello wo|
|     Hello world|
|     Hello world|
Ондрей
источник
12

Я не думаю, что приведенный выше код верен, но (согласно этому описанию printf()) .*средства

Ширина не указывается в строке формата, а указывается как дополнительный аргумент целочисленного значения, предшествующий аргументу, который должен быть отформатирован. '

Так что это строка с допустимой шириной в качестве аргумента.

повторить
источник
2
Я добавил перекрестную ссылку URL, чтобы вы могли избежать обвинений в плагиате. Конечно, правильная цитата гласит: « Точность не…», а не « Ширина не…».
Джонатан Леффлер,
Как отметил @MattMcNabb, каждая ссылка на эту страницу должна подчеркивать, что « целочисленное значение » является точным int(или его подмножеством), а не просто любым целым значением, например более интуитивным size_tили его возможными псевдонимами, например std::string::size_type. Это еще больше сбивает с толку, если учесть, что на указанной странице упоминается size_tодин из описателей поддерживаемого типа.
Антон Самсонов
10

См .: http://www.cplusplus.com/reference/clibrary/cstdio/printf/

.* Точность указывается не в строке формата, а как дополнительный аргумент целочисленного значения, предшествующий аргументу, который необходимо отформатировать.

s Строка символов

Джош
источник