2013-07-10 13 views
6
#include <stdio.h> 

int main() 
{ 
    printf("%*.*d\n", -6 , 7,20000); 
    printf("%*.*d\n", 5, -6, 2000); 
    return 0; 
} 

Ausgang:Wie funktioniert% *. * D in printf()?

0020000 
2000 

Ich verstehe nicht, wie printf die Formatbezeichner * interpretiert. *?

Während im ersten Aufruf zu printf(), wird die später Überschreibung der ehemaligen -6? So dass die Größe der Ausgabebreite zu 7 wird?

Antwort

8

Das Argument der * vor dem . ist die Feldbreite und das Argument der * nach dem . ist die Präzision .

Feldbreiten sind die Mindestanzahl von Bytes, die als Ergebnis der Konvertierung ausgegeben werden; Die Ausgabe wird gepolstert (standardmäßig links mit Leerzeichen, aber die Nullauffüllung und die Auffüllung des rechten Zwischenraums sind ebenfalls Optionen, die durch Flags gesteuert werden), wenn weniger Bytes erzeugt würden. Ein negatives Argument für die Breite * wird als der entsprechende positive Wert mit dem Flag - interpretiert, der die Auffüllung nach rechts verschiebt (d. H. Das Feld linksbündig ausrichtet).

Präzision auf der anderen Seite hat eine Bedeutung, die je nach der durchgeführten Konvertierung variiert. Negative Genauigkeiten werden so behandelt, als ob überhaupt keine Genauigkeit angegeben worden wäre. Für Ganzzahlen ist es die minimale Anzahl von Ziffern (nicht Gesamtausgabe) zu produzieren; Wenn weniger Ziffern erzeugt werden, werden Nullen auf der linken Seite hinzugefügt. Eine explizite Genauigkeit von 0 führt dazu, dass keine Ziffern erzeugt werden, wenn der Wert 0 ist (anstelle einer einzigen 0 wird produziert). Bei Zeichenfolgen ist die Genauigkeit die Anzahl der Ausgangsbytes, die die Zeichenfolge abgeschnitten (und ein längeres, nicht nullterminiertes Eingabearray zulassen), falls erforderlich. Bei Gleitkomma-Spezifizierern steuert die Genauigkeit die Anzahl der gedruckten Stellen, entweder nach dem Basispunkt (für %f) oder den gesamten Signifikanzorten (für die anderen Formate).

In Ihren Beispielen:

printf("%*.*d\n", -6 , 7,20000); 

Hier wird das Feld ausgerichtet bleibt, ist (padding rechts) mit einer Mindestbreite von 6, aber das Feld endet breite ohnehin zu sein, so wird die Breite ignoriert. Die Genauigkeit von 7 erzwingt eine ganzzahlige Ausgabe von mindestens 7 Ziffern, so dass Sie als konvertierten Feldinhalt 0020000 haben, was die Breite bereits überschritten hat.

in der anderen:

printf("%*.*d\n", 5, -6, 2000); 

Die Feldbreite 5 ist, mit der Standard rechten Ausrichtung; Padding ist mit Leerzeichen auf der linken Seite.Die negative Genauigkeit wird ignoriert, als ob sie nicht angegeben wäre. Der konvertierte Feldinhalt ist also 2000, nur 4 Bytes, die bis zu 5 Bytes aufgefüllt werden, um die Breite mit einem einzigen führenden Leerzeichen zu füllen.

+2

+1, aber ich denke, es sollte "Zeichen" oder "Ziffern", nicht "Bytes" sein. – unwind

+6

@unwind: Ich habe absichtlich das Wort "Bytes" verwendet. Es sind keine "Ziffern", da die Breite Dinge wie Vorzeichen, Basispunkt (für Gleitkomma) usw. zum Gesamtwert zählt, und im Fall eines Gebiets, in dem der Basispunkt ein Multibyte-Zeichen ist, würde jedes Byte zur Breite zählen. Beachten Sie, dass im C-Standard "Bytes" und "Zeichen" gleichwertig sind; Ich vermeide es, das Wort "Zeichen" zu verwenden, da es aufgrund der Multibyte-Zeichen für die meisten Menschen mehrdeutig ist. POSIX hat alle Verweise auf "Zeichen" in der Spezifikation für diese Funktionen auf "Bytes" geändert, um Verwechslungen zu vermeiden. –

+0

Vielen Dank. Ich denke, ich habe den Schlüsselpunkt gefunden, das ist die * Feldbreite * Kontrolle der Ausgabe Breite mit der Standardausrichtung rechts und Auffüllen mit Leerzeichen auf der linken Seite, wenn weniger Bytes produziert werden würde, und die * Precision * steuern die Mindestanzahl von Ziffern, die ausgegeben werden sollen. –

3
printf("%*.*d\n", -6 , 7,20000); 

ist die gleiche wie

printf("%-6.7d\n, 20000); 

Diese bieten nur einen Weg für die dynamische Format.

0

diese Quellcode von printf in glibc

/* VARARGS1 */ 
int __printf (const char *format, ...) 
{ 
va_list arg; 
int done; 

va_start (arg, format); 
done = vfprintf (stdout, format, arg); 
va_end (arg); 

return done; 

}

wie man es von Parametern wird printf sehen va_list

hier ist ein weiteres Beispiel, um Ihnen zu zeigen, wie printf Werke:

/* va_start example */ 
#include <stdio.h>  /* printf */ 
#include <stdarg.h>  /* va_list, va_start, va_arg, va_end */ 

void PrintFloats (int n, ...) 
{ 
    int i; 
    double val; 
    printf ("Printing floats:"); 
    va_list vl; 
    va_start(vl,n); 
    for (i=0;i<n;i++) 
    { 
    val=va_arg(vl,double); 
    printf (" [%.2f]",val); 
    } 
    va_end(vl); 
    printf ("\n"); 
} 

int main() 
{ 
    PrintFloats (3,3.14159,2.71828,1.41421); 
    return 0; 
}