前段时间用C写了一个程式,发现3年前学的C的基本语法都忘得差不多了。下面的格式化字符,我觉得值得我写个随笔,免得下次再写时,忘记了。 格式字符控制: 说明:sprintf(格式化后的字符,"%(长度)格式符",格式化前的字符); 1、 d格式符。用来输出十进制数。有以下几种用法: (1)、%d按整数的实际长度输出。 (2)、%md,m为指定的输出字段的宽度。如果数据位数小于m,则左端补以空格,若大于m,则按实际位数输出。(3)、%ld,输出长整型数据。例:long a=135790;printf(“%ld”,a);如果用%d输出就会发生错误,因为整型数据的范围是-32768到32767.对long型数据应当用%ld格式输出,对长整型数据也可以指定字段宽度,如:%8ld。 2、 o格式符,以八进制数形式输出整数。由于内存单元中的各位的值(0或1)按八进制形式输出,因此输出的数值不带符号,即将符号位也一起作为八进制的一部分输出。 3、 x格式符,以十六进制数形式输出整数。同样不会出现负的十六进制数。同样可以用%lx输出长整型数,也可以指定输出字段宽度。 4、 u格式符,用来输出unsigned型数据,即无符号数,以十进制形式输出。一个有符号整数(int型)也可以用%u格式输出,反之,一个unsigned型的数据也可以用%d格式输出。按相互赋值的规则处理。Unsigned型数据也可以用%x格式输出。 5、 c格式符,用来输出一个字符。一个字符型数据也可以用整数形式输出。 6、 s格式符,用来输出一个字符串。 (1)、%s,printf(“%s”,“HELLO”); (2)、%ms输出字符串占m列,如字符串本身大于m,则突破m的限制,字符串全部输出,如果小于m,则左补空格。(3)、%-ms如果字符串小于m,则在m范围内,字符串向左靠,右补空格。 (4)、%m.ns,输出占m列,但只取字符串中左端n个字符。这n个字符输出在m列的右侧,左补空格。 (5)、%-m.ns,其中m,n含义同上,n个字符输出在m范围的左侧,右补空格。如果n>m,则自动取n值,即保证n个字符正常输出。 7、 f格式符,用来输出实数(包括单,双精度),以小数形式输出。 (1)、%f,不指定字段宽度,有系统自动指定,使整数部分全部如数输出,并输出6位小数。应当注意,并非全部数字都是有效数字。单精度实数的有效位数一般是7位。 (2)、%m.nf指定输出的数据占m列,其中有n位小数。如果数值长度小于m,则左补空格。 (3)、%-m.nf与%m.nf基本相同,只是输出的数值向左端靠,右端补空格。 8、 e格式符,以指数形式输出。 9、 g格式符,用来输出实数,它根据数值的大小,自动选择f格式或e格式(选择输出时占宽度较小的一种),且不输出无意义的零。
*********************************************************
一个位于一个%和格式化命令间的整数担当着一个最小字段宽度说明符,并且加上足够多的空格或0使输出足够长. 如果你想填充0,在最小字段宽度说明符前放置0. 你可以使用一个精度修饰符,它可以根据使用的格式代码而有不同的含义.
所有的printf()的输出都是右对齐的,除非你在%符号后放置了负号. 例如,
%-12.4f 将会显示12位字符,4位小数位的浮点数并且左对齐. 你可以修改带字母l和h%d, %i, %o, %u和 %x 等类型说明符指定长型和短型数据类型 (例如 %hd 表示一个短整数). %e, %f和 %g 类型说明符,可以在它们前面放置l指出跟随的是一个double. %g, %f和 %e 类型说明符可以置于字符'#'前保证出现小数点, 即使没有小数位. 带%x类型说明符的'#'字符的使用, 表示显示十六进制数时应该带'0x'前缀. 带%o类型说明符的'#'字符的使用, 表示显示八进制数时应该带一个'0'前缀.
****************************格式化符在sscanf函数中的强大用法***************************** 1. 常见用法。 char buf[512] ; sscanf("123456 ", "%s", buf);//此处buf是数组名,它的意思是将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 当输入: sscanf("123456abcdedfBCDEF","%[1-9A-Z]",buf); printf("%s\n",buf); 结果为:123456 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。(注意:“,”之后有一空格,%s遇空格停止,加*则是忽略第一个读到的字符串) sscanf(“hello, world”, "%*s%s", buf); printf("%s\n", buf); 结果为:world %*s表示第一个匹配到的%s被过滤掉,即hello被过滤了 如果没有空格则结果为NULL。 sscanf的功能很类似于正则表达式, 但却没有正则表达式强大,所以如果对于比较复杂的字符串处理,建议使用正则表达式. //------------------------------------------------------- 用它来分隔类似这样的字符串2006:03:18: int a, b, c; /*sscanf("2006:03:18", "%d:%d:%d", a, b, c); */ /*错误方法, 要在变量a,b,c前加上取地址符, modified by huanmie_09*/ sscanf("2006:03:18", "%d:%d:%d", &a, &b, &c); 以及2006:03:18 - 2006:04:18: char sztime1[16] = "", sztime2[16] = ""; sscanf("2006:03:18 - 2006:04:18", "%s - %s", sztime1, sztime2); 但是后来,我需要处理2006:03:18-2006:04:18 仅仅是取消了‘-’两边的空格,却打破了%s对字符串的界定。 我需要重新设计一个函数来处理这样的情况?这并不复杂,但是,为了使所有的代码都有统一的风格,我需要改动很多地方,把已有的sscanf替换成我自己的分割函数。我以为我肯定需要这样做,并伴随着对sscanf的强烈不满而入睡;一觉醒来,发现其实不必。 format-type中有%[]这样的type field。如果读取的字符串,不是以空格来分隔的话,就可以使用%[]。 %[]类似于一个正则表达式。[a-z]表示读取a-z的所有字符,[^a-z]表示读取除a-z以外的所有字符。 所以那个问题也就迎刃而解了: sscanf("2006:03:18 - 2006:04:18", "%[0-9,:] - %[0-9,:]", sztime1, sztime2); 在softmse (Jake) 的问题贴http://community.csd(去掉我)n.n(去掉我)et/Expert/topic/4843/4843294.xml?temp=.4321558中 ,给出了一个很cool的sscanf用例,而后通过学习,发现sscanf真棒,现做一总结。
搜集一些特殊用法:
%[ ] 的用法:%[ ]表示要读入一个字符集合, 如果[ 后面第一个字符是”^”,则表示反意思。 [ ]内的字符串可以是1或更多字符组成。空字符集(%[])是违反规定的,可 导致不可预知的结果。%[^]也是违反规定的。 %[a-z] 读取在 a-z 之间的字符串,如果不在此之前则停止,如 char s[]="hello, my friend” ; // 注意: ,逗号在不 a-z之间 sscanf( s, “%[a-z]”, string ) ; // string=hello
char s[]="HELLOkitty” ; // 注意: ,逗号在不 a-z之间
%*[^=] 前面带 * 号表示不保存变量。跳过符合条件的字符串。 char s[]="notepad=1.0.0.1001" ; char szfilename [32] = "" ; int i = sscanf( s, "%*[^=]", szfilename ) ; // szfilename=NULL,因为没保存
// szfilename=1.0.0.1001
char s[]="notepad=1.0.0.1001" ; char szfilename [32] = "" ; int i = sscanf( s, "%[^=]", szfilename ) ; // szfilename=notepad
注意:当碰到不满足条件的字符后,sscanf就会停止执行,不再扫描之后的字符。
********************strtok字符串分割函数也是个实战性较强的函数,但是已被strsep函数取代***********************
#include <string.h> char *strtok( char *str1, const char *str2 ); 功能:函数返回字符串str1中紧接“标记”的部分的指针, 字符串str2是作为标记的分隔符。如果分隔标记没有找到,函数返回NULL。为了将字符串转换成标记,第一次调用str1 指向作为标记的分隔符。之后所以的调用str1 都应为NULL。 例如: char str[] = "now # is the time for all # good men to come to the # aid of their country"; char delims[] = "#"; char *result = NULL; result = strtok( str, delims ); while( result != NULL ) { printf( "result is \"%s\"\n", result ); result = strtok( NULL, delims ); } 以上代码的运行结果是: result is "now " result is " is the time for all " result is " good men to come to the " result is " aid of their country" --------------------------------------------------------------------------------- char* strname=NULL;
-------------------------------------------------------------------------------------
strsepbaikeViewInfo={id:"2466295",editable:"true",title:"strsep",expIndex:"0"}; 原型:char *strsep(char **stringp, const char *delim);
功能:分解字符串为一组字符串。从stringp指向的位置起向后扫描,遇到delim指向位置的字符后,将此字符替换为NULL,返回stringp指向的地址。
*********************strncat字符串截取拼接*********************************
strncatbaikeViewInfo={id:"1028544",editable:"true",title:"strncat",expIndex:"0"}; 原型:extern char *strncat(char *dest,char *src,int n);
用法:#include <string.h>
功能:把src所指字符串的前n个字符添加到dest结尾处(覆盖dest结尾处的'\0')并添加'\0'。
说明:src和dest所指内存区域不可以重叠且dest必须有足够的空间来容纳src的字符串。
返回指向dest的指针。
举例:
// strncat.c
#include <syslib.h>
#include <string.h>
main()
{
char d[20]="Golden Global";
char *s=" View WinIDE Library";
clrscr();
strncat(d,s,5);
printf("%s",d);
getchar();
return 0;
}
以上代码的运行结果是: Golden Global View 注意view前面有个空格字符。
***********************strncasecmp***************************
strncasecmpbaikeViewInfo={id:"1589829",editable:"true",title:"strncasecmp",expIndex:"0"}; 相关函数:bcmp, memcmp, strcmp, strcoll, strncmp
表头文件:#include <string.h>
函数定义:int strncasecmp(const char *s1, const char *s2, size_t n)
函数说明:strncasecmp()用来比较参数s1和s2字符串前n个字符,比较时会自动忽略大小写的差异
返回值 :若参数s1和s2字符串相同则返回0 s1若大于s2则返回大于0的值 s1若小于s2则返回小于0的值
#include <string.h>
char *a="acddfefekr"; 以上代码的运行结果是:1 ******************************strcasecmp*************************
strcasecmp(忽略大小写比较字符串) 相关函数 bcmp,memcmp,strcmp,strcoll,strncmp 表头文件 #include<string.h> 定义函数 int strcasecmp (const char *s1, const char *s2); 函数说明 strcasecmp()用来比较参数s1和s2字符串,比较时会自动忽略大小写的差异。 此原文这里有错误:返回值 若参数s1和s2字符串相同则返回0。s1长度大于s2长度则返回大于0 的值,s1 长度若小于s2 长度则返回小于0的值。 strcasecmp是比较两个字符串,但比较的不是它们的长度,而是字符的编码大小——但字母不区分大小写,如果S1小于S2,返回小于0的一个整数;如果S1等于S2,返回值是0;如果S1>S2,返回一个大于0的整数。 #include <string.h> main() { char *a="aBcddfefekr";
执行 aBcDeF=AbCdEf 以上代码的运行结果是:0 注意与strncasecmp()的区别,不要弄混了。 该函数是二进制安全的,且对大小写不敏感。 *************************strncpy******************************* strncpy:字串复制 原型:char * strncpy(char *dest, char *src, size_t n); 功能:将字符串src中最多n个字符复制到字符数组dest中(它并不像strcpy一样遇到NULL才停止复制,而是等凑够n个字符才开始复制),返回指向dest的指针。 说明: 如果n > dest串长度,dest栈空间溢出产生崩溃异常。 否则: 1)src串长度<=dest串长度,(这里的串长度包含串尾NULL字符) 如果n=(0, src串长度),src的前n个字符复制到dest中。但是由于没有NULL字符,所以直接访问dest串会发生栈溢出的异常情况。 如果n = src串长度,与strcpy一致。 如果n = dest串长度,[0,src串长度]处存放于desk字串,(src串长度, dest串长度]处存放NULL。 2)src串长度>dest串长度 如果n =dest串长度,则dest串没有NULL字符,会导致输出会有乱码。如果不考虑src串复制完整性,可以将dest最后一字符置为NULL。 综上,一般情况下,使用strncpy时,建议将n置为dest串长度(除非你将多个src串都复制到dest数组,并且从dest尾部反向操作),复制完毕后,为保险起见, 将dest串最后一字符置NULL,避免发生在第2)种情况下的输出乱码问题。当然喽,无论是strcpy还是strncpy,保证src串长度<dest串长度才是最重要的。
*******************************snprintf*******************************
snprintfbaikeViewInfo={id:"1966670",editable:"true",title:"snprintf",expIndex:"0"}; int snprintf(char *str, size_t size, const char *format, ...);
将可变个参数(...)按照format格式化成字符串,然后将其复制到str中
(1) 如果格式化后的字符串长度 < size,则将此字符串全部复制到str中,并给其后添加一个字符串结束符('\0');
(2) 如果格式化后的字符串长度 >= size,则只将其中的(size-1)个字符复制到str中,并给其后添加一个字符串结束符('\0')
函数返回值:若成功则返回欲写入的字符串长度,若出错则返回负值。 --------------------------------------------
|
|