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

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

輸出:%*。* d如何在printf()中工作?

0020000 
2000 

我不明白如何printf解釋格式說明*。 *

雖然在第一次調用printf(),莫非以後覆蓋前-6?所以輸出寬度的大小變成了7?

回答

8

.的前面的參數到*字段寬度.後的參數傳遞給*精度

字段寬度是作爲轉換結果輸出的最小字節數;如果產生的字節更少,輸出將被填充(默認情況下,左側帶有空格,但左側零填充和右側空白填充也是選項,由標誌控制)。對於寬度*的負面參數被解釋爲-標誌的相應正值,該標誌將填充移到右側(即,左對齊字段)。

另一方面,精度具有根據所執行的轉換而變化的含義。負精度被視爲完全沒有精確度。對於整數,它是數字(不是總產量)的最小數量;如果產生更少的數字,則將零添加到左側。當值爲0時(而不是生成單個0),顯式精度爲0時不會產生數字。對於字符串,精度限制了輸出字節的數量,如果需要,截斷字符串(並允許更長,非空終止的輸入數組)。對於浮點數說明符,精度控制打印的位置數,可以在小數點後面(對於%f)或總體顯着位置(對於其他格式)。

在你的例子:

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

在這裏,字段是左對齊(填充上右)的6的最小寬度,但該字段結束是更寬無論如何,所以寬度被忽略。 7的精度強制整數輸出至少爲7位數,所以最終以0020000作爲轉換後的字段內容,它已經超過了寬度。

在另一項:

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

字段寬度是5,用默認的右對齊;填充在左側有空格。如果沒有指定負精度,則忽略負精度,因此轉換的字段內容爲2000,只有4個字節,通過單個前導空格填充寬度爲5個字節以填充寬度。

+2

+1,但我認爲它應該是「字符」或「數字」,而不是「字節」。 – unwind

+6

@unwind:我故意使用了「字節」這個詞。它不是「數字」,因爲寬度計數符號,小數點(對於浮點數)等總數,並且在小數點是多字節字符的區域設置的情況下,每個字節都會計入寬度。請注意,在C標準中,「字節」和「字符」是等效的;我避免使用「characters」這個詞,因爲由於多字節字符,它對大多數人來說都是模糊的。爲了避免混淆,POSIX將規範中「字符」的所有引用都改爲「字節」。 –

+0

非常感謝。我想我已經找到了關鍵點,那就是*字段寬度*控制輸出寬度,如果產生更少的字節,則使用默認的右對齊和左側的空格填充輸出寬度,並且* Precision *控制最小數量的數字輸出。 –

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

是相同

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

這只是提供動態格式的方式。

0

這是glibc中printf的源代碼

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

}

正如你所看到的printf從va_list的

這裏得到的參數是另一個例子,向您展示如何printf的作品:

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