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结束。 如果参数多于格式规范,那么将对额外的参数进行求值并将其忽略。 如果没有足够的自变量用于所有格式规范,那么未定义结果。

格式规范具有以下格式:

读取语法图跳过可视语法图%标志宽度.精确hLlllHDDD类型

可以将转换应用于自变量列表中 format-string 之后的第 n 个自变量,而不是应用于下一个未使用的自变量。 在这种情况下,转换字符% 将替换为序列 %n$ ,其中 n 是 1 到 NL_ARGMAX 范围内的十进制整数,给出自变量在自变量列表中的位置。 此功能部件提供格式字符串的定义,这些字符串以适合于特定语言的顺序选择自变量。

备用格式规范具有以下格式:
读取语法图跳过可视语法图%arg-number$标志 宽度.精确hLlllHDDD类型

作为替代方法,可以使用上图中概述的格式规范来分配自变量列表中的特定条目。 不能在对 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
带有 diouxXn 类型的前缀,用于指定自变量是 short intunsigned short int
l
带有 diouxXn 类型的前缀,用于指定自变量是 long intunsigned long int
LL
带有 diouxXn 类型的前缀,用于指定自变量是 long long long intunsigned long long int
L
带有 aAeEfFgG 类型的前缀,用于指定参数为 long double
H
带有 aAeEfFgG 类型的前缀,用于指定参数为 _Decimal32
D
带有 aAeEfFgG 类型的前缀,用于指定自变量为 _Decimal64
DD
带有 aAeEfFgG 类型的前缀,用于指定自变量为 _Decimal128

下面详细讨论了格式规范的每个字段。 如果百分号 (%) 后跟没有格式字段含义的字符,那么行为未定义。 此行为的一个例外是 %%。 要打印百分号字符,请使用 %%。

下表给出了 type 字符及其含义:

表 1. 输入字符
字符 自变量 输出格式
a 浮点 对于非十进制浮点数,格式为 [-] 0xh.hhhhp [sign]ddd的带符号值,其中 h 是单个十六进制数字, hhhh 是一个或多个十六进制数字, ddd 是一个或多个十进制数字, sign 是 + 或-。 小数点后的十六进制数字数等于请求的精度。

对于十进制浮点数,如果缺少精度,那么将根据以下条件使用 fe 样式格式化。

  • 当值的 量子指数 小于或等于 0 但大于或等于-(n+ 5) 时,将使用 f 样式格式化。 可以通过调用 quantexp64() 函数来确定数字的 量子指数 。 n 是忽略小数点时数字序列 (包括尾部零) 中的位数。 例如:

    0.000005

    包含数字序列中的 1 个数字, n = 1

    0.0000050

    包含数字序列中的 2 个数字, n = 2

    12.30

    包含数字序列中的 4 个数字, n = 4

    精度等于该值的 量子指数 的绝对值。

  • 当值的 quantum exponent 不满足 f 样式条件时,将使用 e 样式格式化。 精度等于 n-1。 十进制浮点值的 e 样式格式与非十进制浮点值的 e 样式格式相同,但有两种例外: a) 如果该值等于 0 ,那么该指数等于该值的 量子指数 ,并且 b) 该指数始终具有所需的最小位数 (即,该指数从不包含前导零)。 例如:

    0.0000000 生成 0e-7

    -1870 生成 -1.87e+3

如果存在精度修饰符,并且至少与值的精度一样大,那么转换就像缺少精度修饰符一样。 如果精度修饰符存在且小于该值的精度,那么首先将该值舍入为精度修饰符指定的位数。 然后转换结果,就像缺少精度修饰符一样。
A 浮点 与格式相同,但使用大写字母字符而不是小写字母字符。
d , i 整数 带符号十进制整数。
u 整数 无符号十进制整数。
o 整数 无符号八进制整数。
x 整数 无符号十六进制整数,使用 abcdef。
X 整数 无符号十六进制整数,使用 ABCDEF。
D (n , p) 压缩十进制 它的格式为 [-] dddd.dddd ,其中小数点后的位数等于规范的精度。 如果缺少精度,那么缺省值为 p; 如果精度为零,并且未指定 # 标志,那么不会显示小数点字符。 如果 np 是 * ,那么自变量列表中的自变量将提供值。 np 必须在自变量列表中正在格式化的值之前。 在小数点之前至少出现一个字符。 该值将四舍五入为适当的位数。
f 浮点 格式为 [-]dddd.dddd的带符号值,其中 dddd 是一个或多个十进制数字。 小数点之前的位数取决于数字的大小。 小数点后的位数等于请求的精度。2
F 浮点 与 f 格式相同,但使用大写字母字符而不是小写字母字符。2
e 浮点 格式为 [-]d.dddd e[sign]ddd的带符号值,其中 d 是一位十进制数字, dddd 是一位或多位十进制数字, ddd 是 2 或多位十进制数字, sign 是 + 或-。2
E 浮点 e 格式相同,但使用大写字母字符而不是小写字母字符。2
g 浮点 fe 格式打印的带符号值。 仅当值的指数小于 -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
注:
  1. 请参阅 wctomb() 函数的文档或 wcstombs() 函数的文档以获取更多信息。 您还可以在 宽字符中找到其他信息。
  2. 如果不使用 H , D 或 DD 格式大小说明符,那么仅保证输出的 15 个有效数字。

以下列表显示了 IBM® i 指针的打印值的格式,并提供了打印值的组件的简要描述。

空间指针: SPP:Context :Object :Offset :AG

