中的printf

<C陷阱與缺陷>中關於printf

1. 格式符
%g, %f, %e這3個格式項用於打印浮點值。%g格式項用於打印那些不需要按列對齊的浮點數特別有用。它在打印出對應的數值時,會去掉該數值尾綴的零,保留6位有效數字
printf("PI = %g\n", 4 * atan(1.0));
PI = 3.14159  (共6位有效數字,不包括小數點和前綴0)

printf("%g %g %g %g %g\n", 1/1.0, 1/2.0, 1/3.0, 1/4.0, 0.0);
將打印出1 0.5 0.333333 0.25 0  (注意0.3333333共6位有效數字,不包括前綴0和小數點)
printf("%g\n", 2/3.0); => 0.666667  (數值進行四捨五入)

如果一個數的絕對值大於999999,按%g的格式打印出這個數將會超過6位有效數字,故它會採用科學計數法的方法打印。
printf("%g\n", 123456789.0); => 1.23457e+08  (基數部分有6位有效數字)
對於比較小的數值,除非該數的指數小於或等於-5,%g格式項纔會採用科學計數法來表示。因此
printf("%g %g %g\n", 3.14159e-3, 3.14159e-4, 3.14159e-5);
=> 0.00314159 0.000314159 3.14159e-5

%e格式項用於打印浮點數,要求一律顯式地使用指數形式:PI在使用%e格式項時將被寫成3.141593e+00。%e格式項將打印出小數點後6位有效數字,而並非如%g格式項打印出的數總共6位有效數字。
%f跟%e一樣,即小數點後6位有效數字。

2. 修飾符
printf函數也接受輔助字符來修飾一個格式項的含義。這些輔助字符出現在%符號和後面的格式碼之間。
整數有3種不同類型,對應3種不同長度: short,long和正常長度。如果一個short整數作爲任何一個函數的參數出現,它會被自動的擴展爲一個正常長度的整數。(K&R C)

寬度修飾符對所有的格式碼都有效,甚至%%也不例外。因此,例如printf(%8%\n"); 8個%
精度修飾符的作用是控制一個數值的表示中將要出現的數字位數,或者用於限制將要打印的字符串中應該出現的字符數。精度修飾符包括一個小數點,和小數點後面的一串數字。精度修飾符出現在%符號和寬度修飾符之後,格式碼與長度修飾符之前。
1) 對於整數格式項%d, %o, %x和%u,精度修飾符指定了打印數字的最小位數。如果不夠位數,則會自動補0
printf(%.2d/%.2d/%.4d\n", 7, 14, 1789); => 07/14/1789
2) 對於%e, %E, 和%f格式項,精度修飾符指定了小數點後應該出現的數字位數
3) 對於%g和%G格式項,精度修飾符指定了打印數值中的有效數字位數。除非另有說明,非有效數字的0將被去除,如果小數點後不跟數字則小數點也被刪除。
printf("%.1g %.2g %.4g %.8g\n", 10/3.0, 10/3.0, 10/3.0, 10/3.0);
=> 3 3.3 3.333 3.333333
4) 對於%c和%%格式項,精度修飾符將被忽略

3. 標誌
1) ‘-’操作,左對齊
2) '+'操作,規定每個待打印的數值在輸出時都應該以它的符號作爲第一個字符。故正數會打印“+”, 負數會打印“-",0則不輸出。
3) 空白字符作爲標誌字符時,含義是如果某數是一個非負數,就在它前面插入一個空白字符。如果標誌字符+和空白字符同時出現一個格式項中,最終的效果是以標誌字符+爲準。
for (int i = -3; i <= 3; i++) 
    printf("% d\n", i);
-3
-2
-1
 0
 1
 2
 3

4. 可變域寬與精度
printf("%*.*s\n", 12, 5, str);
這個式子將打印出字符串str的前5個字符或更少,前面將填充若干空白字符以達到總共打印12個字符的要求。
printf("%*%\n", n);
上式將在寬度爲n個字符的域內以右端對齊的方式打印出一個%符號。換言之,先打印n-1個空白字符,後面再跟一個%符號。

varargs.h中的宏實現(K&R C)
typdef char* va_list;
#define va_dcl int va_alist;
#define va_start(list) list = (char*)&va_alist
#define va_end(list)
#define va_arg(list, mode) \
    ((mode *)(list += sizeof(mode)))[-1]

#include <varargs.h>
void error(va_alist) va_dcl

int printf(va_alist) va_dcl
{
    va_list ap;
    char* format;
    int n;
    
    va_start(ap);
    format = va_arg(ap, char*);
    n = vprintf(format, ap);
    va_end(ap);
    return n;
}






發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章