分类: LINUX
2012-01-04 21:13:38
++++++APUE读书笔记-05标准输入输出库(6)++++++
11、格式化输入输出
================================================
(1)格式化的输出
格式化输出有如下四种函数:
#include
int printf(const char *restrict format, ...);
int fprintf(FILE *restrict fp, const char *restrict format, ...);
两者返回:如果输出成功返回输出字符数目,如果输出错误返回负数。
int sprintf(char *restrict buf, const char *restrict format, ...);
int snprintf(char *restrict buf, size_t n, const char *restrict format, ...);
两者返回:如果成功返回存放到数组中的字符数目,如果编码错误返回负数。
printf将字符串写入到标准输出;fprintf写入到指定的stream;sprintf将格式化的字符串写入到buf数组中,并且将一个'\0'字符追加到最后,但是返回值却不包含这个'\0';snprintf和sprintf类似,但是指定了要写入的大小限制,写入包含'\0'在内最多n的字符到buf数组中。
需要注意的是,可能sprintf会溢出buf指向的缓存,调用这个函数的调用者需要保证缓存空间足够大。因为,会导致缓存溢出问题,所以引入了函数snprintf。这个函数将buffer大小做为一个显示指定的参数,任何可能导致写过缓存末端的字符都会被截断。如果缓存空间足够大,那么snprintf函数会返回写入到缓存中的字符的数目,当然和sprintf类似,其返回值没有将null所占的字节算进来。如果snprintf返回了一个小于缓存大小n的数目,那么输出就没被截断,如果出现编码错误,那么回返回负数。
也就是说,对于这几个函数的返回值,它们都返回不包括'\0'的、写入的字符数目。另外,如果snprintf由于n限制把写入的字符串截断了,那么它会返回假设没有被截断(也就是n足够大)的时候的字符串字符数目(当然也不包含'\0'),所以如果返回值是n或者更多则表示输出被截断了。
format的格式:
参数前面的format参数指名了格式,其形式是:
%[flags][fldwidth][precision][lenmodifier]convtype
(最好不用翻译,但是翻译起来就是:%[标记][宽度][精度][长度调整]类型)中括号代表可选。这里:
对于flags有:
a)-:指定的参数的输出在所在处是左对齐的(如果存在下面将说的0那么忽略0),默认右对齐。
b)+:指定对于有符号的convtype(相当于类型),输出其符号。
c) (空格):指定如果不显示符号的话就以一个空格作为前缀。
d)#:用可选的方式显示。例如:八进制类型(用o)就以0开头,十六进制(用x)就以0x开头等,见man.
e)0:参数的前面用0填充(如果同时存在-将被-覆盖,导致0被忽略)而不是用空格了。
对于fldwidth:
它指明了最小宽度,如果参数小于这个宽度就填充空格。
fldwidth可以是一个正的十进制数,或者是一个'*'。例如:5,或者*
对于precision:
它指定了整数的最少显示数字数目,浮点数小数点后面的数字数目以及字符串的最大字节数目。
presion可以是一个点'.'后面接整数或者'*'。例如:.5或者.*
注意:对于fldwidth和precision都可以指定一个'*',这时候,需要在将要显示的参数前面再添加一个整数参数来指定将要显示的值。可以参见代码中的例子。
其他的可以参考下面的表格,这里主要注意#和*在format参数中的作用。
lenmodifier指定参数大小,其值如下:
格式规范中的长度选项
+--------------------------------------------------------------+
| Length modifier | Description |
|-----------------+--------------------------------------------|
| hh | signed or unsigned char |
|-----------------+--------------------------------------------|
| h | signed or unsigned short |
|-----------------+--------------------------------------------|
| l | signed or unsigned long or wide character |
|-----------------+--------------------------------------------|
| ll | signed or unsigned long long |
|-----------------+--------------------------------------------|
| j | intmax_t or uintmax_t |
|-----------------+--------------------------------------------|
| z | size_t |
|-----------------+--------------------------------------------|
| t | ptrdiff_t |
|-----------------+--------------------------------------------|
| L | long double |
+--------------------------------------------------------------+
convtype在多个参数的时候是必选的,指定参数的解释方式。如下表:
格式规范中的转换类型选项
+--------------------------------------------------------------------------------------------------------------+
| Conversion type | Description |
|-----------------+--------------------------------------------------------------------------------------------|
| d,i | signed decimal |
|-----------------+--------------------------------------------------------------------------------------------|
| o | unsigned octal |
|-----------------+--------------------------------------------------------------------------------------------|
| u | unsigned decimal |
|-----------------+--------------------------------------------------------------------------------------------|
| x,X | unsigned hexadecimal |
|-----------------+--------------------------------------------------------------------------------------------|
| f,F | double floating-point number |
|-----------------+--------------------------------------------------------------------------------------------|
| e,E | double floating-point number in exponential format |
|-----------------+--------------------------------------------------------------------------------------------|
| g,G | interpreted as f, F, e, or E, depending on value converted |
|-----------------+--------------------------------------------------------------------------------------------|
| a,A | double floating-point number in hexadecimal exponential format |
|-----------------+--------------------------------------------------------------------------------------------|
| c | character (with l length modifier, wide character) |
|-----------------+--------------------------------------------------------------------------------------------|
| s | string (with l length modifier, wide character string) |
|-----------------+--------------------------------------------------------------------------------------------|
| p | pointer to a void |
|-----------------+--------------------------------------------------------------------------------------------|
| n | pointer to a signed integer into which is written the number of characters written so far |
|-----------------+--------------------------------------------------------------------------------------------|
| % | a % character |
|-----------------+--------------------------------------------------------------------------------------------|
| C | wide character (an XSI extension, equivalent to lc) |
|-----------------+--------------------------------------------------------------------------------------------|
| S | wide character string (an XSI extension, equivalent to ls) |
+--------------------------------------------------------------------------------------------------------------+
下面是前面四个类似printf格式化输出系列的函数的变种, 区别仅在于将前面的可变参数列表(...)在这里变成了参数arg。
#include
#include
int vprintf(const char *restrict format, va_list arg);
int vfprintf(FILE *restrict fp, const char *restrict format, va_list arg);
两者返回:如果输出成功返回字符数目,错误返回负数。
int vsprintf(char *restrict buf, const char *restrict format, va_list arg);
int vsnprintf(char *restrict buf, size_t n, const char *restrict format, va_list arg);
两者返回:如果成功将返回存放到数组buf中的字符数目,如果错误返回负数。
下面给出一个printf的例子:
/*程序功能:主要测试printf的格式部分
*
* 关于printf的格式:
* int printf(const char *restrict format, ...);
* 参数前面的format参数指名了格式,其形式是:
* %[flags][fldwidth][precision][lenmodifier]convtype
* 最好不用翻译,但是翻译起来就是:%[标记][宽度][精度][长度调整]类型
* 中括号代表可选。这里:
* 对于flags有:
* 1)-:指定的参数的输出在所在处是左对齐的(如果存在下面将说的0那么忽略0),默认右对齐。
* 2)+:指定对于有符号的convtype(相当于类型),输出其符号。
* 3) (空格):指定如果不显示符号的话就以一个空格作为前缀。
* 4)#:用可选的方式显示。例如:八进制类型(用o)就以0开头,十六进制(用x)就以0x开头等,见man.
* 5)0:参数的前面用0填充(如果同时存在-将被-覆盖,导致0被忽略)而不是用空格了。
*
* 对于fldwidth:
* 它指明了最小宽度,如果参数小于这个宽度就填充空格。
* fldwidth可以是一个正的十进制数,或者是一个'*'。例如:5,或者*
*
* 对于precision:
* 它指定了整数的最少显示数字数目,浮点数小数点后面的数字数目以及字符串的最大字节数目。
* presion可以是一个点'.'后面接整数或者'*'。例如:.5或者.*
*
* 注意:对于fldwidth和precision都可以指定一个'*',这时候,需要在将要显示的参数前面再添加一个整数参数来指定将要显示的值。可以参见代码中的例子。
*
* 其他的暂时不说了,这里主要就说了#和*在format参数中的作用。
*
* */
#include
int main(int argc, char *argv[])
{
printf("%-5d\n", 1);//宽度为5,左对齐
printf("%5d\n", 2);//宽度为5,默认右对齐
printf("%+5d\n", 3);//宽度为5,显示符号(正号)的3
printf("%-+5d\n", 4);//宽度为5,显示符号并且左对齐的4.
printf("%- 5d\n",5);//宽度为5,将正号不显式代之为一个空格,并且左对齐。
printf("%- 5d\n",-6);//宽度为5,左对齐同%-5d。
printf("%05d\n",7);//宽度为5,不足的填充为0。
printf("%*d\n",8,9);//宽度在参数里面指定为8(!!!!!!!!!!!!!)
printf("%0-5d\n",8);//宽度为5,不足的填充为0,忽略左对齐。
printf("%7.5d\n",8);//宽度为7,精度为5的整数(00008)。
printf("%7.5f\n",7.1);//宽度为7,精度为5的浮点数(7.10000)。
printf("%7.*f\n",3,6.1);//宽度为7,精度在参数中指定为3的浮点数(6.100)。
printf("%3.5f\n",5.1);//宽度为3,精度为5的浮点数,精度大于宽度(5.10000)。不被截断!!
printf("%7.3f\n",4.12345);//宽度7,精度3的浮点数,精度小于实际的数值精度(4.123)。截断!!
printf("%3s\n", "abcdef");//宽度3长度大于3的字符串.不被截断!!
printf("%.3s\n", "abcdef");//精度3长度大于3的字符串.截断!!
printf("%.3s\n", "abc");//精度5长度小于5的字符串,没有什么.
return 0;
}
(2)格式化输入
如下函数进行格式化输入的处理:
#include
int scanf(const char *restrict format, ...);
int fscanf(FILE *restrict fp, const char *restrict format, ...);
int sscanf(const char *restrict buf, const char *restrict format, ...);
三者返回:指定的输入的数目。如果输入错误或者在任何conversion之前(也就是转化完成之前)到达文件结尾,返回EOF。
(这个部分说的有些费解,但是最好实践一下???)
这些格式化输入函数用来将输入的字符序列读取并转化成指定的类型变量做为程序输入。参数format后面的参数包含了用转化来的输入值,所初始化的变量的地址。
format参数用来控制如何转化并赋值。%字符指明一个conversion规范的开始。除了空白以及conversion规范,format中的其他的字符需要和输入相匹配。如果有一个字符没有匹配,那么就会导致进程停止,并留下没有读取得输入。
conversion规范中,有三个可选的部分,通过下面的方括号括起来。
%[*][fldwidth][lenmodifier]convtype
这里,星号(*)可选,用来禁止转换。输入会按照conversion规范剩余的部分所指定的那样来进行转换,但是结果不会被存放到参数中去。(有些费解???)
fldwidth部分指定最大的字符宽度。lenmodifier指定conversion的结果值初始化的参数的大小,和printf的含义一样。
convtype域和printf的差不多,但是也有些不同。其中一个就是,存放到无符号类型的变量的转化结果,可以在输入的时候存放在有符号变量中。下表列出了各种标记:
格式规范中的转换类型
+-----------------------------------------------------------------------------------------------------------+
| Conversion | Description |
| type | |
|-----------------+-----------------------------------------------------------------------------------------|
| d | signed decimal, base 10 |
|-----------------+-----------------------------------------------------------------------------------------|
| i | signed decimal, base determined by format of input |
|-----------------+-----------------------------------------------------------------------------------------|
| o | unsigned octal (input optionally signed) |
|-----------------+-----------------------------------------------------------------------------------------|
| u | unsigned decimal, base 10 (input optionally signed) |
|-----------------+-----------------------------------------------------------------------------------------|
| x | unsigned hexadecimal (input optionally signed) |
|-----------------+-----------------------------------------------------------------------------------------|
| a,A,e,E,f,F,g,G | floating-point number |
|-----------------+-----------------------------------------------------------------------------------------|
| c | character (with l length modifier, wide character) |
|-----------------+-----------------------------------------------------------------------------------------|
| s | string (with l length modifier, wide character string) |
|-----------------+-----------------------------------------------------------------------------------------|
| [ | matches a sequence of listed characters, ending with ] |
|-----------------+-----------------------------------------------------------------------------------------|
| [^ | matches all characters except the ones listed, ending with ] |
|-----------------+-----------------------------------------------------------------------------------------|
| p | pointer to a void |
|-----------------+-----------------------------------------------------------------------------------------|
| n | pointer to a signed integer into which is written the number of characters read so far |
|-----------------+-----------------------------------------------------------------------------------------|
| % | a % character |
|-----------------+-----------------------------------------------------------------------------------------|
| C | wide character (an XSI extension, equivalent to lc) |
|-----------------+-----------------------------------------------------------------------------------------|
| S | wide character string (an XSI extension, equivalent to ls) |
+-----------------------------------------------------------------------------------------------------------+
类似格式化输出,也有一些格式化输入的变种函数:
#include
#include
int vscanf(const char *restrict format, va_list arg);
int vfscanf(FILE *restrict fp, const char *restrict format, va_list arg);
int vsscanf(const char *restrict buf, const char *restrict format, va_list arg);
所有三个函数返回:指定的输入的数目,如果输入错误或者在转化完之前 到达文件结尾,返回EOF。
参考: