Was bedeutet "%. * S" in printf?

112

Ich habe ein Code-Snippet, in dem es ein gibt

printf("%.*s\n")

Was bedeutet das %.*sbedeuten?

Shaobo Wang
quelle
26
Ohne zusätzliche Argumente ist dies kein gültiger printfAufruf.
Andrew Marshall

Antworten:

119

Sie können ein Sternchen ( *) verwenden, um den Breitenbezeichner / die Genauigkeit an zu übergeben printf(), anstatt ihn fest in die Formatzeichenfolge zu codieren, d. H.

void f(const char *str, int str_len)
{
  printf("%.*s\n", str_len, str);
}
AusCBloke
quelle
3
Es ist zu beachten, dass das str_lenArgument einen Typ haben muss int(oder einen engeren integralen Typ, zu dem befördert werden würde int). Es wäre ein Fehler passieren sein long, size_tusw.
MM
9
Es ist erwähnenswert, dass der wahrscheinliche Zweck dieses Codes, insbesondere bei Verwendung mit %s, darin besteht, eine Teilzeichenfolge der ursprünglichen Zeichenfolge zu drucken. In diesem Anwendungsfall strwürde auf eine Stelle innerhalb der ursprünglichen Zeichenfolge verweisen (möglicherweise am Anfang) und str_lendie Länge der zu druckenden Unterzeichenfolge angegeben.
Sonic Atom
2
Durch Angabe einer Länge können wir das Drucken (oder Sprinten) einer Zeichenfolge umgehen, die keinen Nullterminator hat, z. B. eine Zeichenfolge, die von einer Stream- oder dateibasierten Quelle eingegeben wird. Das ist weitaus häufiger der Anwendungsfall, auf den ich gestoßen bin, als nur Prettinen zu drucken.
Conrad B
23

Detaillierter hier .

ganzzahliger Wert oder * der die minimale Feldbreite angibt. Das Ergebnis wird bei Bedarf mit Leerzeichen (standardmäßig) aufgefüllt, links, wenn rechtsbündig, oder rechts, wenn linksbündig. Wenn * verwendet wird, wird die Breite durch ein zusätzliches Argument vom Typ int angegeben. Wenn der Wert des Arguments negativ ist, ergibt sich das angegebene Flag und die positive Feldbreite. (Hinweis: Dies ist die Mindestbreite: Der Wert wird niemals abgeschnitten.)

.gefolgt von einer Ganzzahl oder * oder keiner, die die Genauigkeit der Konvertierung angibt. Wenn * verwendet wird, wird die Genauigkeit durch ein zusätzliches Argument vom Typ int angegeben. Wenn der Wert dieses Arguments negativ ist, wird es ignoriert. Wenn weder eine Zahl noch * verwendet wird, wird die Genauigkeit als Null angenommen. Die genauen Auswirkungen der Präzision finden Sie in der folgenden Tabelle.

Wenn wir also beide Konvertierungsspezifikationen ausprobieren

#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;
}

wir bekommen die Ausgabe:

|Hello wo|
|Hello wo|
|     Hello world|
|     Hello world|
Ondrej
quelle
12

Ich denke nicht, dass der obige Code korrekt ist, aber (gemäß dieser Beschreibung von printf()) die .*Mittel

Die Breite wird nicht in der Formatzeichenfolge angegeben, sondern als zusätzliches Ganzzahlwertargument vor dem Argument, das formatiert werden muss. '

Es ist also eine Zeichenfolge mit einer passablen Breite als Argument.

Wiederholung
quelle
2
Ich habe den URL-Querverweis hinzugefügt, damit Sie Anklagen wegen Plagiats vermeiden können. Das korrekte Zitat lautet natürlich "Die Genauigkeit ist nicht ..." und nicht "Die Breite ist nicht ...".
Jonathan Leffler
Wie @MattMcNabb hervorhob, muss jeder Verweis auf diese Seite hervorheben, dass „ ein ganzzahliger Wert “ genau int(oder eine Teilmenge davon) ist - nicht irgendein ganzzahliger Wert wie intuitiver size_toder seine möglichen Aliase wie std::string::size_type. Dies ist noch verwirrender, wenn man bedenkt, dass auf der Seite, auf die verwiesen wird, size_teiner der unterstützten Typspezifizierer erwähnt wird.
Anton Samsonov