Що означає "%. * S" у printf?


Відповіді:


120

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

void f(const char *str, int str_len)
{
  printf("%.*s\n", str_len, str);
}

4
Слід зазначити, що str_lenаргумент повинен мати тип int(або вузький інтегральний тип, до якого можна було б сприяти int). Було б помилкою пройти long, size_tі т.д.
MM

10
Варто зазначити, що ймовірною метою цього коду, особливо при використанні %s, є друк підрядного рядка вихідного рядка. У цьому випадку використання strвказуватиме десь усередині початкового рядка (можливо, на початку) та str_lenвизначатиме довжину підрядка, який слід надрукувати.
Sonic Atom

2
Вказавши довжину, ми можемо обійти друк (або sprintf) із рядка, який не має нульового термінатора, наприклад, рядка, який вводиться з будь-якого джерела на основі потоку або файлів. Що набагато частіше зустрічається із випадком використання, ніж я просто друкую дописи.
Конрад Б

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як один із підтримуваних специфікаторів типу.
Антон Самсонов

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.