printf&scanf的格式化代码详解

这些函数的精髓就是变参...

Printf 格式代码

%[对齐][占位符(填充符号)][最小占位宽度][.精度][限定符][格式符]

分类说明:

[对齐]

    '-'
        实现左对齐,默认是右对齐

[占位符(填充符号)]

    '+' 正负号占位符
        含义: 当用于一个格式化某个有符号值代码时,如果值非负,正号标志就会给它加上一个正号。如果该值为负,就像往常一样显示一个负号。
        在缺省情况(不填)下,正号并不会显示。
    ' ' 空格占位符
        含义:只用于转换有符号值的代码。当值非负时,这个标志把一个空格添加到它开始的位置。
        注意这个标志和正号标志是相互排斥的,如果两个同时给出,空格标志便被忽略。
    '#' 数字占位符
        当在类型为o 之前(如%#o),则会在打印八进制数值前多印一个0。
        在类型为x 之前(%#x)则会在打印十六进制数前多印’0x’
        在型态为e、E、f、g或G 之前则会强迫数值打印小数点。
        在类型为g 或G之前时则同时保留小数点及小数位数末尾的零。
        在...    符号下#表示...
        o                   保证产生的值以一个'0'开头
        x,X                 在非零值前面加0x前缀(%X则为0X)
        e,E,f               确保结果始终包含一个小数点,即使它后面没有数字
        g,G                 和上面的e,E和f代码相同。另外,缀尾的0并不从小数中去除
   '0'  零占位符
        当有指定参数时,无数字的参数将补上0。默认是关闭此旗标,所以一般会打印出空白字符
   '%'  百分比占位符 delphi only?
        含义:在格式字符串中出现“%”字符将导致数字在格式化之前乘以 100。适当的符号插入到数字本身在格式字符串中出现“%”的位置。
        使用的百分比字符由当前的 NumberFormatInfo 类确定。

[最小占位宽度]

    如其含义,当宽度超过这个范围后,这个限制无效
    当宽度少于最小占位宽度,即用上面的填充字符来填充空下的部分
    使用*号,表示需要从参数表中获取这个值

[.精度]

    精度以一个句点开头,后面跟一个可选的十进制数。如果未给出整数,精度值为零。
    如未给出 [.精度] 这项 ,默认6位小数位.
    使用*号,表示需要从参数表中获取这个值
    对于d,i,u,o,x和X类型的转换
        此时, "%.5var" 同  "%05var"  左端补零作用   var表示要输出的变量
        精度字段指定将出现在结果中的 值数字 的最小位数  并覆盖零标志。
        如果转换后的值的位数小于宽度,就在它的前面插入零。
        如果值为零且精度也为零,则转换结果就不会产生数字。
    对于e,E和 f 类型的转换
        精度决定将出现在小数点之后的数字位数。另一种说法是全部数字(不包括小数点)
    对于g和G类型的转换
        它指定将出现在结果中的最大有效位数。
    对于s类型的转换
        精度指定将被转换的最多的字符数。指定取出的字符串长度(低于字符串截断的优先级)
        如果由一个"*"星号代替 用于表示字段宽度(和/或)精度的十进制整数,那么printf的下一个参数(必须是个整数)就提供宽度(和/或)精度。
        这些值可以通过计算获得   而不必预先指定(预先制定可能是不定的大小)。

[限定符] (h/l/L)

    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型值
        %lf 貌似能够输出和读取的精度更高(小数点位数更长)
        PS:( 留个问题...scanf(%f)---9.90000000E+37 和 scanf(%lf)---9.900000000E+37)...

[格式符]

    c   参数 int 
        含义 参数被裁剪为unsigned char类型并作为字符进行打印。
    i,d 参数 int
        含义 参数作为一个十进制整数打印。如果给出了最小占位宽度而且值的位数小于最小占位宽度位数,前面就用0填充。
    u,o,x,X 参数 unsigned int
        含义 参数作为一个无符号值打印,u使用十进制,o使用八进制,x或X使用十六进制,两者的区别是x约定使用abcdef,而X约定使用ABCDEF
    e,E 参数 double
        含义 参数根据指数形式打印。例如,6.023000e23是使用代码e,6.023000E23是使用代码E。小数点后面的位数由精度决定,缺省值是6。
    f   参数 double
        含义 参数按照的常规浮点格式打印。精度字段决定小数点后面的位数,缺省值是6。
    g,G 参数 double
        含义 参数以%f或%e(如G则%E)的格式打印,取决于它的值。如果指数大于等于-4但小于精度字段就使用%f格式,否则使用指数格式。
    s   参数 char *
        含义 打印一个字符串。精度字段可以限定该字符串最大的长度(不足则填充0?)
    p   参数 void *
        含义 指针值被转换为一串因编译器而异的可打印字符。这个代码主要是和scanf中的%p代码组合使用。
    n   参数 int *   !输出参数!
        含义 这个代码是独特的,因为它并不产生任何输出。相反,到目前为止函数已经产生的输出字符数目将被保存到对应的参数中。
    %   参数 (无)
        含义 打印一个%字符。
###############################################################################
scanf函数族
int fscanf (FILE *stream, const char *format, ...);
int scanf (const char *format, ...);
int sscanf (const char *string, const char *format, ...);

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


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

scanf格式代码

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

[*]

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

[宽度]

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

[限定符]

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

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

[格式符]

    格式符用于指定字符如何被解释:
    c   参数 char * 
        含义 读取和存储单个字符。前导空白字符并不跳过。
        如果给出宽度,就读取和存储这个数目的字符。字符后面不会添加一个NUL字节。
        参数必须指向一个足够大的字符数组。
    i,d 参数 int *
        含义 一个可选的有符号整数被转换。
        d把输入解释为十进制数;
        i根据它的第一个字符决定值的基数,就像整型字面值常量的表示形式一样。
    u,o,x,X 参数 unsigned *
        含义 一个可选的有符号整数被转换,但它按照无符号数存储。
        如果使用u,值被解释为十进制数;
        如果使用o,值被解释为八进制数;
        如果使用x,值被解释为十六进制数。X和x同义。
    e,E,f,g,G   参数 float *
        含义 期待一个浮点值。
        它的形式必须像一个浮点型字面常量,但小数点并非必须。
    s   参数 char *
        含义 读取一串非空白字符。
        参数必须指向一个足够大的字符数组。
        当发现空白时输入就停止,字符串后面会自动加上NUL终止符。
    [xxx]   参数 char *
        含义 根据给定组合的字符从输入中读取一串字符。
        参数必须指向一个足够大的字符数组。
        当遇到第一个不在给定组合中出现的字符时,输入就停止。
        字符串后面会自动加上NUL终止符。
        代码%[abc]表示字符组合包括a、b和c。
        如果列表以一个^字符开头,表示字符组合是所列字符的补集 ,
        所以%[^abc]表示字符组合为a、b、c之外的所有字符。贪婪性
        右方括号也可以出现在字符列表中,但它必须是列表的第一个字符。
        至于横杠是否用于指定某个范围的字符(例如%[a-z]),则因编译器而异。
    p   参数 void *
        含义 输入预期为一串字符,诸如那些由printf函数的%p格式代码所产生的输出。
        它的转换方式因编译器而异,但转换结果将和按照上面描述的进行打印所产生的字符的值是相同的。
    n   参数 int *
        含义 到目前为止通过这个scanf函数的调用从输入读取的字符数被返回。
        %n转换的字符并不计算在scanf函数的返回值之内。它本身并不消耗任何输入。
    %   参数 (无)
        含义 %%这个代码与输入中的一个%相匹配,该%符号被丢弃。
        

灵活使用scanf

scanf支持正则表达式

怎样从<sip:tom@172.18.1.133>中取出tom?
char * url="<sip:tom@172.18.1.133>";
char uri[10]={0};
sscanf(url,"%*[^:]:%[^@]",uri);
转贴:
在softmse (Jake) 的问题贴
http://community.csdn.net/Expert/topic/4843/4843294.xml?temp=. 4321558中 ,
周星星给出了一个很cool的sscanf用例,而后通过学习,发现sscanf真棒,现做一总结。


原问题:
iios/12DDWDFF@122
获取/和@之间的字符串怎么做
C程序里面有什么函数吗?
周星星的代码:
#include <stdio.h>
int main()
{
const char* s = "iios/12DDWDFF@122";
char buf[20];
sscanf( s, "%*[^/]/%[^@]", buf );
printf( "%s\n", buf );
return 0;
}
结果为:12DDWDFF
sscanf与scanf类似,都是用于输入的,只是后者以屏幕(stdin)为输入源,前者以固定字符串为输入源。
函数原型:
int scanf( const char *format [,argument]... );
其中的format可以是一个或多个 {%[*] [width] [{h | l | I64 | L}]type | ' ' | '\t' | '\n' | 非%符号},
注:{a|b|c}表示a,b,c中选一,[d],表示可以有d也可以没有d。
width:宽度,一般可以忽略,用法如:
const char sourceStr[] = "hello, world";
char buf[10] = {0};
sscanf(sourceStr, "%5s", buf); //%5s,只取5个字符
cout << buf<< endl;
结果为:hello
{h | l | I64 | L}:参数的size,通常h表示单字节size,I表示2字节 size,L表示4字节size(double例外),l64表示8字节size。
type :这就很多了,就是%s,%d之类。
特别的:
%*[width] [{h | l | I64 | L}]type 表示满足该条件的被过滤掉,不会向目标参数中写入值。如:
const char sourceStr[] = "hello, world";
char buf[10] = {0};
sscanf(sourceStr, "%*s%s", buf); //%*s表示第一个匹配到的%s被过滤掉,即hello被过滤了
cout << buf<< endl;
结果为:world
支持集合操作:
%[a-z] 表示匹配a到z中任意字符,贪婪性(尽可能多的匹配)
%[aB'] 匹配a、B、'中一员,贪婪性
%[^a] 匹配非a的任意字符,贪婪性
是不是感觉眼熟了啊,不错,这和正则表达式很相似,而且仍然支持过滤,即可以有%*[a-z].如:


星星大哥例子回顾:
const char* s = "iios/12DDWDFF@122";
char buf[20];
sscanf( s, "%*[^/]/%[^@]", buf );
printf( "%s\n", buf );
先将 "iios/"过滤掉,再将非'@'的一串内容送到buf中,cool.得到结果。




sscanf() - 从一个字符串中读进与指定格式相符的数据.
 
函数原型:
Int  sscanf( string str, string fmt,mixed var1, mixed var2 ... );
int  scanf( const char *format [,argument]...);
 
说明:
sscanf与scanf类似,都是用于输入的,只是后者以屏幕(stdin)为输入源,前者以固定字符串为输入源。
其中的format可以是一个或多个 {%[*] [width][{h | l | I64 | L}]type | ‘ ‘ | ‘/t‘ | ‘/n‘ | 非%符号}
 
注:
1、 * 亦可用于格式中, (即%*d 和 %*s) 加了星号 (*) 表示跳过此数据不读入. (也就是不把此数据读入参数中)
 
2、{a|b|c}表示a,b,c中选一,[d],表示可以有d也可以没有d。
 
3、width表示读取宽度。
 
4、{h | l | I64 | L}:参数的size,通常h表示单字节size,I表示2字节 size,L表示4字节size(double例外),l64表示8字节size。


5、type :这就很多了,就是%s,%d之类。
 
6、特别的:%*[width] [{h | l | I64 | L}]type表示满足该条件的被过滤掉,不会向目标参数中写入值
 
 
支持集合操作:
    %[a-z] 表示匹配a到z中任意字符,贪婪性(尽可能多的匹配)
    %[aB‘] 匹配a、B、‘中一员,贪婪性
    %[^a] 匹配非a的任意字符,贪婪性
 

例子:

 
1. 常见用法。
    char buf[512] = {0};
    sscanf("123456 ", "%s", buf);
printf("%s/n", buf);
 
结果为:123456
 
 
2. 取指定长度的字符串。如在下例中,取最大长度为4字节的字符串。
    sscanf("123456 ", "%4s", buf);
printf("%s/n", buf);
 
结果为:1234
 
 
3. 取到指定字符为止的字符串。如在下例中,取遇到空格为止字符串。
    sscanf("123456 abcdedf", "%[^ ]", buf);
printf("%s/n", buf);
 
结果为:123456
 
 
4.  取仅包含指定字符集的字符串。如在下例中,取仅包含1到9和小写字母的字符串。
    sscanf("123456abcdedfBCDEF", "%[1-9a-z]", buf);
printf("%s/n", buf);
 
结果为:123456abcdedf
 
 
5.  取到指定字符集为止的字符串。如在下例中,取遇到大写字母为止的字符串。
    sscanf("123456abcdedfBCDEF", "%[^A-Z]", buf);
printf("%s/n", buf);
 
结果为:123456abcdedf
 
 
 
6、给定一个字符串iios/12DDWDFF@122,获取 / 和 @ 之间的字符串,先将 "iios/"过滤掉,再将非‘@‘的一串内容送到buf中
sscanf("iios/12DDWDFF@122", "%*[^/]/%[^@]", buf);
printf("%s/n", buf);
 
结果为:12DDWDFF
 
 
7、给定一个字符串““hello, world”,仅保留world。(注意:“,”之后有一空格)
sscanf(“hello, world”,  "%*s%s",  buf); 
printf("%s/n", buf);
 
 
结果为:world
 
%*s表示第一个匹配到的%s被过滤掉,即hello被过滤了
 
如果没有空格则结果为NULL。




sscanf的功能很类似于正则表达式, 但却没有正则表达式强大,所以如果对于比较复杂的字符串处理,建议使用正则表达式

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值