printf ()- 打印格式化字符
格式
#include <stdio.h>
int printf(const char *format-string, argument-list);
语言级别
ANSI
线程安全
是
语言环境敏感
此函数的行为可能受当前语言环境的 LC_CTYPE 和 LC_NUMERIC 类别影响。 如果在编译命令中指定了 LOCALETYPE (*LOCALEUCS2) 或 LOCALETYPE (*LOCALEUTF) ,那么此行为也可能受当前语言环境的 LC_UNI_CTYPE 类别影响。 有关更多信息,请参阅 了解 CCSID 和语言环境。
描述
printf()
函数将一系列字符和值格式化并打印到标准输出流 stdout
。 格式规范 (以百分号 (%) 开头) 确定 format-string之后的任何 argument-list 的输出格式。 format-string 是以初始移位状态开始和结束的多字节字符串。
从左到右读取 format-string 。 找到第一个格式规范时,将根据格式规范转换并打印 format-string 之后的第一个自变量的值。 第二个格式规范导致转换和打印 format-string 之后的第二个自变量,以此类推,直到 format-string结束。 如果参数多于格式规范,那么将对额外的参数进行求值并将其忽略。 如果没有足够的自变量用于所有格式规范,那么未定义结果。
格式规范具有以下格式:
可以将转换应用于自变量列表中 format-string 之后的第 n 个自变量,而不是应用于下一个未使用的自变量。 在这种情况下,转换字符% 将替换为序列 %n$ ,其中 n 是 1 到 NL_ARGMAX 范围内的十进制整数,给出自变量在自变量列表中的位置。 此功能部件提供格式字符串的定义,这些字符串以适合于特定语言的顺序选择自变量。
作为替代方法,可以使用上图中概述的格式规范来分配自变量列表中的特定条目。 不能在对 printf()
的同一调用中混合使用此格式规范和先前的格式规范。 否则,可能会发生不可预测的结果。
arg-number 是正整数常量,其中 1 引用自变量列表中的第一个条目。 自变量数不能大于自变量列表中的条目数,否则结果未定义。 Arg-number 也不能大于 NL_ARGMAX。
在包含 %n$ 格式的转换规范的格式字符串中,可以根据需要多次从格式字符串引用参数列表中的编号参数。
在包含转换规范的 %n$ 格式的格式字符串中,字段宽度或精度可以由序列 * m$ 指示,其中 m 是 1 thru NL_ARGMAX 范围内的十进制整数,给出包含字段宽度或精度的整数自变量的自变量列表 (在格式自变量之后) 中的位置,例如:
printf("%1$d:%2$.*3$d:%4$.*3$d\n", hour, min, precision, sec);
格式字符串可以包含已编号的参数规范 (即 %n$ 和 * m$) 或未编号的参数规范 (即% 和 *) ,但通常不能同时包含两者。 唯一的例外是%% 可以与 %n$ 格式混合。 未定义在格式字符串中混合编号和未编号参数规范的结果。 使用编号自变量规范时,指定第 n 个自变量要求在格式字符串中指定从第一个自变量到第 (n-1) 个自变量的所有前导自变量。
格式规范的每个字段都是表示特定格式选项的单个字符或数字。 type 字符 (出现在最后一个可选格式字段之后) 确定是将关联的自变量解释为字符,字符串,数字还是指针。 最简单的格式规范仅包含百分号和 类型 字符 (例如, %s)。
- 字段
- 描述
- 标志
- 输出和打印符号,空格,小数点,八进制和十六进制前缀的理由,以及 wchar_t 精度单位的语义。
- 宽度
- 输出的最小字节数。
- 精度
- 请参阅 表 2。
- h , l , ll , L , H , D , DD
- 期望参数的大小:
- h
- 带有 d, i, o, u, x, X和 n 类型的前缀,用于指定自变量是 short int 或 unsigned short int。
- l
- 带有 d, i, o, u, x, X和 n 类型的前缀,用于指定自变量是 long int 或 unsigned long int。
- LL
- 带有 d, i, o, u, x, X和 n 类型的前缀,用于指定自变量是 long long long int 或 unsigned long long int。
- L
- 带有 a, A, e, E, f, F, g或 G 类型的前缀,用于指定参数为 long double。
- H
- 带有 a, A, e, E, f, F, g或 G 类型的前缀,用于指定参数为 _Decimal32。
- D
- 带有 a, A, e, E, f, F, g或 G 类型的前缀,用于指定自变量为 _Decimal64。
- DD
- 带有 a, A, e, E, f, F, g或 G 类型的前缀,用于指定自变量为 _Decimal128。
下面详细讨论了格式规范的每个字段。 如果百分号 (%) 后跟没有格式字段含义的字符,那么行为未定义。 此行为的一个例外是 %%。 要打印百分号字符,请使用 %%。
下表给出了 type 字符及其含义:
字符 | 自变量 | 输出格式 |
---|---|---|
a | 浮点 | 对于非十进制浮点数,格式为 [-] 0xh.hhhhp [sign]ddd的带符号值,其中 h 是单个十六进制数字, hhhh 是一个或多个十六进制数字, ddd 是一个或多个十进制数字, sign 是 + 或-。 小数点后的十六进制数字数等于请求的精度。 对于十进制浮点数,如果缺少精度,那么将根据以下条件使用 f 或 e 样式格式化。
|
A | 浮点 | 与格式相同,但使用大写字母字符而不是小写字母字符。 |
d , i | 整数 | 带符号十进制整数。 |
u | 整数 | 无符号十进制整数。 |
o | 整数 | 无符号八进制整数。 |
x | 整数 | 无符号十六进制整数,使用 abcdef。 |
X | 整数 | 无符号十六进制整数,使用 ABCDEF。 |
D (n , p) | 压缩十进制 | 它的格式为 [-] dddd.dddd ,其中小数点后的位数等于规范的精度。 如果缺少精度,那么缺省值为 p; 如果精度为零,并且未指定 # 标志,那么不会显示小数点字符。 如果 n 和 p 是 * ,那么自变量列表中的自变量将提供值。 n 和 p 必须在自变量列表中正在格式化的值之前。 在小数点之前至少出现一个字符。 该值将四舍五入为适当的位数。 |
f | 浮点 | 格式为 [-]dddd.dddd的带符号值,其中 dddd 是一个或多个十进制数字。 小数点之前的位数取决于数字的大小。 小数点后的位数等于请求的精度。2 |
F | 浮点 | 与 f 格式相同,但使用大写字母字符而不是小写字母字符。2 |
e | 浮点 | 格式为 [-]d.dddd e[sign]ddd的带符号值,其中 d 是一位十进制数字, dddd 是一位或多位十进制数字, ddd 是 2 或多位十进制数字, sign 是 + 或-。2 |
E | 浮点 | 与 e 格式相同,但使用大写字母字符而不是小写字母字符。2 |
g | 浮点 | 以 f 或 e 格式打印的带符号值。 仅当值的指数小于 -4 或大于或等于 精度时,才会使用 e 格式。 将截断尾部零,仅当后跟一个或多个数字时才会显示小数点。2 |
G | 浮点 | 与 g 格式相同,但使用大写字母字符而不是小写字母字符。2 |
c | 字符 (字节) | 单个字符。 |
s | 字符串 | 字符 (字节) 打印到第一个空字符 (\0) 或直到达到 精度 。 |
n | 指向整数的指针 | 迄今为止成功写入 流 或缓冲区的字符数 (字节); 此值存储在其地址作为自变量提供的整数中。 |
p | 指针 | 转换为可打印字符序列的指针。 可以是下列之一:
|
lc 或 C | 宽字符 | 将 (wchar_t) 字符转换为多字节字符,就像调用 wctomb () 一样,并将此字符打印出来。1 |
或 S | 宽字符 | (wchar_t) 字符直到第一个 (wchar_t) 空字符 (L\0) ,或者直到达到精度,才会转换为多字节字符,就像通过调用 wcstombs () 一样,这些字符被打印出来。 如果自变量是空字符串,那么将打印 (null)。1 |
- 请参阅
wctomb()
函数的文档或wcstombs()
函数的文档以获取更多信息。 您还可以在 宽字符中找到其他信息。 - 如果不使用 H , D 或 DD 格式大小说明符,那么仅保证输出的 15 个有效数字。
以下列表显示了 IBM® i 指针的打印值的格式,并提供了打印值的组件的简要描述。
上下文: 上下文的类型,子类型和名称
对象: 对象的类型,子类型和名称
偏移量: 空间中的偏移量
AG: 激活组标识
系统指针: SYP:Context :Object :Auth :Index :AG
上下文: 类型, 上下文
对象的子类型和名称: 对象的类型,子类型和名称
认证: 权限
索引: 与指针关联的索引
AG: 激活组标识
调用指针: IVP:Index :AG
索引: 与指针关联的索引
AG: 激活组标识
过程指针: PRP:Index :AG
索引: 与指针关联的索引
AG: 激活组标识
暂挂指针: SUP:Index :AG
索引: 与指针关联的索引
AG: 激活组标识
数据指针: DTP:Index :AG
索引: 与指针关联的索引
AG: 激活组标识
标签指针: LBP:Index :AG
索引: 与指针关联的索引
AG: 激活组标识
NULL 指针: NULL
- 如果一个指针被打印出来并从同一个激活组中扫描回来,那么扫描回来的指针将与打印出来的指针进行相等的比较。
- 如果
scanf()
系列函数扫描由其他激活组输出的指针,那么scanf()
系列函数会将该指针设置为 NULL。 - 如果在太字节空间环境中打印出指针,那么仅打印出指针的十六进制值。 这些结果与使用%#p时的结果相同。
与 %p 格式说明符相比,%#p 格式说明符具有更好的性能。
请参阅 ILE C/C++ Programmer 's Guide ,以获取有关使用 IBM i 指针的更多信息。
如果使用 a , e , f 或 g 格式格式化浮点值 INFINITY 或 Not-a-Number (NaN) ,那么输出字符串为infinity或nan. 如果使用 A , E , F 或 G 格式格式化浮点值 INFINITY 或 Not-A-Number (NaN) ,那么输出字符串为INFINITY或NAN.
标志 字符及其含义如下 (请注意,在格式规范中可以显示多个 标志 ):
标志 | 含义 | 缺省值 |
---|---|---|
- | 左对齐字段宽度内的结果。 | 右对齐。 |
+ | 如果输出值为带符号类型,请在输出值前添加符号 (+ 或-)。 | 仅对负符号值 (-) 显示符号。 |
blank('') | 如果输出值是有符号且为正数,请在输出值前添加空白。 如果出现 blank 标志,那么 + 标志将覆盖这两个标志,并且将输出带有符号的正带符号值。 | 无空白。 |
# | 当与 o, x或 X 格式一起使用时, # 标志分别以 0, 0x 或 0X 作为任何非零输出值的前缀。 | 无前缀。 |
当与 D (n , p), a, A, e, E, f 或 F 格式一起使用时, # 标志强制输出值在所有情况下都包含小数点。 | 仅当数字跟在小数点之后时才会显示小数点。 | |
当与 g 或 G 格式一起使用时, # 标志强制输出值在所有情况下都包含小数点,并防止尾部零被截断。 | 仅当数字跟在小数点之后时,才会显示小数点; 将截断尾部零。 | |
当与 ls 或 S 格式一起使用时, # 标志会使精度以字符为单位测量,而不考虑字符的大小。 例如,如果打印单字节字符,那么精度为 4 将导致打印 4 个字节。 如果正在打印双字节字符,那么精度为 4 将导致打印 8 个字节。 | 精度指示要输出的最大字节数。 | |
当与 p 格式一起使用时, # 标志会将指针转换为十六进制数字。 除非在太字节空间环境中,否则无法将这些十六进制数字转换回指针。 | 转换为可打印字符序列的指针。 | |
0 | 当与 d, i, D (n , p) o, u, x, X, a, A, e, E, f, F, g或 G 格式一起使用时, 0 标志将导致 0的输出填充到字段宽度。 如果为整数指定了精度或指定了 - 标志,那么将忽略 0 标志。 | 空间填充。 D (n , p) 无空格填充。 |
# 标志不应与 c, lc, d, i, u或 s 类型一起使用。
宽度 是一个非负十进制整数,用于控制打印的最小字符数。 如果输出值中的字符数 (字节) 小于指定的 width,那么将在左边或右边添加空格 (取决于是否指定了 - 标志) ,直到达到最小宽度为止。
宽度 从不导致值被截断; 如果输出值中的字符数 (字节) 大于指定的 宽度,或者未给出 宽度 ,那么将打印该值的所有字符 (遵循 精度 规范)。
对于 ls 或 S 类型,以字节为单位指定 width 。 如果输出值中的字节数小于指定的宽度,那么将在左边或右边添加单字节空格 (取决于是否指定了 - 标志) ,直到达到最小宽度为止。
width 规范可以是星号 (*) ,在这种情况下,自变量列表中的自变量将提供值。 width 自变量必须在自变量列表中要格式化的值之前。
精度 是一个以句点开头的非负十进制整数,用于指定要打印的字符数或小数位数。 与 width 规范不同, precision 可能导致浮点或 packed decimal 值的输出值截断或四舍五入。
precision 规范可以是星号 (*) ,在这种情况下,自变量列表中的自变量将提供值。 precision 自变量必须在自变量列表中正在格式化的值之前。
precision 值的解释以及省略 precision 时的缺省值取决于 类型,如下表中所示:
类型 | 含义 | 缺省值 |
---|---|---|
A |
对于非十进制浮点数, precision 指定要在小数点后打印的十六进制数字数。 对于十进制浮点数, precision 指定要打印的有效数字数。 |
对于非十进制浮点数,缺省 精度 足以表示该值的精确表示。 如果 precision 为 0 ,那么不会打印小数点。 对于十进制浮点数,缺省 精度 足以表示该值的精确表示。 请参阅 表 1 ,以获取有关所使用格式的更多详细信息。 |
i
d u o x X |
精度 指定要打印的最小位数。 如果自变量中的位数小于 precision,那么将在左侧用零填充输出值。 当位数超过 精度时,不会截断该值。 | 如果 precision 是 0 或完全省略,或者如果句点 (.) 显示后没有数字,那么 precision 设置为 1。 |
f
F D (n , p) e E |
精度 指定要在小数点后打印的位数。 打印的最后一个数字是四舍五入的。 | f , F , e 和 E 的缺省 精度 为 6。 缺省 precision for D (n , p) 为 p。 如果 precision 是 0 ,或者出现句点后没有数字,那么不会打印小数点。 |
g
G |
精度 指定打印的有效数字的最大数目。 | 打印所有有效数字。 缺省 精度 为 6。 |
c
|
没有效果 | 打印字符。 |
lc
|
没有效果 | 将转换 wchar_t 字符并打印生成的多字节字符。 |
s
|
精度 指定要打印的最大字符数 (字节)。 不打印超出 precision 的字符 (字节)。 | 打印字符,直到迂到空字符。 |
ls
|
精度 指定要打印的最大字节数。 不会打印超出 precision 的字节; 但是,将始终保留多字节完整性。 | 将转换 wchar_t 字符并打印生成的多字节字符。 |
返回值
printf()
函数返回打印的字节数。 errno 的值可以设置为:- 值
- 含义
- EBADMODE
- 指定的文件方式无效。
- ECONVERT
- 发生转换错误。
- EIOERROR
- 发生了不可恢复的I/O错误。
- EIORECERR
- 发生了可恢复的I/O错误。
- EILSEQ
- 迂到无效的多字节字符序列。
- EPUTANDGET
- 在读操作之后发生了非法写操作。
- ESTDOUT
- 无法打开
stdout
。
printf()
函数的基字符区分语言环境。 基数字符是要用于格式类型 D (n , p) , a , A , e , E , f , F , g 和 G 的格式字符串参数的 # 标志字符的小数点。示例
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char ch = 'h', *string = "computer";
int count = 234, hex = 0x10, oct = 010, dec = 10;
double fp = 251.7366;
wchar_t wc = (wchar_t)0x0058;
wchar_t ws[4];
printf("1234567890123%n4567890123456789\n\n", &count);
printf("Value of count should be 13; count = %d\n\n", count);
printf("%10c%5c\n", ch, ch);
printf("%25s\n%25.4s\n\n", string, string);
printf("%f %.2f %e %E\n\n", fp, fp, fp, fp);
printf("%i %i %i\n\n", hex, oct, dec);
}
/***************** Output should be similar to: *****************
234 +234 000234 EA ea 352
12345678901234567890123456789
Value of count should be 13; count = 13
h h
computer
comp
251.736600 251.74 2.517366e+02 2.517366E+02
16 8 10
*******************************************************************/
使用 printf()
的示例
#include <stdio.h>
#include <stdlib.h>
#include <locale.h>
/* This program is compiled with LOCALETYPE(*LOCALEUCS2) and */
/* SYSIFCOPT(*IFSIO) */
/* We will assume the locale setting is the same as the CCSID of the */
/* job. We will also assume any files involved have a CCSID of */
/* 65535 (no convert). This way if printf goes to the screen or */
/* a file the output will be the same. */
int main(void)
{
wchar_t wc = 0x0058; /* UNICODE X */
wchar_t ws[4];
setlocale(LC_ALL,
"/QSYS.LIB/EN_US.LOCALE"); /* a CCSID 37 locale */
ws[0] = 0x0041; /* UNICODE A */
ws[1] = (wchar_t)0x0042; /* UNICODE B */
ws[2] = (wchar_t)0x0043; /* UNICODE C */
ws[3] = (wchar_t)0x0000;
/* The output displayed is CCSID 37 */
printf("%lc %ls\n\n",wc,ws);
printf("%lc %.2ls\n\n",wc,ws);
/* Now let's try a mixed-byte CCSID example */
/* You would need a device that can handle mixed bytes to */
/* display this correctly. */
setlocale(LC_ALL,
"/QSYS.LIB/JA_JP.LOCALE");/* a CCSID 5026 locale */
/* big A means an A that takes up 2 bytes on the screen */
/* It will look bigger then single byte A */
ws[0] = (wchar_t)0xFF21; /* UNICODE big A */
ws[1] = (wchar_t)0xFF22; /* UNICODE big B */
ws[2] = (wchar_t)0xFF23; /* UNICODE big C */
ws[3] = (wchar_t)0x0000;
wc = 0xff11; /* UNICODE big 1 */
printf("%lc %ls\n\n",wc,ws);
/* The output of this printf is not shown below and it */
/* will differ depending on the device you display it on,*/
/* but if you looked at the string in hex it would look */
/* like this: 0E42F10F404040400E42C142C242C30F */
/* 0E is shift out, 0F is shift in, and 42F1 is the */
/* big 1 in CCSID 5026 */
printf("%lc %.4ls\n\n",wc,ws);
/* The output of this printf is not shown below either. */
/* The hex would look like: */
/* 0E42F10F404040400E42C10F */
/* Since the precision is in bytes we only get 4 bytes */
/* of the string. */
printf("%lc %#.2ls\n\n",wc,ws);
/* The output of this printf is not shown below either. */
/* The hex would look like: */
/* 0E42F10F404040400E42C142C20F */
/* The # means precision is in characters reguardless */
/* of size. So we get 2 characters of the string. */
}
/***************** Output should be similar to: *****************
X ABC
X AB
*******************************************************************/
使用 printf()
的示例
#include <stdio.h>
#include <stdlib.h>
#include <locale.h>
/* This program is compile LOCALETYPE(*LOCALE) and */
/* SYSIFCOPT(*IFSIO) */
int main(void)
{
wchar_t wc = (wchar_t)0x00C4; /* D */
wchar_t ws[4];
ws[0] = (wchar_t)0x00C1; /* A */
ws[1] = (wchar_t)0x00C2; /* B */
ws[2] = (wchar_t)0x00C3; /* C */
ws[3] = (wchar_t)0x0000;
/* The output displayed is CCSID 37 */
printf("%lc %ls\n\n",wc,ws);
/* Now let's try a mixed-byte CCSID example */
/* You would need a device that can handle mixed bytes to */
/* display this correctly. */
setlocale(LC_ALL,
"/QSYS.LIB/JA_JP.LOCALE"); /* a CCSID 5026 locale */
/* big A means an A that takes up 2 bytes on the screen */
/* It will look bigger than single byte A */
ws[0] = (wchar_t)0x42C1; /* big A */
ws[1] = (wchar_t)0x42C2; /* big B */
ws[2] = (wchar_t)0x42C3; /* big C */
ws[3] = (wchar_t)0x0000;
wc = 0x42F1; /* big 1 */
printf("%lc %ls\n\n",wc,ws);
/* The output of this printf is not shown below and it */
/* will differ depending on the device you display it on,*/
/* but if you looked at the string in hex it would look */
/* like this: 0E42F10F404040400E42C142C242C30F */
/* 0E is shift out, 0F is shift in, and 42F1 is the */
/* big 1 in CCSID 5026 */
printf("%lc %.4ls\n\n",wc,ws);
/* The output of this printf is not shown below either. */
/* The hex would look like: */
/* 0E42F10F404040400E42C10F */
/* Since the precision is in bytes we only get 4 bytes */
/* of the string. */
printf("%lc %#.2ls\n\n",wc,ws);
/* The output of this printf is not shown below either. */
/* The hex would look like: */
/* 0E42F10F404040400E42C142C20F */
/* The # means precision is in characters regardless */
/* of size. So we get 2 characters of the string. */
}
/***************** Output should be similar to: *****************
D ABC
*******************************************************************/