printf, fprintf, sprintf, snprintf, vprintf, vfprintf, vsprintf, vsnprintf - 輸出格式轉換


總覽 (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 參數 生成 輸出內容. printfvprintf 函數 把 輸出內容 寫到 stdout, 即 標准輸出流; fprintfvfprintf 函數 把 輸出內容 寫到 給定的 stream 流; sprintf, snprintf, vsprintfvsnprintf 函數 把 輸出內容 存放到 字符串 str 中.

這些 函數 由 格式字符串 format 參數 控制 輸出內容, 它 指出 怎么樣 把 后面的 參數 (或 通過 stdarg(3) 的 變長參數機制 訪問的 參數) 轉換成 輸出內容.

這些 函數 返回 打印的 字符 數量 (不包括 字符串 結尾用的 `\0'). snprintfvsnprintf 的 輸出 不會 超過 size 字節 (包括了 結尾的 `\0'), 如果 因為 這個 限制 導致 輸出內容 被截斷, 則 函數 返回 -1.

格式字符串 (format 參數) 由 零到多個 指令 組成: 普通字符 (除 % 外), 它們 被 原封不動的 送到 輸出流; 以及 格式轉換說明 (conversion specification), 每個 格式轉換說明 都會 從后面 提取 零到多個 參數. 格式轉換說明 由 % 字符 引導開始. 參數 必須 正確的 對應到 格式轉換符 (conversion specifier) 上. 下述 字符 按順序 列在 % 后面:

*
零個 或 多個 下列 標志:
#
指出 數值 應該 轉換成 "其他形式". 對於 c, d, i, n, p, s, 和 u 格式轉換, 這個選項 沒有 影響. 對於 o 格式轉換, 數值的 精度 被提高, 使 輸出字符串的 第一個 字符 為零 (除非 打印 一個零值 時, 明確 定義 精度 為零). 對於 xX 格式轉換, 非零數值 前面 會添加 `0x' 字符串 (或 X 格式轉換 的 `0X' 字符串). 對於 e, E, f, g, 和 G 格式轉換, 其結果 始終 含有一個 十進制小數點, 即使 后面 沒有 數字 (一般說來, 只有當 格式轉換 后, 小數點 后面 有數字時 才顯示 小數點). 對於 gG 格式轉換, 將不刪去 結果末尾的 零, 其他情況下 這些 零 應該 刪掉.
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 格式轉換 小數點 后面 顯示的 位數, gG 格式轉換 顯示的 最大有效位數(significant digits), 或 s 格式轉換 打印 某個 字符串的 最多 字符數目.
*
可選的 字符 h, 指出 后面的 d, i, o, u, x, 或 X 格式轉換 對應為 short intunsigned short int 的 參數, 或者是 后面的 n 格式轉換 對應為 指向 short int 參數 的 指針.
*
可選的 字符 l (ell) 指出 后面的 d, i, o, u, x, 或 X 格式轉換 應用到 指向 long intunsigned 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 形 (或 合適的 變量) 參數 轉換輸出為 有符號十進制數 ( di), 無符號八進制數 ( o), 無符號十進制數 ( u), 或者 無符號十六進制數 ( xX). x 格式轉換 用 小寫字母 abcdef ; X 格式轉換 用 大寫字母 ABCDEF . 精度值 (如果給出) 指出 必須顯示的 最少 數字; 如果 轉換結果 少於 這個 要求, 則用 零 填補 轉換結果 的 左邊.
eE
double 參數 舍入后 轉換為 [-]d .ddd e\*(Pmdd 的 格式, 這個格式 的 小數點 前面 有 一位 數字, 后面 表示 精度; 如果沒有 指出 精度, 則意味着 精度是 6; 如果 精度 是 0, 則不顯示 小數點. E 格式轉換 使用 字母 E (而不是 e) 要求 引入 指數. 指數 至少 包含 兩個 數字; 如果 值 是 零, 則 指數 是 00.
f
double 參數 舍入后 轉換為 [-]ddd .ddd 的 十進制 表達式, 這個格式 小數點 后面 的 數字 表示 精度. 如果 沒有 指出 精度, 則意味着 精度是 6; 如果 顯式 給出 精度 是 0, 則不顯示 小數點. 如果 顯示了 小數點, 則 小數點 前面 至少有 一位 數字.
g
double 參數 以 fe (或者 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' 格式 顯示 日期, 其中 weekdaymonth 是 字符串指針:

#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'') 標准.

qBSD 4.4long long 形 的 標志, 而 整數格式轉換 的 llL 是 GNU 的 標志.

這些 函數 的 Linux 版本 基於 GNU libio 庫. 有關細節 可以 查看 GNU libc (glibc-1.08)info 文檔.

BUGS

在 Linux 下 某些 浮點格式轉換 會導致 內存泄露.

這些函數 都遵循 完整的 ANSI C3.159-1989, 但是 提供了 附加的 q, Z' 標志, 並給了 Ll 標志 更多的 特性. 后者 可能會 被認為 是 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.

因為 sprintfvsprintf 不設定 字符串的 長度, 調用者 必須小心 別讓它 從 有效空間 溢出; 這一點通常 不能 保證. 

打賞

免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2022 CODEPRJ.COM