Thursday, July 05, 2007

C语言专题――格式化I/O详解

C语言专题――格式化I/O详解

1 格式化I/O函数族


函数族 用途       可用于所有的流 只用于stdinstdout 内存中的字符串
scanf 
格式化输入 fscanf         scanf               sscanf
printf
格式化输出 fprintf        printf              sprintf

 

2 scanf函数族


int fscanf (FILE *stream, const char *format, ...);
int scanf (const char *format, ...);
int sscanf (const char *string, const char *format, ...);


当格式化字符串到达末尾或者读取的输入不再匹配格式字符串所指定的类型时,输入就停止。
被转换的输入值的个数作为返回值返回。
如果在任何输入值被转换之前,输入流就已到达尾部,函数就返回EOF


scanf
族中的format字符串参数可能包含下列内容:
空白字符――它们与输入中的零个或多个空白字符匹配,在处理过程中将被忽略。
格式代码――它们指定函数如何解释接下来的输入字符。
其他字符――当任何其他字符出现在格式字符串时,下一个输入字符必须与它匹配。
如果匹配,该输入字符随后就被丢弃。如果不匹配,函数就不再读取直接返回。

 

3 scanf格式代码


格式:%[*][宽度][限定符]格式码


其中,[]表示可选项。

 

1> *


星号表示将使转换后的值被丢弃而不是进行存储。

 

2> 宽度


宽度以一个非负的整数给出,它限制将被读取用于转换的输入字符的个数。
如果未给出宽度,函数就连续读入字符直到遇见输入中的下一个空白字符。

 

3> 限定符


限定符用于修改有些格式代码的含义:


格式码 h              l             L
d,i,n  short          long         
o,u,x  unsigned short unsigned long
e,f,g                 double        long double

 

4> 格式码


格式码用于指定字符如何被解释:


代码 c
参数 char *    
含义 读取和存储单个字符。前导空白字符并不跳过。如果给出宽度,就读取和存储这个数目的字符。字符后面不会添加一个NUL字节。参数必

须指向一个足够大的字符数组。


代码 i,d
参数 int *
含义 一个可选的有符号整数被转换。d把输入解释为十进制数;i根据它的第一个字符决定值的基数,就像整型字面值常量的表示形式一样。


代码 u,o,x
参数 unsigned *
含义 一个可选的有符号整数被转换,但它按照无符号数存储。如果使用u,值被解释为十进制数;如果使用o,值被解释为八进制数;如果使用

x,值被解释为十六进制数。Xx同义。


代码 e,f,g
参数 float *
含义 期待一个浮点值。它的形式必须像一个浮点型字面常量,但小数点并非必须。EG分别与eg同义。


代码 s
参数 char *
含义 读取一串非空白字符。参数必须指向一个足够大的字符数组。当发现空白时输入就停止,字符串后面会自动加上NUL终止符。


代码 [xxx]
参数 char *
含义 根据给定组合的字符从输入中读取一串字符。参数必须指向一个足够大的字符数组。当遇到第一个不在给定组合中出现的字符时,输入就

停止。字符串后面会自动加上NUL终止符。代码%[abc]表示字符组合包括abc。如果列表以一个^字符开头,表示字符组合是所列字符的补集

,所以%[^abc]表示字符组合为abc之外的所有字符。右方括号也可以出现在字符列表中,但它必须是列表的第一个字符。至于横杠是否用

于指定某个范围的字符(例如%[a-z]),则因编译器而异。


代码 p
参数 void *
含义 输入预期为一串字符,诸如那些由printf函数的%p格式代码所产生的输出。它的转换方式因编译器而异,但转换结果将和按照上面描述的

进行打印所产生的字符的值是相同的。


代码 n
参数 int *
含义 到目前为止通过这个scanf函数的调用从输入读取的字符数被返回。%n转换的字符并不计算在scanf函数的返回值之内。它本身并不消耗任

何输入。


代码 %
参数 (无)
含义 这个代码与输入中的一个%相匹配,该%符号被丢弃。

 

4 printf函数族


int fprintf (FILE *stream, const char *format, ...);
int printf (const char *format, ...);
int sprintf (char *buffer, const char *format, ...);


函数的返回值是实际打印或存储的字符数。

 

5 printf格式代码


格式:%[零个或多个标志][最小字段宽度][精度][修改符]格式码

 

1> 格式码


代码 c
参数 int   
含义 参数被裁剪为unsigned char类型并作为字符进行打印。


