總覽 (SYNOPSIS)
#include <stdio.h>
int printf(const char *format, ...);
int fprintf(FILE *stream, const char *format, ...);
int sprintf(char *str, const char *format, ...);
int snprintf(char *str, size_t size, const char *format, ...);
#include <stdarg.h>
int vprintf(const char *format, va_list ap);
int vfprintf(FILE *stream, const char *format, va_list ap);
int vsprintf(char *str, const char *format, va_list ap);
int vsnprintf(char *str, size_t size, const char *format, va_list ap);
描述 (DESCRIPTION)
printf 系列 函數 根據 下述的 format 參數 生成 輸出內容. printf 和 vprintf 函數 把 輸出內容 寫到 stdout, 即 標准輸出流; fprintf 和 vfprintf 函數 把 輸出內容 寫到 給定的 stream 流; sprintf, snprintf, vsprintf 和 vsnprintf 函數 把 輸出內容 存放到 字符串 str 中.
這些 函數 由 格式字符串 format 參數 控制 輸出內容, 它 指出 怎么樣 把 后面的 參數 (或 通過 stdarg(3) 的 變長參數機制 訪問的 參數) 轉換成 輸出內容.
這些 函數 返回 打印的 字符 數量 (不包括 字符串 結尾用的 `\0'). snprintf 和 vsnprintf 的 輸出 不會 超過 size 字節 (包括了 結尾的 `\0'), 如果 因為 這個 限制 導致 輸出內容 被截斷, 則 函數 返回 -1.
格式字符串 (format 參數) 由 零到多個 指令 組成: 普通字符 (除 % 外), 它們 被 原封不動的 送到 輸出流; 以及 格式轉換說明 (conversion specification), 每個 格式轉換說明 都會 從后面 提取 零到多個 參數. 格式轉換說明 由 % 字符 引導開始. 參數 必須 正確的 對應到 格式轉換符 (conversion specifier) 上. 下述 字符 按順序 列在 % 后面:
- *
-
零個 或 多個 下列 標志:
-
- #
- 指出 數值 應該 轉換成 "其他形式". 對於 c, d, i, n, p, s, 和 u 格式轉換, 這個選項 沒有 影響. 對於 o 格式轉換, 數值的 精度 被提高, 使 輸出字符串的 第一個 字符 為零 (除非 打印 一個零值 時, 明確 定義 精度 為零). 對於 x 和 X 格式轉換, 非零數值 前面 會添加 `0x' 字符串 (或 X 格式轉換 的 `0X' 字符串). 對於 e, E, f, g, 和 G 格式轉換, 其結果 始終 含有一個 十進制小數點, 即使 后面 沒有 數字 (一般說來, 只有當 格式轉換 后, 小數點 后面 有數字時 才顯示 小數點). 對於 g 和 G 格式轉換, 將不刪去 結果末尾的 零, 其他情況下 這些 零 應該 刪掉.
- 0
- 指出 用零 填充 結果. 所有的 格式轉換, 除了 n, 轉換結果 的 左邊 用零 填充, 而不是 空格. 如果 數值轉換 時 給定了 精度, ( d, i, o, u, i, x, 和 X), 則 忽略 0 標志.
- -
- (負位寬標志) 指出 轉換結果 必須 在 位邊界 上 向左邊 對齊. 除了 n 格式轉換, 轉換結果 的 右邊 用空格 填充, 而不是 在左邊 填充 空格或零. 如果 同時 給出了 - 和 0 , 則 - 覆蓋 0 .
- ' '
- (空格) 指出 在 通過 有符號數(signed) 格式轉換 ( d, e, E, f, g, G, 或 i ) 產生的 正數 前面 留一個 空格.
- +
- 指出 有符號數 格式轉換 產生的 結果 前面 始終 有一個 正負符號. 如果 同時 給出了 + 和 空格, 則 + 覆蓋 空格.
- '
- 指出 在 數字 參數 中, 如果 locale 給出 相關信息, 輸出結果 將被 分組. 注意, 許多 版本 的 gcc 不能 理解 這個選項, 因而會 產生 一個警告.
- *
- 一個 可選的 十進制數, 指出 最小的 位寬. 如果 格式轉換后 產生的 字符數少於 位寬, 則 左邊 用 空格 填充 (或者 填充 右邊, 如果 給出了 向左對齊標志), 直到 填滿 指定的 位寬.
- *
- 一個 可選的 精度, 格式是 一個 句號(`.') 后面 跟着 一個 可選的 數字. 如果 沒有 給出 這個 數字, 則 精度 取為 零. 這樣就 指定了 d, i, o, u, x, 和 X 格式轉換 顯示的 最小位數, e, E, 和 f 格式轉換 小數點 后面 顯示的 位數, g 和 G 格式轉換 顯示的 最大有效位數(significant digits), 或 s 格式轉換 打印 某個 字符串的 最多 字符數目.
- *
- 可選的 字符 h, 指出 后面的 d, i, o, u, x, 或 X 格式轉換 對應為 short int 或 unsigned short int 的 參數, 或者是 后面的 n 格式轉換 對應為 指向 short int 參數 的 指針.
- *
- 可選的 字符 l (ell) 指出 后面的 d, i, o, u, x, 或 X 格式轉換 應用到 指向 long int 或 unsigned long int 參數 的 指針, 或者 后面的 n 格式轉換 對應為 指向 long int 參數 的 指針. Linux 提供 和 ANSI 不兼容 的 雙 l 標志, 作為 q 或 L 的 同義詞. 因此 ll 可以 結合 浮點格式轉換 使用. 但是 強烈 反對 這個 用法.
- *
- 字符 L 指出 后面的 e, E, f, g, 或 G 格式轉換 對應 long double 參數, 或者 讓 后面的 d, i, o, u, x, 或 X 格式轉換 對應 long long 參數. 注意 long long 沒有在 ANSI C 中 聲明, 因此 不能夠 移植到 所有的 體系平台 上.
- *
- 可選的 字符 q 等於 L. 參考 STANDARDS 和 BUGS 節 關於 ll, L, 和 q 的 敘述.
- *
- 字符 Z 指出 后面的 整數 ( d, i, o, u, x, 或 X) 格式轉換 對應 size_t 參數.
- *
- 指出 采用 格式轉換類型 的 字符.
可以 用 星號 `*' 代替 數字 指定 域寬 或 精度, 也可以 兩者 同時 指定. 這種情況下 要求 用一個 int 參數 指出 域寬 或 精度. 負域寬 被認為是 正域寬 跟在 向左對齊標志 后面; 負精度 被認為是 精度 丟失.
格式轉換符(specifier) 及其 含義 如下:
- diouxX
- 將 int 形 (或 合適的 變量) 參數 轉換輸出為 有符號十進制數 ( d 和 i), 無符號八進制數 ( o), 無符號十進制數 ( u), 或者 無符號十六進制數 ( x 和 X). x 格式轉換 用 小寫字母 abcdef ; X 格式轉換 用 大寫字母 ABCDEF . 精度值 (如果給出) 指出 必須顯示的 最少 數字; 如果 轉換結果 少於 這個 要求, 則用 零 填補 轉換結果 的 左邊.
- eE
- 將 double 參數 舍入后 轉換為 [-]d .ddd e\*(Pmdd 的 格式, 這個格式 的 小數點 前面 有 一位 數字, 后面 表示 精度; 如果沒有 指出 精度, 則意味着 精度是 6; 如果 精度 是 0, 則不顯示 小數點. E 格式轉換 使用 字母 E (而不是 e) 要求 引入 指數. 指數 至少 包含 兩個 數字; 如果 值 是 零, 則 指數 是 00.
- f
- 將 double 參數 舍入后 轉換為 [-]ddd .ddd 的 十進制 表達式, 這個格式 小數點 后面 的 數字 表示 精度. 如果 沒有 指出 精度, 則意味着 精度是 6; 如果 顯式 給出 精度 是 0, 則不顯示 小數點. 如果 顯示了 小數點, 則 小數點 前面 至少有 一位 數字.
- g
- 將 double 參數 以 f 或 e (或者 G 格式轉換的 E 標志) 的 形式 轉換. 其精度 指出 有符號數字 的 數目. 如果 沒有 指出精度, 則默認為 6; 如果 精度 是 零, 則按 1 處理. 如果 格式轉換后 其 指數 小於 -4 或者 大於等於 其精度, 則 使用 e 形式. 轉換結果 消除了 分數部分 末尾的 零; 小數點 前面 至少有 一位 十進制數字.
- c
- 將 int 參數 轉換為 unsigned char, 然后 輸出 對應的 字符.
- s
- 認為 `` char *'' 參數 是 指向 字符形數組 的 指針 (指向 字符串). Printf 輸出 數組內的 字符, 直到 遇上 (但不包括) 結束字符 NUL ; 如果 給出了 精度值, printf 不會 輸出 多於 這個值 的 字符, 也不需要 提供 NUL 結束符; 如果 沒有 給出 精度值, 或 精度值 大於 數組長度, 則 數組內一定要 包括 一個 NUL 字符.
- p
- 將以 十六進制數 打印 `` void *'' 指針參數 (就象是 %#x 或 %#lx).
- n
- 將 目前 已經 輸出的 字符數目 存儲在 `` int *'' (或變量) 指針參數 指向的 地址. 不轉換 任何參數.
- %
- 輸出 一個 '%'. 不轉換 任何參數. 完整的 寫法 是 `%%'.
不指定 域寬 或 偏小的 域寬 不會 導致 內容 被截斷; 如果 轉換結果 的 長度超過 其域寬, 則 域寬 會 擴大到 容下 完整的 結果.
示例 (EXAMPLES)
以 `Sunday, July 3, 10:02' 格式 顯示 日期, 其中 weekday 和 month 是 字符串指針:
-
#include <stdio.h> fprintf(stdout, "%s, %s %d, %.2d:%.2d\n", weekday, month, day, hour, min);
顯示 五位 十進制數:
-
#include <math.h> #include <stdio.h> fprintf(stdout, "pi = %.5f\n", 4 * atan(1.0));
分配 128 個 字節 的 字符串 空間 保存 打印 結果:
-
#include <stdio.h> #include <stdlib.h> #include <stdarg.h> char *newfmt(const char *fmt, ...) { char *p; va_list ap; if ((p = malloc(128)) == NULL) return (NULL); va_start(ap, fmt); (void) vsnprintf(p, 128, fmt, ap); va_end(ap); return (p); }
另見 (SEE ALSO)
printf(1), scanf(3)
標准 (STANDARDS)
fprintf, printf, sprintf, vprintf, vfprintf, 和 vsprintf 函數 遵循 ANSI C3.159-1989 (``ANSI C'') 標准.
q 是 BSD 4.4 對 long long 形 的 標志, 而 整數格式轉換 的 ll 或 L 是 GNU 的 標志.
這些 函數 的 Linux 版本 基於 GNU libio 庫. 有關細節 可以 查看 GNU libc (glibc-1.08) 的 info 文檔.
BUGS
在 Linux 下 某些 浮點格式轉換 會導致 內存泄露.
這些函數 都遵循 完整的 ANSI C3.159-1989, 但是 提供了 附加的 q, Z 和 ' 標志, 並給了 L 和 l 標志 更多的 特性. 后者 可能會 被認為 是 bug, 因為 它 改變了 ANSI C3.159-1989 中 定義的 特性.
用 零 填充 的 %p 格式轉換 (既可以用 0 標志, 也可以用 精度), 對 %n 和 %p 格式轉換 使用 # (即不處理), 以及 某些 不標准的 荒謬 組合; 這些 組合 應當 避免.
某些 ANSI C 定義 的 標志 組合 沒有 意義 (如 %Ld). 即使 在 Linux 機器上 定義的 比較好, 但是 其他 體系結構 不一定 有相同的 結果. 因此 最好 別用 While they may have a well-defined behaviour on Linux, this need not to be so on other architectures. Therefore it usually is better not to use flags that are not defined by ANSI C at all, i.e. use q instead of L in combination with diouxX conversions or ll.
q 的 用法 和 BSD 4.4 上 不一樣, 它 可能 用在 浮點格式轉換 上, 即等於 L.
因為 sprintf 和 vsprintf 不設定 字符串的 長度, 調用者 必須小心 別讓它 從 有效空間 溢出; 這一點通常 不能 保證.