分类: 系统运维
2012-03-29 12:06:22
格式化输出
格式化输出由4个printf函数处理
printf函数向标准输出写,fprintf向一个指定的流写,而sprintf把格式化的字符串放入到数组buf里。sprintf函数在数组末自动将上一个空字节,但这个空字节没有包含在返回值里。
注意sprintf可能为溢出buf指向的缓冲区。这是调用者的执行来保证这个缓冲区足够大。因为这会导致缓冲区溢出的问题,于是snprintf被引 入。用它可以把缓冲的尺寸作为一个显式的参数;任何超过缓冲区末尾的字符都会被舍弃掉。snprintf函数返回假如缓冲足够大时会写入的字符数。而 sprintf一样,返回值不包括终止的空字节。如果snprintf返回一个比缓冲大小n更小的正值,那么输出则被裁切过了。如果编码出 错,snprintf返回一个负值。
格式规范控制了剩下的参数如何被编码和最终显示。每个参数根据一个以百分号(%)开头的转换规格(conversion specification)来编码。除了转换规格,其它在格式里的字符都被无修改地复制。一个转换规格有4个可先部分,如下方括号里所示:
%[flags] [fldwidth] [precision] [lenmodifier] convtype
flags由下表汇总:
转换规格的flag部分 | |
Flag | 描述 |
- | 域里面左输出 |
+ | 总是显示一个正负号 |
(空格) | 如果没有正负号则以一个空格开头 |
# | 使用代替的格式转换(例如16进制格式中包含0x前缀) |
0 | 以0填充,而不是空格 |
fldwidth部分指定了最小的域宽度。如果转换结果有更少的字符,则以空格填充。域完是一个非负十进制整数或一个星号。
precision部分在整数转换时指定了整数中数字的最小数量,在浮点数转换时指定了小数点右侧的数字的最小数量,或者在字符串转换中指定字节的最大数量。precision是一个“.”接着一个可选的非负十进制整数或星号。
域宽和精度都可以是一个星号。这种情况下,一个指定这个值的参数被使用,它直接在出现在被转换的参数前。
lenmodifier部分指定了参数的尺寸。下表总结了可能的值:
转换格式的长度修改符 | |
Length modifier | 描述 |
hh | 有符号或无符号char |
h | 有符号或无符号short |
l | 有符号或无符号long或宽字符 |
ll | 有符号或无符号long long |
j | intmax_t或uintmax_t |
z | size_t |
t | ptrdiff_t |
L | long double |
convtype部分不是可选的。它控制了参数如何被解释。下表总结了各种转换类型:
转换规格的转换类型部分 | |
Conversion type | 描述 |
d, i | 有符号十进制 |
o | 无符号八进制 |
u | 无符号十进制 |
x, X | 无符号十六进制 |
f, F | double浮点数 |
e, E | 指数格式的double浮点数 |
g, G | 根据要转换的值,以f,F,e或E来解释 |
a, A | 十六进制指数格式的double浮点数 |
c | 字符(长度修改符l表示宽字符) |
s | 字符串(长度修改符l表示宽字符串) |
p | void指针 |
n | 指向表示目前为止已写字符数量的有符号整型的指针 |
% | 一个%字符 |
C | 宽字符(XSI扩展,等价于lc) |
S | 宽字符串(XIS扩展,等价于ls) |
下面4个printf家族的变体与前4个函数相似,只是参数列表(...)被arg代替。
注意可变长度的参数列表由ISO C提供,定义在
格式化输入
格式化输入由三个scanf函数处理
scanf家族用来解析一个输入的字符串并转换成指定类型的变量。在格式后的参数包含需要用转换结果初绐化的变量的地址。
格式规格(format specification)控制了参数如何为赋值而被转换。百分号(%)表示格式规格的开始。除了转换规格和空格,其它在格式里的字符都用来匹配输入。如果有一个字符不匹配,操作停止,不再读剩下的输入。
转换规格中有三个可选部分,如下面方括号里所示:
%[*] [fldwidth] [lenmodifier] convtype
可选的开头的星号用来抑制转换。输入根据转换规格的其它部分转换,但结果不会存储在一个参数里。
fldwidth部分指定域的最大字符数。lenmodifier部分指定要以转换结果初始化的参数的尺寸。被printf家族支持的长度修改符同样也被scanf家族支持。
convtype域与printf家族所用的转换类型域类似,但有一些不同。一个区别是,存在一个无符号类型的结果在输入里可以是有符号的。下表总结了scanf家族支持的转换类型:
转换规格的转换类型部分 | |
Conversion type | 描述 |
d | 有符号十进制 |
i | 有符号数,根据输入格式决定进制 |
o | 无符号八进制(输入可以是有符号的) |
u | 无符号十进制(输入可以是有符号的) |
x | 无符号十六进制(输入可以是有符号的) |
a, A, e, E, f, F, g, G | 浮点数 |
c | 字符(长度修改符l表示宽字符) |
s | 字符串(长度修改符l表示宽字符串) |
[ | 匹配一个字符列表,以]结束 |
[^ | 匹配除列出的之外的所有字符,以]结束 |
p | void指针 |
n | 指向表示目前为止已写字符数量的有符号整型的指针 |
% | 一个%字符 |
C | 宽字符(XSI扩展,等价于lc) |
S | 宽字符串(XIS扩展,等价于ls) |
和printf家族一样,scanf家族也支持使用可变参数列表的函数,它们由
参考你的UNIX系统手册来获得更多关于scanf家族函数的细节。