代码 i,d
参数 int
含义 参数作为一个十进制整数打印。如果给出了精度而且值的位数小于精度位数,前面就用0填充。


代码 u,o,x,X
参数 unsigned int
含义 参数作为一个无符号值打印,u使用十进制,o使用八进制,xX使用十六进制,两者的区别是x约定使用abcdef,而X约定使用ABCDEF


代码 e,E
参数 double
含义 参数根据指数形式打印。例如,6.023000e23是使用代码e6.023000E23是使用代码E。小数点后面的位数由精度字段决定,缺省值是6


代码 f
参数 double
含义 参数按照的常规浮点格式打印。精度字段决定小数点后面的位数,缺省值是6


代码 g,G
参数 double
含义 参数以%f%e(如G%E)的格式打印,取决于它的值。如果指数大于等于-4但小于精度字段就使用%f格式,否则使用指数格式。


代码 s
参数 char *
含义 打印一个字符串。


代码 p
参数 void *
含义 指针值被转换为一串因编译器而异的可打印字符。这个代码主要是和scanf中的%p代码组合使用。


代码 n
参数 int *
含义 这个代码是独特的,因为它并不产生任何输出。相反,到目前为止函数所产生的输出字符数目将被保存到对应的参数中。


代码 %
参数 (无)
含义 打印一个%字符。

 

2> 标志


标志 -
含义 值在字段中做对齐,缺省情况下是右对齐。


标志 0
含义 当数值为右对齐时,缺省情况下是使用空格填充值左边未使用的列。这个标志表示用零填充,它可用于d,i,u,o,x,X,e,E,f,gG代码。
使用d,i,u,o,xX代码时,如果给出了精度字段,零标志就被忽略。如果格式代码中出现了负号,零标志也没有效果。


标志 +
含义 当用于一个格式化某个有符号值代码时,如果值非负,正号标志就会给它加上一个正号。如果该值为负,就像往常一样显示一个负号。在

缺省情况下,正号并不会显示。


标志 空格
含义 只用于转换有符号值的代码。当值非负时,这个标志把一个空格添加到它开始的位置。注意这个标志和正号标志是相互排斥的,如果两个

同时给出,空格标志便被忽略。


标志 #
含义 选择某些代码的另一种转换形式:


用于...  #标志...
o       
保证产生的值以一个零开头
x,X     
在非零值前面加0x前缀(%X则为0X
e,E,f   
确保结果始终包含一个小数点,即使它后面没有数字
g,G     
和上面的e,Ef代码相同。另外,缀尾的0并不从小数中去除

 

3> 字段宽度


字段宽度是一个十进制整数,用于指定将出现在结果中的最小字符数。如果值的字符数少于字段宽度,就对它进行填充以增加长度。

 

4> 精度


精度以一个句点开头,后面跟一个可选的十进制数。如果未给出整数,精度的缺省值为零。


对于d,i,u,o,xX类型的转换,精度字段指定将出现在结果中的最小的数字个数并覆盖零标志。如果转换后的值的位数小于宽度,就在它的前

面插入零。如果值为零且精度也为零,则转换结果就不会产生数字。


对于e,Ef类型的转换,精度决定将出现在小数点之后的数字位数。


对于gG类型的转换,它指定将出现在结果中的最大有效位数。


当使用s类型的转换时,精度指定将被转换的最多的字符数。


如果用于表示字段宽度和/或精度的十进制整数由一个星号代替,那么printf的下一个参数(必须是个整数)就提供宽度和(或)精度。因此,

这些值可以通过计算获得而不必预先指定。

 

5> 修改符


修改符 用于...   表示参数是...
h      d,i,u,o,x,X
一个(可能是无符号)short型整数
h      n          
一个指向short型整数的指针
l      d,i,u,o,x,X
一个(可能是无符号)long型整数
l      n          
一个指向long型整数的指针
L      e,E,f,g,G  
一个long double型值

 

6 代码举例


1>
使用扫描集,使scanf能够读取一整行:


#include <stdio.h>


int main()
{
 char string[50];
 scanf("%[^\n]", string);
 printf("%s\n", string);


 return 0;
}

 

2> 使用*号,从参数表获取printf所需的字段宽度和精度参数:


#include <stdio.h>
#include <math.h>


int main()
{
        double pi = acos(-1);
        int width = 12;
        int precision = 8;
        printf("%*.*f\n", width, precision, pi);


        return 0;
}

 

 

No comments: