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

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

uscita:Come funziona% *. * D in printf()?

0020000 
2000 

Non capisco come si fa printf interpretano l'identificatore di formato *. *?

Mentre nella prima chiamata a printf(), fa il seguito di override l'ex -6? In modo che la dimensione della larghezza di output diventa 7?

risposta

8

L'argomento * prima della . è la larghezza del campo e l'argomento al * dopo il . è il precisione.

Le larghezze di campo sono il numero minimo di byte che verranno emessi come risultato della conversione; l'output verrà riempito (per impostazione predefinita, a sinistra con spazi, ma padding zero e spazio vuoto a destra sono anche opzioni, controllate da flag) se verranno prodotti meno byte. Un argomento negativo per la larghezza * viene interpretato come il valore positivo corrispondente con il flag -, che sposta il padding a destra (vale a dire a sinistra-giustifica il campo).

Precisione d'altra parte ha un significato che varia in base alla conversione eseguita. Le precisioni negative vengono trattate come se non fosse stata specificata alcuna precisione. Per numeri interi, è il numero minimo di cifre da produrre (non totale); se vengono prodotte meno cifre, gli zero vengono aggiunti a sinistra. Una precisione esplicita di 0 non produce nessuna cifra quando il valore è 0 (invece di un singolo 0 viene prodotto). Per stringhe, precisione limiti il numero di byte di output, troncando la stringa (e consentendo un array di input più lungo, non nullo, se necessario). Per gli specificatori a virgola mobile, la precisione controlla il numero di posizioni stampate, sia dopo il punto di radix (per %f) sia per le posizioni di significatività totali (per gli altri formati).

Nei tuoi esempi:

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

Qui il campo è allineato a sinistra (padding sulla destra) con una larghezza minima di 6, ma il campo finisce per essere più ampia comunque, quindi la larghezza viene ignorato. La precisione di 7 forza l'output intero di almeno 7 cifre, quindi si finisce con 0020000 come contenuto del campo convertito, che ha già superato la larghezza.

Nell'altra:

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

La larghezza del campo è 5, con l'allineamento a destra predefinito; il riempimento è con gli spazi a sinistra.La precisione negativa viene ignorata, come se non fosse specificata, quindi il contenuto del campo convertito è 2000, solo 4 byte, che vengono riempiti fino a 5 byte per riempire la larghezza per mezzo di un unico spazio iniziale.

+2

+1, ma penso che dovrebbe essere "caratteri" o "cifre", non "byte". – unwind

+6

@unwind: ho usato la parola "byte" intenzionalmente. Non è "cifre" perché la larghezza conta cose come il segno, il punto di radice (per il float), ecc. Verso il totale, e nel caso di un locale in cui il punto di radix è un carattere multibyte, ogni byte conterebbe verso la larghezza. Si noti che nello standard C, "byte" e "caratteri" sono equivalenti; Evito di usare la parola "personaggi" perché è ambigua alla maggior parte delle persone, a causa dei caratteri multibyte. POSIX ha cambiato tutti i riferimenti a "caratteri" nelle specifiche per queste funzioni a "byte" per evitare la confusione. –

+0

Grazie mille. Penso di aver trovato il punto chiave, ovvero l'ampiezza * del campo * controlla la larghezza dell'output con l'allineamento a destra predefinito e il padding con gli spazi a sinistra se vengono prodotti meno byte e la * Precision * controlla i numeri minimi di cifre da produrre. –

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

è stessa

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

Questo limita a fornire un modo per il formato dinamico.

0

questo è il codice sorgente di 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; 

}

come si può vedere printf riceve parametri da va_list

ecco un altro esempio, per mostrare come printf lavori:

/* 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; 
}