[转载]C语言 格式化字符

  提问: 6 年 前 最后更新: 1 周 前 浏览数: 25855
1
2

前段时间用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格式(选择输出时占宽度较小的一种),且不输出无意义的零。

 

 

*********************************************************

Code 格式
%c 字符
%d 带符号整数
%i 带符号整数
%e 科学计数法, 使用小写"e"
%E 科学计数法, 使用大写"E"
%f 浮点数
%g 使用%e或%f中较短的一个
%G 使用%E或%f中较短的一个
%o 八进制
%s 一串字符
%u 无符号整数
%x 无符号十六进制数, 用小写字母
%X 无符号十六进制数, 用大写字母
%p 一个指针
%n 参数应该是一个指向一个整数的指针
指向的是字符数放置的位置
%% 一个'%'符号

一个位于一个%和格式化命令间的整数担当着一个最小字段宽度说明符,并且加上足够多的空格或0使输出足够长. 如果你想填充0,在最小字段宽度说明符前放置0. 你可以使用一个精度修饰符,它可以根据使用的格式代码而有不同的含义.

  • 用%e, %E和 %f,精度修饰符让你指定想要的小数位数. 例如,

     

        %12.6f

    将会至少显示12位数字,并带有6位小数的浮点数.

  • 用%g和 %G, 精度修饰符决定显示的有效数的位数最大值.
  • 用%s,精度修饰符简单的表示一个最大的最大长度, 以补充句点前的最小字段长度.

所有的printf()的输出都是右对齐的,除非你在%符号后放置了负号. 例如,

 

    %-12.4f

将会显示12位字符,4位小数位的浮点数并且左对齐. 你可以修改带字母lh%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


%[^a-z] 读取不在 a-z 之间的字符串,如果碰到a-z之间的字符则停止,如

              char s[]="HELLOkitty” ; // 注意: ,逗号在不 a-z之间


              sscanf( s, “%[^a-z]”, string ) ; // string=HELLO

 

%*[^=] 前面带 * 号表示不保存变量。跳过符合条件的字符串。

              char s[]="notepad=1.0.0.1001" ;

       char szfilename [32] = "" ;

       int i = sscanf( s, "%*[^=]", szfilename ) ;

// szfilename=NULL,因为没保存


int i = sscanf( s, "%*[^=]=%s", szfilename ) ;

// szfilename=1.0.0.1001


%40c 读取40个字符


%[^=] 读取字符串直到碰到’=’号,’^’后面可以带更多字符,如:

              char s[]="notepad=1.0.0.1001" ;

              char szfilename [32] = "" ;

             int i = sscanf( s, "%[^=]", szfilename ) ;

           // szfilename=notepad


       如果参数格式是:%[^=:] ,那么也可以从 notepad:1.0.0.1001读取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;
    strname=(char*)malloc(sizeof(char));
 memset(strname,0,sizeof(char));
 strcpy(strname,"tong|sun|java|google");
 
    char delims[] = "|";
    char* ret=NULL;
    ret=(char*)malloc(sizeof(char));
 memset(ret,0,sizeof(char));
 ret=strtok(strname,delims);
 while(ret!=NULL)
 {
  printf("%s\n",ret);
   ret=(char*)malloc(sizeof(char));
  memset(ret,0,sizeof(char));
  ret=strtok(NULL,delims); 
 }

 

-------------------------------------------------------------------------------------

 

  strsep

baikeViewInfo={id:"2466295",editable:"true",title:"strsep",expIndex:"0"};

  原型:char *strsep(char **stringp, const char *delim);
  功能:分解字符串为一组字符串。从stringp指向的位置起向后扫描,遇到delim指向位置的字符后,将此字符替换为NULL,返回stringp指向的地址。

 

 *********************strncat字符串截取拼接*********************************

 

strncat

baikeViewInfo={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***************************

 

strncasecmp

baikeViewInfo={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";
  char *b="AbCddfefekr";
  printf("%d\n",strncasecmp(a,b,2));

  以上代码的运行结果是: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";
   char *b="AbCddfefekr";
   printf("%d\n",strcasecmp(a,b));

  }

 

  执行 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*******************************

 

snprintf

baikeViewInfo={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')
  函数返回值:若成功则返回欲写入的字符串长度,若出错则返回负值。 --------------------------------------------

    int snprintf(char *restrict buf, size_t n, const char * restrict  format, ...);

  函数说明:最多从源串中拷贝n-1个字符到目标串中,然后再在后面加一个0。所以如果目标串的大小为n

      的话,将不会溢出。

  函数返回值:若成功则返回欲写入的字符串长度,若出错则返回负值。

  Result1(推荐的用法)

  #include <stdio.h>

  #include <stdlib.h>

  int main()

  {

       char str[10]={0,};

       snprintf(str, sizeof(str), "0123456789012345678");

       printf("str=%s\n", str);

       return 0;

  }

 
 
  #include <stdio.h> //snprintf()
  #include <string.h> //strlen()
  int main()
  {
  char toname[30];
  char *name = "yangtaiping";
  printf("strlen(name) = %d\n", strlen(name));
  snprintf(toname, sizeof(toname), "姓名:%s", name);
  printf("toname = %s\n", toname);
  printf("strlen(name) = %d\n", strlen(name));
  }
  strcpy() sprintf() strcat() 存在安全隐患, 其对应的安全版为:strncpy() snprintf() strncat() 。 
  snprintf(s, 100, "%.*S", 3, "abcd");s的值为abc %.*s 表示有两项, 第一项指定了长度,第二项则是%s的内容,所以取前三位 词条图册更多图册
  类似的函数还有:
  #include <stdio.h>
  int printf(const char *format, ...); //格式化输出到标准输出设备
  int fprintf(FILE *stream,const char *format, ...); //格式化输出到文件流
  int sprintf(char *str,const char *format, ...); //格式化的输出字符串输出到str指向的地址空间

 

**************************************************************

  实战常用函数:

  printf scanf sscanf strcat strncat fprint fwrite fread fopen fclose

  sprintf snprintf strcmp strncmp strstr strchr strlen strcasecmp strncasecmp

  memcpy strcpy strncpy

提问时间 2011-10-13 23:00

openkk的头像

openkk
56 3 1
答案被采用率: 0.0%


好东西,谢谢哈……

回答于 2015-11-17 15:35

perll的头像

perll
0 0 3
答案被采用率: 0.0%

好东西,谢谢哈。。。。。。

回答于 2017-11-08 22:22

a6040315的头像

a6040315
0 0 2
答案被采用率: 0.0%

学习中

回答于 2017-11-11 11:12

@ml的头像

@ml
0 0 2
答案被采用率: 0.0%

总结的很好,good

回答于 2011-12-15 16:07

mapleuu的头像

mapleuu
0 0 2
答案被采用率: 0.0%

和好,学习中

回答于 2012-09-04 22:44

hua-2012的头像

hua-2012
0 0 9
答案被采用率: 0.0%

学习了,感谢

回答于 2012-09-05 19:54

hua-2012的头像

hua-2012
0 0 9
答案被采用率: 0.0%

您的回答:

  

powered by Open-Open.com