C语言sprintf与sscanf函数总结及fscanf,sscanf,fprintf,sprintf之间的区别
C语言sprintf与sscanf函数[总结]
1、前言
我们经常涉及到数字与字符串之间的转换,例如将32位无符号整数的ip地址转换为点分十进制的ip地址字符串,或者反过来。从给定的字符串中提取相关内容,例如给定一个地址:http://www.bokeyuan.cn:2345,我们要从地址中提出协议,主机地址和端口号。之前对字符串和数字之间的关系不是很熟悉,工作中经常涉及到这个,如是好好总结一下。C语言提供了一些列的格式化输入输出函数,最基本的是面向控制台标准输出和输入的printf和scanf,其实还有面向字符串的sprint和sscanf,面向文件的流的fprintf和fscanf。今天着重总结一下sprintf和sscanf系列函数,这两个函数类似于scanf和printf ,不同点是从字符串*buffer用于输入输出。
2、sprintf函数
sprintf函数原型为 int sprintf(char *str, const char *format, …)。作用是格式化字符串,具体功能如下所示:
(1)将数字变量转换为字符串。
(2)得到整型变量的16进制和8进制字符串。
(3)连接多个字符串。
举例如下所示:
1 char str[256] = { 0 }; 2 int data = 1024; 3 //将data转换为字符串
4 sprintf(str,"%d",data); 5 //获取data的十六进制
6 sprintf(str,"0x%X",data); 7 //获取data的八进制
8 sprintf(str,"0%o",data); 9 const char *s1 = "Hello"; 10 const char *s2 = "World"; 11 //连接字符串s1和s2
12 sprintf(str,"%s %s",s1,s2);
3、sscanf函数
sscanf函数原型为int sscanf(const char *str, const char *format, …)。将参数str的字符串根据参数format字符串来转换并格式化数据,转换后的结果存于对应的参数内。具体功能如下:
(1)根据格式从字符串中提取数据。如从字符串中取出整数、浮点数和字符串等。
(2)取指定长度的字符串
(3)取到指定字符为止的字符串
(4)取仅包含指定字符集的字符串
(5)取到指定字符集为止的字符串
sscanf可以支持格式字符%[]:
(1)-: 表示范围,如:%[1-9]表示只读取1-9这几个数字 %[a-z]表示只读取a-z小写字母,类似地 %[A-Z]只读取大写字母
(2)^: 表示不取,如:%[^1]表示读取除’1’以外的所有字符 %[^/]表示除/以外的所有字符
(3),: 范围可以用”,”相连接 如%[1-9,a-z]表示同时取1-9数字和a-z小写字母
(4)原则:从第一个在指定范围内的数字开始读取,到第一个不在范围内的数字结束%s 可以看成%[] 的一个特例 %[^ ](注意^后面有一个空格!)
解析网址的例子如下所示:
1 const char *s = "http://www.baidu.com:1234"; 2 char protocol[32] = { 0 }; 3 char host[128] = { 0 }; 4 char port[8] = { 0 }; 5 sscanf(s,"%[^:]://%[^:]:%[1-9]",protocol,host,port); 6
7 printf("protocol: %s\n",protocol); 8 printf("host: %s\n",host); 9 printf("port: %s\n",port); 10
4、snprintf函数
snprintf函数是sprintf函数的更加安全版本,考虑到字符串的字节数,防止了字符串溢出。函数形式为:int snprintf(char *restrict buf, size_t n, const char * restrict format, …);。最多从源串中拷贝n-1个字符到目标串中,然后再在后面加一个0。所以如果目标串的大小为n 的话,将不会溢出。
5、测试程序
本次采用ip地址和整型之间的转换,mac地址转换作为测试程序,整个程序如下所示:
1 #include <stdio.h>
2 #include <assert.h>
3
4 #define IP_STR_LEN 18
5 #define MAC_STR_LEN 18
6 #define MAC_BIT_LEN 6
7 #define LITTLE_ENDIAN 0
8 #define BIG_ENDIAN 1
9
10 typedef unsigned char uchar; 11 typedef unsigned int uint; 12
13 int big_little_endian() 14 { 15 int data = 0x1; 16 if (*((char*)&data) == 0x1) 17 return LITTLE_ENDIAN; 18 return BIG_ENDIAN; 19 } 20
21 uint ipstr2int(const char * ipstr) 22 { 23 assert(ipstr); 24 uint a,b,c,d; 25 uint ip = 0; 26 sscanf(ipstr,"%u.%u.%u.%u",&a,&b,&c,&d); 27 a = (a << 24) ; 28 b = (b << 16) ; 29 c = (c << 8) ; 30 d = (d << 0) ; 31 ip = a | b | c | d; 32 return ip; 33 } 34
35 char *int2ipstr(const uint ip, char *ipstr, const uint ip_str_len) 36 { 37 assert(ipstr); 38 if (big_little_endian() == LITTLE_ENDIAN) 39 sprintf(ipstr,"%u.%u.%u.%u", 40 (uchar)*((char*)(&ip)+3), 41 (uchar)*((char*)(&ip)+2), 42 (uchar)*((char*)(&ip)+1), 43 (uchar)*((char*)(&ip)+0)); 44 else
45 sprintf(ipstr,"%u.%u.%u.%u", 46 (uchar)*((char*)(&ip)+0), 47 (uchar)*((char*)(&ip)+1), 48 (uchar)*((char*)(&ip)+2), 49 (uchar)*((char*)(&ip)+3)); 50
51 return ipstr; 52 } 53
55 char *mac2str(const unsigned char *mac,char *mac_str,const uint mac_str_len) 56 { 57 assert(mac_str); 58 sprintf(mac_str,"%02X-%02X-%02X-%02X-%02X-%02X", 59 mac[0],mac[1],mac[2], 60 mac[3],mac[4],mac[5]); 61 } 62
63 int main() 64 { 65 char ip_str[IP_STR_LEN] = {
0}; 66 char mac_str[MAC_STR_LEN] = {
0}; 67 unsigned char mac[MAC_BIT_LEN] = {
0XEF,0XAD,0XF4,0X4F,0XAA,0X0F}; 68 const char *ipstr = "10.0.3.193"; 69 unsigned int ip; 70 int2ipstr(167773121,ip_str,IP_STR_LEN); 71 mac2str(mac,mac_str,MAC_STR_LEN); 72 ip = ipstr2int(ipstr); 73 printf("%s\n",ip_str); 74 printf("%s\n",mac_str); 75 printf("ip:%u\n",ip); 76 return 0; 77 }
程序执行结果如下所示:
参考网址:
http://www.360doc.com/content/08/0813/22/45933_1539152.shtml
http://blog.csdn.net/wesweeky/article/details/6439777
http://msdn.microsoft.com/en-us/library/ce3zzk1k.aspx
http://technet.microsoft.com/zh-tw/library/wez13747
http://orgcent.com/ip-address-integer-convert/
sscanf与sprintf
一 sscanf函数
int sscanf(const char *s,const char *format,..);
int scanf(const char *format,…);
sscanf与scanf等价,所不同的是,前者的输入字符来源于字符串s,而scanf以stdin作为输入源。
1 %*d,%*s:*号表示此数据不读入,忽略掉。
比如
ch=”MemTotal: 2028248 kB”
sscanf(ch,”%*s%d”,&total);
printf(“%d\n”,total);
输出结果:2028248
2 取指定长度的字符串
sscanf(“123456 “, “%4s”, buf);
printf(“%s\n”, buf);
结果为:1234
3 取到指定字符为止的字符串。如在下例中,取遇到空格为止字符串。
sscanf(“123456 abcdedf”, “%[^ ]“, buf);
printf(“%s\n”, buf);
结果为:123456
4 sscanf(ch,”%*[^e]%[^2]“,ch1);
寻找e到2之间的数,包括e但不包括2
如果中间有空格,包括空格。
5 给定一个字符串““hello, world”,仅保留world。(注意:“,”之后有一空格)
sscanf(“hello, world”, “%*s%s”, buf);
printf(“%s\n”, buf);
结果为:world
%*s表示第一个匹配到的%s被过滤掉,即hello被过滤了
如果没有空格则结果为NULL。
6 分割字符串
sscanf(“2006:03:18”, “%d:%d:%d”, a, b, c);
sscanf(“2006:03:18 - 2006:04:18”, “%s - %s”, sztime1, sztime2);
如果2006:03:18 - 2006:04:18间没有空格
sscanf(“2006:03:18 - 2006:04:18”, “%[0-9,:] - %[0-9,:]“, sztime1, sztime2);
二 sprintf
- 负号时表示从后向前处理
0 表示空格填0
字符总宽度 小数点前面的数
精确度 小数点后面的数
1 把整数123 打印成一个字符串保存在s 中。
sprintf(s, “%d”, 123); //产生”123”
2 sprintf(s, “%08X”, 4567); //产生:”000011D7”
3 char a1[] = {‘A’, ‘B’, ‘C’, ‘D’, ‘E’, ‘F’, ‘G’};
char a2[] = {‘H’, ‘I’, ‘J’, ‘K’, ‘L’, ‘M’, ‘N’};
sprintf(s, “%.7s%.7s”, a1, a2);//产生:”ABCDEFGHIJKLMN”
这可以类比打印浮点数的”%m.nf”,在”%m.ns”中,m 表示占用宽度(字符串长度不足时补空格,超出了则按照实际宽度打印),n 才表示从相应的字符串中最多取用的字符数。通常在打印字符串时m 没什么大用,还是点号后面的n 用的多。自然,也可以前后都只取部分字符:
sprintf(s, “%.6s%.5s”, a1, a2);//产生:”ABCDEFHIJKL”
sprintf(s, “%.*s%.*s”, 7, a1, 7, a2);
或者:
sprintf(s, “%.*s%.*s”, sizeof(a1), a1, sizeof(a2), a2);
4 实际上,前面介绍的打印字符、整数、浮点数等都可以动态指定那些常量值,比如:
sprintf(s, “%-*d”, 4, ‘A’); //产生”65 “
sprintf(s, “%#0*X”, 8, 128); //产生”0X000080”,”#“产生0X
sprintf(s, “%*.*f”, 10, 2, 3.1415926); //产生” 3.14”
5 sprintf(s, “%p”, &i);
6 strlen 便已经知道了结果字符串的长度。如:
int len = sprintf(s, “%d”, i);
对于正整数来说,len 便等于整数i 的10 进制位数。
sscanf:
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的任意字符,贪婪性
例子:
- 常见用法。
char buf[512] = {0};
sscanf(“123456 “, “%s”, buf);
printf(“%s\n”, buf);
结果为:123456 - 取指定长度的字符串。如在下例中,取最大长度为4字节的字符串。
sscanf(“123456 “, “%4s”, buf);
printf(“%s\n”, buf);
结果为:1234 - 取到指定字符为止的字符串。如在下例中,取遇到空格为止字符串。
sscanf(“123456 abcdedf”, “%[^ ]“, buf);
printf(“%s\n”, buf);
结果为:123456 - 取仅包含指定字符集的字符串。如在下例中,取仅包含1到9和小写字母的字符串。
sscanf(“123456abcdedfBCDEF”, “%[1-9a-z]“, buf);
printf(“%s\n”, buf);
结果为:123456abcdedf - 取到指定字符集为止的字符串。如在下例中,取遇到大写字母为止的字符串。
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。
Sprintf:
sprintf 是个变参函数,定义如下:
int sprintf( char *buffer, const char *format [, argument] … );
除了前两个参数类型固定外,后面可以接任意多个参数。而它的精华,显然就在第二个参数:
格式化字符串上。
fprintf():
按格式输入到流,其原型是int fprintf(FILE *stream, const char *format[, argument, …]);其用法和printf()相同,不过不是写到控制台,而是写到流罢了
例:fprintf(fp,”%2d%s”,4,”Hahaha”);
fscanf():
从流中按格式读取,其原型是int fscanf(FILE *stream, const char *format[, address, …]);其用法和scanf()相同,不过不是从控制台读取,而是从流读取罢了。
例:fscanf(fp,”%d%d” ,&x,&y);
fscanf,sscanf,fprintf,sprintf还有scanf,printf
共同点是都是格式化输入/输出用的,它们的格式化方法/通配符都是一样的。
不同之处:
f打头的是文件I/O
s打头的是字符串I/O
什么都不带的, 在标准 键盘 屏幕(控制台) 出入输出.
还没有评论,来说两句吧...