printf , fprintf , sprintf , snprintf , wsprintf , vprintf , vfprintf , vsprintf , vwsprintf 或 vdprintf 子例程
用途
打印格式化输出。
库
标准 C 库 (libc.a) 或具有 128 位长双打的标准 C 库 (libc128.a)
语法
#include <stdio.h>
int printf (Format, [Value, ...])
const char *Format;
int fprintf (Stream, Format, [Value, ...])
FILE *Stream;
const char *Format;
int sprintf (String, Format, [Value, ...])
char *String;
const char *Format;
int snprintf (String, Number, Format, [Value, . . .])
char *String;
int Number;
const char *Format; #include <stdarg.h>
int vprintf (Format, Value)
const char *Format;
va_list Value;
int vfprintf (Stream, Format, Value)
FILE *Stream;
const char *Format;
va_list Value;
int vsprintf (String, Format, Value)
char *String;
const char *Format;
va_list Value;
int vdprintf (fildes, Format, Value);
int fildes;
const char *Format;
va_list Value; #include <wchar.h>
int vwsprintf (String, Format, Value)
wchar_t *String;
const char *Format;
va_list Value;
int wsprintf (String, Format, [Value, ...])
wchar_t *String;
const char *Format; 描述
printf 子例程在 Format 参数的控制下将 Value 参数值转换,格式化和写入标准输出流。 printf 子例程提供用于处理代码点和 wchar_t 宽字符代码的转换类型。
fprintf 子例程在 Format 参数的控制下将 Value 参数值转换,格式化和写入 Stream 参数指定的输出流。 此子例程提供用于处理代码点和 wchar_t 宽字符代码的转换类型。
sprintf 子例程在 Format 参数的控制下将 Value 参数值转换,格式化和存储为连续字节,从 String 参数指定的地址开始。 sprintf 子例程在末尾放置一个空字符 (\0)。 您必须确保有足够的存储空间可用于包含格式化字符串。 此子例程提供用于处理代码点和 wchar_t 宽字符代码的转换类型。
snprintf 子例程在 Format 参数的控制下将 Value 参数值转换,格式化和存储为从 String 参数指定的地址开始的连续字节。 snprintf 子例程在末尾放置一个空字符 (\0)。 您必须确保有足够的存储空间可用于包含格式化字符串。 此子例程提供用于处理代码点和 wchar_t 宽字符代码的转换类型。 snprintf 子例程与 sprintf 子例程相同,添加了 Number 参数,该参数说明了 String 参数所引用的缓冲区的大小。
wsprintf 子例程在 Format 参数的控制下将 Value 参数值转换,格式化和存储为从 String 参数指定的地址开始的连续 wchar_t 字符。 wsprintf 子例程在末尾放置空字符 (\0)。 调用进程应确保有足够的存储空间可用于包含格式化字符串。 字段宽度单位指定为 wchar_t 字符数。 wsprintf 子例程与 printf 子例程相同,但 wsprintf 子例程的 String 参数使用 wchar_t 宽字符代码字符串。
上述所有子例程都通过使用 varargs 宏的可变长度参数工具来调用 _doprnt 子例程来工作。
vdprintf, vprintf, vfprintf, vsprintf和 vwsprintf 子例程格式化并写入 varargs 宏参数列表。 这些子例程分别与 drpintf, printf, fprintf, sprintf, snprintf和 wsprintf 子例程相同,只是它们未使用可变数目的参数进行调用。 而是使用 varargs 宏定义的参数列表指针来调用它们。
参数
- 编号
- 指定要复制或变换的字符串中的字节数。
- VALUE
- 指定直接映射到 Format 参数中的对象的 0 或更多参数。
- 流
- 指定输出流。
- String
- 指定起始地址。
- 格式
- 包含两种类型对象的字符串:
- 纯字符,复制到输出流。
- 转换规范,每个规范都会导致从 值 参数列表中检索 0 或更多项。 对于 vprintf, vfprintf, vsprintf和 vwsprintf 子例程,每个转换规范都会导致从 varargs 宏参数列表中检索 0 或更多项。
如果 Value 参数列表没有包含足够的 Format 参数项,那么结果不可预测。 如果在处理完整个 Format 参数之后仍有更多参数,那么子例程将忽略这些参数。
Format 参数中的每个转换规范都具有以下元素:
- A% (百分号)。
- 0 或更多选项,用于修改转换规范的含义。 选项字符和它们的含义是:
- '
- 格式化由 i, d, u, f, g 和 G 十进制转换生成的整数部分,并使用 千和 sep 分组字符。 对于其他转换,行为未定义。 此选项使用非货币分组字符。
- -
- 左对齐字段中的转换结果。
- +
- 使用 + (加号) 或-(减号) 开始有符号转换的结果。
- 空格字符
- 如果有符号转换的第一个字符不是符号,那么将空格字符作为结果的前缀。 如果同时出现空格字符和 + 选项字符,那么将忽略空格字符选项。
- #
- 将值转换为备用格式。 对于 c, d, s和 u 转换,此选项无效。 对于 o 转换,它将提高精度以强制结果的第一个数字为 0。 对于 x 和 X 转换,非零结果具有 0x 或 0X 前缀。 对于 e, E, f, g和 G 转换,结果始终包含小数点,即使后面没有数字。 对于 g 和 G 转换,不会从结果中除去尾部 0。
- 重大安全事件数量
- 对于 d, i, o, u, x, X, e, E, f, g和 G 转换,使用前导 0 (遵循任何符号或基本指示) 来填充字段宽度; 字段不是空格填充的。 如果同时显示 0 和 - 选项,那么将忽略 0 选项。 对于 d, i, o u, x和 X 转换,如果指定了精度,那么还将忽略 0 选项。 如果同时显示 0 和 " " 选项,那么将在填充字段之前插入分组字符。 对于其他转换,结果不可靠。
- B
- 指定 no-op 字符。
- n
- 指定 no-op 字符。
- J
- 指定 no-op 字符。
- 可选十进制数字字符串,用于指定最小字段宽度。 如果转换值字符少于字段宽度,该字段将从左到右按指定的字段宽度填充。 如果指定了 - (左对齐) 选项,那么将在右侧填充该字段。
- 可选精度。 精度为 。 (点) 后跟十进制数字字符串。 如果未指定精度,那么缺省值为 0。 精度指定以下限制:
- 要对 d, i, o, u, x或 X 转换显示的最小位数。
- 要在 e, E和 f 转换的小数点后显示的位数。
- g 和 G 转换的最大有效位数。
- 要从 s 和 S 转换中的字符串打印的最大字节数。
- 要从 S 转换打印的从 wchar_t 数组转换的最大字节数。 仅打印完整字符。
- 可选 l (小写 L) , ll (小写 LL) , h或 L 说明符指示下列其中一项:
- 可选 h ,指定后续的 d, i, u, o, x或 X 转换说明符应用于 short int 或 unsigned short int Value 参数 (该参数将根据积分促销进行提升, 其值将在打印前转换为 short int 或 unsigned short int 。
- 可选 h ,用于指定后续 n 转换说明符应用于指向 short int 参数的指针。
- 可选 l (小写 L) ,用于指定后续 d, i, u, o, x或 X 转换说明符适用于 long int 或 unsigned long int 参数。
- 可选 l (小写 L) ,指定后续 n 转换说明符应用于指向 long int 参数的指针。
- 可选 ll (小写 LL) ,指定后续 d, i, u, o, x或 X 转换说明符适用于 long long long int 或 unsigned long long int 参数。
- 可选 ll (小写 LL) ,指定后续 n 转换说明符应用于指向 long long int 参数的指针。
- 可选的 L ,用于指定以下 e, E, f, g或 G 转换说明符适用于 long double 参数。 如果与 libc.a链接,那么 long double 与 double (64bits) 相同。 如果与 libc128.a 和 libc.a链接,那么 long double 为 128 位。
- 可选的 H, D或 DD 说明符指示下列其中一个转换:
- 可选的 H ,指定以下 e, E, f, F, g或 G 转换说明符适用于 _Decimal32 参数。
- 可选的 D ,指定以下 e, E, f, F, g或 G 转换说明符适用于 _Decimal64 参数。
- 可选的 DD ,指定以下 e, E, f, F, g或 G 转换说明符适用于 _Decimal128 参数。
- 可选的 vl, lv, vh, hv 或 v 说明符指示下列其中一个向量数据类型转换:
- 可选 v ,指定以下 e, E, f, g, G, a或 A 转换说明符适用于 vector float 参数。 它使用一个自变量,并将数据解释为由四个 4 字节的浮点组件组成的系列。
- 可选的 v ,指定以下 c, d, i, u, o, x或 X 转换说明符适用于 vector signed char, vector unsigned char或 vector bool char 参数。 它使用一个自变量,并将数据解释为一系列十六个 1 字节的组件。
- 可选的 vl 或 lv ,指定以下 d, i, u, o, x或 X 转换说明符适用于 vector signed int, vector unsigned int或 vector bool 参数。 它使用一个自变量,并将数据解释为由四个 4 字节的整数组件组成的序列。
- 可选的 vh 或 hv ,指定以下 d, i, u, o, x或 X 转换说明符适用于 vector signed short 或 vector unsigned short 参数。 它使用一个自变量,并将数据解释为由 8 个 2 字节整数组件组成的系列。
- 对于前面的任何说明符,可以在向量大小说明符之前指定可选的分隔符。 如果未指定分隔符,那么除非转换为 c(在这种情况下,缺省分隔符为空) ,否则缺省分隔符为空格。 受支持的可选分隔符集为
,(逗号) ,;(分号) ,:(冒号) 和_(下划线)。
- 以下字符指示要应用的转换类型:
- %
- 不进行转换。 打印 (%)。
- d 或 i
- 接受指定整数的 Value 参数,并将其转换为带符号的十进制表示法。 精度指定要显示的最小位数。 如果要转换的值可以用更少的数字表示,那么将使用前导 0 对其进行扩展。 缺省精度为 1。 转换精度为 0 的值 0 的结果是空字符串。 指定以 0 作为前导字符的字段宽度会导致使用前导 0 填充字段宽度值。
- u
- 接受指定无符号整数的 Value 参数,并将其转换为无符号十进制表示法。 精度指定要显示的最小位数。 如果要转换的值可以用更少的数字表示,那么将使用前导 0 对其进行扩展。 缺省精度为 1。 转换精度为 0 的值 0 的结果是空字符串。 指定以 0 作为前导字符的字段宽度会导致使用前导 0 填充字段宽度值。
- o
- 接受指定无符号整数的 Value 参数,并将其转换为无符号八进制表示法。 精度指定要显示的最小位数。 如果要转换的值可以用更少的数字表示,那么将使用前导 0 对其进行扩展。 缺省精度为 1。 转换精度为 0 的值 0 的结果是空字符串。 指定以 0 作为前导字符的字段宽度会导致使用前导 0 填充字段宽度值。 不用八进制值表示字段宽度。
- x 或 X
- 接受指定无符号整数的 Value 参数,并将其转换为无符号十六进制表示法。 字母 abcdef 用于 x 转换,字母 ABCDEF 用于 X 转换。 精度指定要显示的最小位数。 如果要转换的值可以用更少的数字表示,那么将使用前导 0 对其进行扩展。 缺省精度为 1。 转换精度为 0 的值 0 的结果是空字符串。 指定以 0 作为前导字符的字段宽度会导致使用前导 0 填充字段宽度值。
- f
- 接受指定双精度值的 Value 参数,并将其转换为格式为 [-]ddd.ddd的十进制表示法。 小数点后的位数等于精度规范。 如果未指定精度,那么将输出 6 位数字。 如果精度为 0 ,那么不会显示小数点。
- e 或 E
- 接受指定双精度值的 Value 参数,并将其转换为指数形式 [-]d.ddde+/-dd。 小数点前存在一个数字,小数点后的位数等于精度规范。 精度规范可以在 0-17 位的范围内。 如果未指定精度,那么将输出 6 位数字。 如果精度为 0 ,那么不会显示小数点。 E 转换字符生成一个带有 E 的数字,而不是在指数之前生成 e 。 指数通常至少包含两个数字。
- g 或 G
- 接受指定双精度值的 值 参数,并将其转换为 e, E或 f 转换字符的样式,其精度指定有效位数。 将从结果中除去尾部 0。 仅当小数点后跟数字时,才会显示该小数点。 使用的样式取决于转换的值。 只有当转换后的指数小于-4,或大于或等于精度时,才会产生样式 e(E,如果使用的标志是G)。 如果显式精度为 0 ,那么会将其视为 1。
- c
- 接受并打印 Value 参数,指定转换为 unsigned char 数据类型的整数。
- C
- 接受并打印指定 wchar_t 宽字符代码的 Value 参数。 由 Value 参数指定的 wchar_t 宽字符代码将转换为表示字符的字节数组并写入该字符; 使用 wsprintf 子例程时,将不进行转换而写入 Value 参数。
- 请
- 接受 Value 参数作为字符串 (字符指针) ,并打印字符串中的字符,直到迂到空字符 (\0) 或达到精度指示的字节数为止。 如果未指定精度,那么将打印直至第一个空字符的所有字节。 如果 Value 参数指定的字符串指针具有空值,那么结果不可靠。
- 六
- 接受相应的 Value 参数作为指向 wchar_t 字符串的指针。 将打印字符串中的字符 (不进行转换) ,直到迂到空字符 (\0) 或达到精度指示的宽字符数为止。 如果没有指定精度,显示全部字符直到出现第一个空字符。 如果 Value 参数指定的字符串指针的值为空,那么结果不可靠。
- p
- 接受指向 void 的指针。 将指针的值转换为可打印字符序列,与无符号十六进制 (x) 相同。
- n
- 接受一个指向整数的指针,在该整数中写入此调用写入输出流的字符数 (在 wsprintf 子例程的情况下为宽字符代码)。 未转换任何参数。
字段宽度或精度可以用 * (星号) 而不是数字字符串表示。 在这种情况下,整数 值 参数提供字段宽度或精度。 在达到转换字母之前,不会检索为输出转换的 值 参数,因此指定字段宽度或精度的参数必须出现在要转换的值 (如果有) 之前。
如果转换的结果比字段宽度宽,那么将扩展该字段以包含转换的结果,并且不会发生截断。 但是,较小的字段宽度或精度会导致右侧截断。
printf, fprintf, sprintf, snprintf, wsprintf, vprintf, vfprintf, vsprintf或 vwsprintf 子例程允许在输出字符串中插入依赖于语言的基数字符。 该基数字符由程序语言环境的 LC_NUMERIC 类别中特定于语言的数据定义。 在 C 语言环境中,或者在未定义基数字符的语言环境中,基数字符缺省为 a。 (点)。
在成功运行任何这些子例程之后,并且在下一次成功完成对同一流上的 fclose 或 fflush 子例程或对 exit 或 abort 子例程的调用之前,st_ctime和st_mtime将该文件的字段标记为待更新。
e, E, f, g和 G 转换说明符表示特殊浮点值,如下所示:
| 项 | 描述 |
|---|---|
| 安静 NaN | +NaNQ或-NaNQ |
| 发信号 NaN | +NaNS或-NaNS |
| +/-INF | + INF 或 -INF |
| +/-0 | +0 或-0 |
+ (加号) 的表示取决于是否指定了 + 或空格字符格式化选项。
这些子例程可以处理使系统能够按变量顺序处理参数列表的元素的格式字符串。 在这种情况下,正常转换字符% (百分号) 将替换为 %数字$,其中 数字 是从 1 到 NL_ARGMAX 值范围内的十进制数字。 然后,转换将应用于指定的自变量,而不是应用于下一个未使用的自变量。 此功能部件以适合于特定语言的顺序提供格式字符串的定义。 使用变量排序时,精度字段宽度的 * (星号) 规范将替换为 %位$。 如果使用变量排序功能,那么必须为所有转换指定该功能。
以下条件适用:
- 传递到 NLS 扩展的格式可以包含转换的格式,也可以包含显式或隐式参数编号。 但是,除了 %% (双百分号) 之外,不能在单个格式字符串中混合这些格式。
- n 值必须没有前导零。
- 如果使用 %n$ ,那么必须使用 %1$ 到 %n- 1$ (含)。
- %n$ 中的 n 在从 1 到 NL_ARGMAX 值 (含) 的范围内。 请参阅 limits.h 文件,以获取有关 NL_ARGMAX 值的更多信息。
- 可以根据需要多次引用自变量列表中编号的自变量。
- 不允许使用变量顺序 %n$ 格式的字段宽度或精度的 * (星号) 规范; 而是使用 *m$ 格式。
返回值
成功完成时, printf, fprintf, vprintf和 vfprintf 子例程将返回传输的字节数 (对于 sprintf和 vsprintf 子例程,不包括空字符 [\0])。 如果迂到错误,那么将输出负值。
成功完成时, snprintf 子例程将返回写入 String 参数的字节数 (不包括终止的空字节)。 如果由于输出超过了 Number 参数的长度而废弃了输出字符,那么 snprintf 子例程将返回如果 Number 参数足够大 (不包括终止的空字节) 就会写入 String 参数的字节数。
成功完成后, wsprintf 和 vwsprintf 子例程将返回传输的宽字符数 (不包括宽字符空字符 [\0])。 如果迂到错误,那么将输出负值。
错误代码
printf, fprintf, sprintf, snprintf或 wsprintf 子例程不成功 (如果 Stream 参数指定的文件未缓冲或需要清空缓冲区,并且下列其中一个或多个为 true):
| 项 | 描述 |
|---|---|
| 再次 | O_NONBLOCK 或 O_NDELAY 标志是为 Stream 或 String 参数指定的文件底层的文件描述符设置的,进程将在写操作中延迟。 |
| EBADF | Stream 或 String 参数指定的文件下的文件描述符不是打开用于写入的有效文件描述符。 |
| EFBIG | 尝试写入超过此进程的文件大小限制或最大文件大小的文件。 有关更多信息,请参阅 ulimit 子例程。 |
| EINTR | 写操作由于接收到信号而终止,并且未传输任何数据或未报告部分传输。 注: 根据应用程序绑定到的库例程,此子例程可能返回 EINTR。 请参阅有关 sa_restart的 signal 子例程。
|
| 项 | 描述 |
|---|---|
| EIO | 该进程是尝试对其控制终端执行写操作的后台进程组的成员,设置了 TOSTOP 标志,该进程既不忽略也不阻塞 SIGTTOU 信号,并且该进程的进程组没有父进程。 |
| ENOSPC | 包含该文件的设备上没有保留可用空间。 |
| EOVERFLOW | 在 UNIX03 方式下,如果 Number 参数的值大于 INT_MAX的值,那么 snprintf 或 vsnprintf 子例程不成功。 注: 如果 XPG_SUS_ENV 环境变量的值设置为 ON ,那么将启用 UNIX03 行为。
|
| EPIPE | 尝试写入管道或先进先出 (FIFO) ,但未打开该管道或先进先出 (FIFO) 以供任何进程读取。 向进程发送 SIGPIPE 信号。 |
如果下列其中一个或多个为 true ,那么 printf, fprintf, sprintf, snprintf或 wsprintf 子例程可能不成功:
| 项 | 描述 |
|---|---|
| EILSEQ | 检测到无效字符序列。 |
| EINVAL | Format 参数接收到的自变量不足。 |
| ENOMEM | 存储空间不足。 |
| ENXIO | 对不存在的设备发出了请求,或者该请求超出了该设备的能力范围。 |
示例
以下示例演示如何使用 vfprintf 子例程来编写错误例程:
#include <stdio.h>
#include <stdarg.h>
/* The error routine should be called with the
syntax: */
/* error(routine_name, Format
[, value, . . . ]); */
/*VARARGS0*/
void error(char *fmt, . . .);
/* ** Note that the function name and
Format arguments cannot be **
separately declared because of the **
definition of varargs. */ {
va_list args;
va_start(args, fmt);
/*
** Display the name of the function
that called the error routine */
fprintf(stderr, "ERROR in %s: ",
va_arg(args, char *)); /*
** Display the remainder of the message
*/
fmt = va_arg(args, char *);
vfprintf(fmt, args);
va_end(args);
abort(); }