上下文: 上下文的类型,子类型和名称
对象: 对象的类型,子类型和名称
偏移量: 空间中的偏移量
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

以下限制适用于 IBM i 操作系统上的指针打印和扫描:
  • 如果一个指针被打印出来并从同一个激活组中扫描回来,那么扫描回来的指针将与打印出来的指针进行相等的比较。
  • 如果 scanf() 系列函数扫描由其他激活组输出的指针,那么 scanf() 系列函数会将该指针设置为 NULL。
  • 如果在太字节空间环境中打印出指针,那么仅打印出指针的十六进制值。 这些结果与使用%#p时的结果相同。

与 %p 格式说明符相比,%#p 格式说明符具有更好的性能。

请参阅 ILE C/C++ Programmer 's Guide ,以获取有关使用 IBM i 指针的更多信息。

如果使用 a , e , f 或 g 格式格式化浮点值 INFINITY 或 Not-a-Number (NaN) ,那么输出字符串为infinitynan. 如果使用 A , E , F 或 G 格式格式化浮点值 INFINITY 或 Not-A-Number (NaN) ,那么输出字符串为INFINITYNAN.

标志 字符及其含义如下 (请注意,在格式规范中可以显示多个 标志 ):

标志 含义 缺省值
- 左对齐字段宽度内的结果。 右对齐。
+ 如果输出值为带符号类型,请在输出值前添加符号 (+ 或-)。 仅对负符号值 (-) 显示符号。
blank('') 如果输出值是有符号且为正数,请在输出值前添加空白。 如果出现 blank 标志,那么 + 标志将覆盖这两个标志,并且将输出带有符号的正带符号值。 无空白。
# 当与 oxX 格式一起使用时, # 标志分别以 00x 或 0X 作为任何非零输出值的前缀。 无前缀。
当与 D (n , p)aAeEfF 格式一起使用时, # 标志强制输出值在所有情况下都包含小数点。 仅当数字跟在小数点之后时才会显示小数点。
当与 gG 格式一起使用时, # 标志强制输出值在所有情况下都包含小数点,并防止尾部零被截断。 仅当数字跟在小数点之后时,才会显示小数点; 将截断尾部零。
当与 ls 或 S 格式一起使用时, # 标志会使精度以字符为单位测量,而不考虑字符的大小。 例如,如果打印单字节字符,那么精度为 4 将导致打印 4 个字节。 如果正在打印双字节字符,那么精度为 4 将导致打印 8 个字节。 精度指示要输出的最大字节数。
当与 p 格式一起使用时, # 标志会将指针转换为十六进制数字。 除非在太字节空间环境中,否则无法将这些十六进制数字转换回指针。 转换为可打印字符序列的指针。
0 当与 diD (n , p) ouxXaAeEfFgG 格式一起使用时, 0 标志将导致 0的输出填充到字段宽度。 如果为整数指定了精度或指定了 - 标志,那么将忽略 0 标志。 空间填充。 D (n , p) 无空格填充。

# 标志不应与 clcdius 类型一起使用。

宽度 是一个非负十进制整数,用于控制打印的最小字符数。 如果输出值中的字符数 (字节) 小于指定的 width,那么将在左边或右边添加空格 (取决于是否指定了 - 标志) ,直到达到最小宽度为止。

宽度 从不导致值被截断; 如果输出值中的字符数 (字节) 大于指定的 宽度,或者未给出 宽度 ,那么将打印该值的所有字符 (遵循 精度 规范)。

对于 ls 或 S 类型,以字节为单位指定 width 。 如果输出值中的字节数小于指定的宽度,那么将在左边或右边添加单字节空格 (取决于是否指定了 - 标志) ,直到达到最小宽度为止。

width 规范可以是星号 (*) ,在这种情况下,自变量列表中的自变量将提供值。 width 自变量必须在自变量列表中要格式化的值之前。

精度 是一个以句点开头的非负十进制整数,用于指定要打印的字符数或小数位数。 与 width 规范不同, precision 可能导致浮点或 packed decimal 值的输出值截断或四舍五入。

precision 规范可以是星号 (*) ,在这种情况下,自变量列表中的自变量将提供值。 precision 自变量必须在自变量列表中正在格式化的值之前。

precision 值的解释以及省略 precision 时的缺省值取决于 类型,如下表中所示:

表 2。 精度值
类型 含义 缺省值
  
A
对于非十进制浮点数, precision 指定要在小数点后打印的十六进制数字数。

对于十进制浮点数, precision 指定要打印的有效数字数。

对于非十进制浮点数,缺省 精度 足以表示该值的精确表示。 如果 precision 为 0 ,那么不会打印小数点。 对于十进制浮点数,缺省 精度 足以表示该值的精确表示。 请参阅 表 1 ,以获取有关所使用格式的更多详细信息。
   i
d
u
o
x
X
精度 指定要打印的最小位数。 如果自变量中的位数小于 precision,那么将在左侧用零填充输出值。 当位数超过 精度时,不会截断该值。 如果 precision0 或完全省略,或者如果句点 (.) 显示后没有数字,那么 precision 设置为 1。
   f
F
D (n , p)
e
E
精度 指定要在小数点后打印的位数。 打印的最后一个数字是四舍五入的。 f , F , eE 的缺省 精度 为 6。 缺省 precision for D (n , p) 为 p。 如果 precision0 ,或者出现句点后没有数字,那么不会打印小数点。
   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


 *******************************************************************/
 

相关信息