【澳门新葡萄京官网首页】php中的sprintf的应用

sprintf

将字串格式化命令。sprintf
是个变参函数,使用时平日出难题,并且如若出问题普通便是能促成程序崩溃的内部存款和储蓄器访问错误,但好在由sprintf
误用导致的主题材料就算严重,却比较轻松寻觅,无非就是那么三种情况,平日用眼睛再把失误的代码多看几眼就看出来了。

 

将字串格式化。

  sprintf 将字串格式化。

求助编辑应有尽著名片

字串格式化命令,首要功用是把格式化的多寡写入某些字符串中。sprintf
是个变参函数,使用时平时出难题,而且只要出题目普通就是能招致程序崩溃的内部存款和储蓄器访谈错误,但万幸由sprintf
误用引致的难题即便严重,却超级轻巧搜索,无非就是那么两种意况,平时用肉眼再把失误的代码多看几眼就看出来了。

 

目录

函数简要介绍

参数表达及采Nabi方

应用sprintf 的普遍难点

展开

 

语法: string sprintf(string format, mixed [args]…);

  在头文件 #include<stdio.h

编纂本段函数简单介绍

  函数功用:把格式化的数码写入有个别字符串

 

  头文件:stdio.h

 

  函数原型:int sprintf( char *buffer, const char *format, [
argument] … ) ;

 

  再次来到值:字符串长度(strlen)

 

  相关函数:[1]

 

  int sprintf_s(char
*buffer,size_t sizeOfBuffer,const
char *format, [argument] … );

 

澳门新葡萄京官网首页,  int _sprintf_s_l(char *buffer,size_t sizeOfBuffer,const char
*format,locale_t locale ,[argument] … );

 

  int
swprintf_s(wchar_t *buffer,size_t
sizeOfBuffer,const wchar_t *format ,[argument]…);

 

  int _swprintf_s_l(wchar_t *buffer,size_t sizeOfBuffer,const
wchar_t *format,locale_t locale ,[argument]…);

 

  template <size_t size>

 

  int sprintf_s(char (&buffer)[size],const char *format,
[argument] … ); // C++ only

 

  template <size_t size>

 

  int swprintf_s(wchar_t (&buffer)[size],const wchar_t *format
,[argument]…); // C++ only

 

传回值: 字串

  >中

编写制定本段参数表明及应用比方

  sprintf格式的原则如下所示。[]中的部分是可选的。

 

  %[内定参数][标识符][宽度][.精度]指示符

 

  若想出口`%’本身时, 请这样`%%’处理。

 

  1. 甩卖字符方向。负号时表示从后迈入管理。

 

  2. 填空字元。 0 的话代表空格填 0;空格是钦点值,表示空格就放着。

 

  3. 字符总宽度。为最小宽度。

 

  4. 正确度。指在小数点后的浮点数位数。

 

  =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

函式种类: 资料管理

  语法: int sprintf(string format, mixed [args]…);

改变字符

  =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

 

  %% 印出百分比符号,不调换。

 

  %c 整数转成对应的 ASCII 字元。

 

  %d 整数转成十进位。

 

  %f 倍正确度数字转成浮点数。

 

  %o 整数转成八进位。

 

  %s 整数转成字符串。

 

  %x 整数转成小写十五进位。

 

  %X 整数转成大写十九进位。

 

  =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

 

  <?

 

  $money = 123.1

 

  $formatted = sprintf (“%06.2f”, $money卡塔尔; // 那时候变数 $ formatted
值为 “123.10”

 

  $formatted = sprintf (“%08.2f”, $money卡塔尔; // 那时变数 $ formatted
值为 “00123.10”

 

  $formatted = sprintf (“%-08.2f”, $money卡塔尔国; // 这时变数 $ formatted
值为 “123.1000”

 

  $formatted = sprintf (“%.2f%%”, 0.95 * 100卡塔尔国; // 格式化为百分比

 

  ?>

 

  ¢%08.2f 解释:

 

  %开始符

 

  0是 “填空字元” 表示,假使长度相差时就用0来填满。

 

  8格式化后总长度

 

  2f小数位长度,即2位

 

  ¢第3行值为”00123.10″ 解释:

 

  因为2f是(2位State of Qatar+小数点符号(1State of Qatar+前边123(3位卡塔尔国=6位,总参谋长度为8位,故后边用[填空字元]0表示,即00123.10

 

  ¢第4行值为”123.1000″ 解释:

 

  -号为反向操作,然后填空字元0增加在最终边了

 

  /********************************************************

 

  以下选自《CSDN 社区电子杂志——C/C++杂志》

 

  *********************************************************/

 

  在将各种类型的多少构产生字符串时,sprintf
的强有力效用少之甚少会让您深负众望。由于sprintf 跟printf
在用法上大约如出一辙,只是打字与印刷的目标地不一致而已,前面一个打字与印刷到字符串中,后面一个则一向在命令行上输出。那也导致sprintf
比printf 有用得多。

 

  sprintf 是个变参函数,定义如下:

 

  int sprintf( char *buffer, const char *format [, argument] …
);

 

  除了前四个参数类型定位外,前边能够接大肆八个参数。而它的精髓,明显就在其次个参数:

 

  格式化字符串上。

 

  printf 和sprintf
都选择格式化字符串来钦赐串的格式,在格式串内部接受一些以“%”早先的格式表明符(format
specifications)来吞噬二个岗位,在末端的变参列表中提供对应的变量,末了函数就能够用相应地方的变量来代表这个表明符,发生一个调用者想要的字符串。

剧情表达

  重临值:字符串长度(strlen)

格式化数字字符串

  sprintf 最广大的应用之一莫过于把整数打字与印刷到字符串中,所以,sprintf
在大超级多场馆能够替代

 

  itoa。

 

  如:

 

  //把整数123 打字与印刷成三个字符串保存在s 中。

 

  sprintf(s, “%d”, 123); //产生”123″

 

  能够钦赐宽度,不足的左侧补空格:

 

  sprintf(s, “%8d%8d”, 123, 4567); //产生:” 123 4567″

 

  当然也足以左对齐:

 

  sprintf(s, “%-8d%8d”, 123, 4567); //产生:”123 4567″

 

  也足以遵从16 进制打字与印刷:

 

  sprintf(s, “%8x”, 4567); //小写16 进制,宽度占8
个位置,右对齐

 

  sprintf(s, “%-8X”, 4568); //大写16 进制,宽度占8 个位置,左对齐

 

  那样,二个整数的16 进制字符串就十分轻易获得,但大家在打字与印刷16
进制内容时,日常想要一种侧面补0
的等宽格式,那该如何是好吗?非常粗略,在表示宽度的数字前边加个0 就能够了。

 

  sprintf(s, “%08X”, 4567); //产生:”000011D7″

 

  上面以”%d”实行的10 进制打字与印刷相近也能够采用这种左侧补0 的章程。

 

  这里要留心多个符号扩张的主题材料:比如,假若大家想打字与印刷短整数(short)-1
的内存16 进制表示情势,在Win32 平台上,一个short 型占2
个字节,所以大家自然期望用4 个16 进制数字来打印它:

 

  short si = -1;

 

  sprintf(s, “%04X”, si);

 

  发生“FFFFFFFF”,怎么回事?因为spritnf
是个变参函数,除了前边三个参数之外,前边的参数都不是项目安全的,函数更不曾章程唯有通过一个“%X”就能够识破当初函数调用前参数压栈时被压进来的毕竟是个4
字节的莫西干发型依然个2 字节的短整数,所以利用了合併4
字节的管理方式,引致参数压栈时做了标识扩大,扩展成了叁拾一个人的整数-1,打印时4 个地点缺乏了,就把32 位整数-1 的8 位16
进制都打字与印刷出来了。

 

  假诺你想看si
的原有,那么就应当让编译器做0
扩张而不是标记扩张(扩充时二进制左侧补0 实际不是补符号位):

 

  sprintf(s, “%04X”, (unsigned short)si);

 

  就足以了。可能:

 

  unsigned short si = -1;

 

  sprintf(s, “%04X”, si);

 

  sprintf 和printf 还能按8 进制打字与印刷整数字符串,使用”%o”。注意8
进制和16 进制都不会打

 

  印出负数,都以无符号的,实际上也正是变量的内部编码的直接的16 进制或8
进制表示。

 

  调整浮点数打字与印刷格式

 

  浮点数的打字与印刷和格式调控是sprintf
的又一大常用作用,浮点数使用格式符”%f”调节,暗中同意保

 

  留小数点后6 位数字,举例:

 

  sprintf(s, “%f”, 3.1415926); //产生”3.141593″

 

  但有时候大家愿意团结决定打字与印刷的上升的幅度和小数位数,那个时候就相应利用:”%m
/nf”格式,当中m 表

 

  示打字与印刷的宽窄,n 表示小数点后的位数。举个例子:

 

  sprintf(s, “%10.3f”, 3.1415626); //产生:” 3.142″

 

  sprintf(s, “%-10.3f”, 3.1415626); //产生:”3.142 “

 

  sprintf(s, “%.3f”, 3.1415626卡塔尔; //不内定总增加率,爆发:”3.142″

 

  注意多少个主题素材,你猜

 

  int i = 100;

 

  sprintf(s, “%.2f”, i);

 

  会打出哪些东东来?“100.00”?对吧?自个儿探求就知道了,同临时候也试试上边那些:

 

  sprintf(s, “%.2f”, (double)i);

 

  第一个打出去的确定不是对的结果,原因眼前边提到的同出一辙,参数压栈时调用者并不知道跟i相对应的格式调控符是个”%f”。而函数实行时函数自个儿则并不知道当年被压入栈里的是个整数,于是充裕的保留整数i
的那4
个字节就被无可批驳地强行作为浮点数格式来表明了,整个乱套了。但是,即使有人风乐趣使用手工业编码三个浮点数,那么倒能够行使这种艺术来验证一下你手工业编写制定的结果是或不是科学。

本函式用来将字串格式化。参数 format 是更动的格式,以百分比符号 %
开首到调换字符甘休。而在改造的格式间依序包罗了

  sprintf格式的标准如下所示。[]中的部分是可选的。

字符/Ascii 码对照

  大家明白,在C/C++语言中,char 也是一种平凡的scalable
类型,除了字长之外,它与short,

 

  int,long
那么些类别没有本质不一样,只然而被我们习贯用来代表字符和字符串而已。(只怕当初该把

 

  那一个项目叫做“byte”,然后现在就足以依靠实际景况,使用byte 或short
来把char 通过typedef
定义出来,那样更合适些)于是,使用”%d”可能”%x”打字与印刷叁个字符,便能得出它的10
进制或16 进制的ASCII
码;反过来,使用”%c”打字与印刷叁个大背头,便能够看来它所对应的ASCII字符。以下程序段把具有可知字符的ASCII
码对照表打字与印刷到荧屏上(这里运用printf,注意”#”与”%X”合用时自动为16
进制数扩展”0X”前缀):

 

  for(int i = 32; i < 127; i++) {

 

  printf(“[ %c ]: %3d 0x%#04Xn”, i, i, i);

 

  }

 

  连接字符串

 

  sprintf
的格式调控串中既然能够插入种种东西,并最终把它们“连成一串”,自然也就可以知道连

 

  接字符串,进而在相当多场面能够取代strcat,但sprintf
能够一次延续三个字符串(自然也足以同一时间

 

  在它们当中插入其余内容,简单来讲极度灵活)。比方:

 

  char* who = “I”;

 

  char* whom = “CSDN”;

 

  sprintf(s, “%s love %s.”, who, whom); //产生:”I love CSDN. “

 

  strcat
只好再而三字符串(一段以’’结尾的字符数组或称为字符缓冲,null-terminated-string),但不经常候大家有两段字符缓冲区,他们而不是以
’’结尾。举例超级多从第三方库函数中回到的字符数组,从硬件依然互连网传输中读进去的字符流,它们未必每一段字符类别前边都有个照料的’’来最终。即使直白连接,不管是sprintf
照旧strcat 断定会招致违规内部存款和储蓄器操作,而strncat
也起码要求首先个参数是个null-terminated-string,那该如何做呢?大家自然会想起前边介绍打字与印刷整数和浮点数时能够内定宽度,字符串也相仿的。比方:

 

  char a1[] = {‘A’, ‘B’, ‘C’, ‘D’, ‘E’, ‘F’, ‘G’};

 

  char a2[] = {‘H’, ‘I’, ‘J’, ‘K’, ‘L’, ‘M’, ‘N’};

 

  如果:

 

  sprintf(s, “%s%s”, a1, a2); //Don’t do that!

 

  十之八九要出标题了。是不是能够改成:

 

  sprintf(s, “%7s%7s”, a1, a2);

 

  也没好到哪个地方去,正确的相应是:

 

  sprintf(s, “%.7s%.7s”, a1, a2);//产生:”ABCDEFGHIJKLMN”

 

  那能够类比打字与印刷浮点数的”%m/nf”,在”%m.ns”中,m
代表占用宽度(字符串长度相差时补空格,超出了则遵照实际拉长率打字与印刷),n
才表示从相应的字符串中最多取用的字符数。平常在打字与印刷字符串时m
没什么大用,依然点号前面包车型客车n 用的多。自然,也得早先后都只取部分字符:

 

  sprintf(s, “%.6s%.5s”, a1, a2);//产生:”ABCDEFHIJKL”

 

  在众多时候,我们或然还期望这一个格式调整符中用以内定长度音信的数字是动态的,并非静态钦命的,因为超级多时候,程序要到运转时才会通晓到底须求取字符数组中的多少个字符,这种动态的大幅度/精度设置功用在sprintf
的贯彻中也被思谋到了,sprintf
选取”*”来占领贰个自然必要多少个内定宽度或精度的常数数字的岗位,相仿,而实在的大幅或精度就足以和其余被打字与印刷的变量同样被提供出来,于是,上边的事例能够产生:

 

  sprintf(s, “%.*s%.*s”, 7, a1, 7, a2);

 

  或者:

 

  sprintf(s, “%.*s%.*s”, sizeof(a1), a1, sizeof(a2), a2);

 

  实际上,后边介绍的打字与印刷字符、整数、浮点数等都能够动态钦赐那几个常量值,举个例子:

 

  sprintf(s, “%-*d”, 4, ‘A’); //产生”65 “

 

  sprintf(s, “%#0*X”, 8, 128); //产生”0X000080″,”#”产生0X

 

  sprintf(s, “%*.*f”, 10, 2, 3.1415926); //产生” 3.14″

 

  打字与印刷地址音信

 

  有时调节和测量试验程序时,大家兴许想查看某个变量或然成员之处,由于地方或然指针也只是是个三十七位的数,你完全能够运用打字与印刷无标记整数的”%u”把他们打字与印刷出来:

 

  sprintf(s, “%u”, &i);

 

  可是一般大家依然向往使用16 进制而不是10 进制来浮现三个地点:

 

  sprintf(s, “%08X”, &i);

 

  然则,这么些都以直接的措施,对于地点打字与印刷,sprintf 提供了极其的”%p”:

 

  sprintf(s, “%p”, &i);

 

  小编觉着它实在就也就是:

 

  sprintf(s, “%0*x”, 2 * sizeof(void *), &i);

 

  利用sprintf 的再次回到值

 

  较稀有人注意printf/sprintf 函数的再次来到值,但奇迹它却是有用的,spritnf
再次回到了本次函数调用

 

  最后打字与印刷到字符缓冲区中的字符数目。也正是说每当叁次sprinf
调用结束之后,你无须再调用一次

 

  strlen 便一度知晓了结果字符串的长度。如:

 

  int len = sprintf(s, “%d”, i);

 

  对夏梅整数来讲,len 便等于整数i 的10 进制位数。

 

  下边包车型大巴是个一体化的例子,发生10 个[0,
100State of Qatar之间的专断数,并将她们打字与印刷到七个字符数组s 中,

 

  以逗号分隔开分离。

 

  #include <stdio.h>

 

  #include <stdlib.h>

 

  #include <time.h>

 

  int main() {

 

  srand(time(0));

 

  char s[64];

 

  int offset = 0;

 

  for(int i = 0; i < 10; i++) {

 

  offset += sprintf(s + offset, “%d,”, rand() % 100);

 

  }

 

  s[offset – 1] = ‘n’;//将最终三个逗号换来换行符。

 

  printf(s);

 

  return 0;

 

  }

 

  虚构当您从数据库中抽取一条记下,然后希望把他们的顺序字段遵照某种规则连接成一个字

 

  符串时,就足以选择这种方式,从理论上讲,他应该比不断的strcat
功能高,因为strcat 每便调用

 

  都亟需先找到最终的特别’’的岗位,而在上头给出的例证中,大家每回都使用sprintf
重回值把那

 

  个岗位平昔记下来了。

 

  MSDN中例子:

 

  // crt_sprintf.c// compile with: /W3// This program uses sprintf to
format various// data and place them in the string named buffer.

 

  #include <stdio.h>

 

  int main( void )

 

  {

 

  char buffer[200], s[] = “computer”, c = ‘l’;

 

  int i = 35, j;

 

  float fp = 1.7320534f; // Format and print various data:

 

  j = sprintf( buffer, ” String: %sn”, s ); // C4996

 

  j += sprintf( buffer + j, ” Character: %cn”, c ); // C4996

 

  j += sprintf( buffer + j, ” Integer: %dn”, i ); // C4996

 

  j += sprintf( buffer + j, ” Real: %fn”, fp );// C4996

 

  // Note: sprintf is deprecated; consider using sprintf_s instead

 

  printf( “Output:n%sncharacter count = %dn”, buffer, j );

 

  }

 

  Copy

 

  Output:

 

  String: computer

 

  Character: l

 

  Integer: 35

 

  Real: 1.732053

 

  character count = 79

 

  1. 填空字元。0 的话代表空格填 0;空格是钦定值,表示空格就放着。

  2. 对齐格局。内定值为向右对齐,负号表向左对齐。

  3. 栏位宽度。为最小宽度。

  4. 正确度。指在小数点后的浮点数位数。

  %[点名参数$][标识符][宽度][.精度]指示符

编写制定本段动用sprintf 的大范围难点

  sprintf
是个变参函数,使用时平时出标题,何况只要出难题平时就是能变成程序崩溃的内部存款和储蓄器访

 

  问错误,但万幸由sprintf
误用招致的主题材料尽管严重,却相当轻便找寻,无非便是那么两种状态,通

 

  常用眼睛再把失误的代码多看几眼就看出来了。

 

  sprintf_s(卡塔尔国是sprintf(卡塔尔的福建银针版本,通过点名缓冲区长度来制止sprintf(卡塔尔国存在的溢出危机。在动用VS二零零六时一经你利用了sprintf函数,那么编写翻译器会发生警告:使用sprintf存在危害,提议使用sprintf_s。这几个安全版本的原型是:

 

  int sprintf_s(char *buffer,size_t sizeOfBuffer,const char
*format [,argument] … );

 

  缓冲区溢出

 

  第二个参数的尺寸太短了,没的说,给个大点的地点啊。当然也会有可能是前面的参数的问

 

  题,提出变参对应必须求致密,而打字与印刷字符串时,尽量利用”%.ns”的款式内定最大字符数。

 

  忘记了第一个参数

 

  低档得不可能再起码难题,用printf 用得太惯了。//偶就常犯。:。(

 

  变参对应出标题

 

  常常是忘记了提供对应某些格式符的变参,导致以往的参数统统错位,检查检查吗。尤

 

  其是对应”*”的那多少个参数,都提供了吧?不要把二个卡尺头对应三个”%s”,编译器会认为你

 

  欺她太甚了(编写翻译器是obj 和exe 的母亲,应该是个女的,:P)。

 

  strftime

 

  sprnitf
还应该有个精确的表姐:strftime,特意用来格式化时间字符串的,用法跟她三弟很像,也

 

  是一大堆格式调控符,只是究竟阿奶奶家心细,她还要调用者钦定缓冲区的最大尺寸,也许是为

 

  了在现身难题时能够推卸义务吧。这里举个例证:

 

  time_t t = time(0);

 

  //爆发”YYYY-MM-DD hh:mm:ss”格式的字符串。

 

  char s[32];

 

  strftime(s, sizeof(s), “%Y-%m-%d %H:%M:%S”, localtime(&t));

 

  sprintf 在MFC 中也能找到她的知心人:CString::Format,strftime 在MFC
中本来也许有她的同道:

 

  CTime::Format,这一对由于从面向对象哪个地方得到了支持,用以写出的代码更觉高雅。

型态,见下表

  若想出口`%’本身时, 请这样`%%’处理。

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-转变字符=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-%
印出百分比符号,不调换。 b 整数转成二进位。 c 整数转成对应的 ASCII
字元。 d 整数转成十进位。 f 倍正确度数字转成浮点数。 o 整数转成八进位。
s 整数转成字串。 x 整数转成小写十七进位。 X 整数转成大写十三进位。

  1. 管理字符方向。负号时表示从后迈入管理。

例子

  2. 填空字元。 0 的话代表空格填 0;空格是内定值,表示空格就放着。

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

  3. 字符总宽度。为最小宽度。

利用圭表

  4. 准确度。指在小数点后的浮点数位数。

?$money1 = 68.75;$money2 = 54.35;$money = $money1 + $money2;// 那时候变数
$money 值为 123.1;$formatted = sprintf (%01.2f, $moneyState of Qatar;// 那个时候变数 $
formatted 值为 123.10?

  =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

  转变字符

其一 %01.2f 是哪些看头吧?

  =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

率先 这么些 % 符号是从头的情致,他写在最前头表示钦赐格式要起来了。 也正是开始字符, 直到现身 转变字符 甘休,就算格式终止。

  %% 印出百分比符号,不改换。

接下来 跟在 % 符号 前面的是 0 这么些零是 填空字元 表示,借使地方空着
就用0来填满。在 0 前面包车型大巴是 1 这些 1
是规定,小数点前边的数字占位要有1位以上。

  %c 整数转成对应的 ASCII 字元。

即使把 1 改成 2 假如 $money 的值为 1.23 ,则 $formatted 的值将为
01.23因为,在小数点前边的数字只占了1位,依照地点所鲜明的格式,小数点前数字应该占2位,今后唯有1位,所以,用0来填满。

  %d 整数转成十进位。

到日前,在 %01 前面包车型客车 .2 (点2)就很好驾驭了,它的意思是,规定,小数点后的数字,必须占2位. 借使这时,$money
的值为 1.234,则 $formatted 的值将为 1.23。为何 4 不见了啊?
因为,在小数点前面 依照上边的明确,必得且仅能占2位。 不过 $money
的值中,小数点占了3位,所以,4 被去掉了,只剩下 23。

  %f 倍精确度数字转成浮点数。

最后,以 f 转变字符 结尾,其余转变字符请自行参考上边的调换字符列表。

  %o 整数转成八进位。

关于对齐

  %s 整数转成字串。

假设在 % 开头符号前面 加上 – (负号卡塔尔则,将会把数字以向右对齐的法子张开管理。

  %x 整数转成小写十三进位。

列子

  %X 整数转成大写十九进位。

?$money = 1.4;

  =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

$formatted = sprintf (%-02.2f, $money);

  <?

echo $formatted;?

  $money = 123.1

那个时候,$formatted 将不会再是 01.40 而是 1.400

  $formatted = sprintf (“%06.2f”, $moneyState of Qatar; // 当时变数 $ formatted
值为 “123.10”

<

  $formatted = sprintf (“%08.2f”, $money卡塔尔国; // 当时变数 $ formatted
值为 “00123.10”

  $formatted = sprintf (“%-08.2f”, $moneyState of Qatar; // 那时候变数 $ formatted
值为 “123.1000”

  $formatted = sprintf (“%.2f%%”, 0.95 * 100卡塔尔(قطر‎; // 格式化为百分比

  ?>

  ¢%08.2f 解释:

  %开始符

  0是 “填空字元” 表示,假如长度相差时就用0来填满。

  8格式化后总参谋长度

  2f小数位长度,即2位

  ¢第3行值为”00123.10″ 解释:

  因为2f是(2位卡塔尔国+小数点符号(1卡塔尔+后边123(3位卡塔尔(قطر‎=6位,总参谋长度为8位,故前边用[填空字元]0表示,即00123.10

  ¢第4行值为”123.1000″ 解释:

  -号为反向操作,然后填空字元0增多在最后边了

  /********************************************************

  以下选自《CSDN 社区电子杂志——C/C++杂志》

  *********************************************************/

  在将各连串型的数据构形成字符串时,sprintf
的强硬效能超少会让您失望。由于sprintf 跟printf
在用法上差不离一致,只是打字与印刷的指标地分歧而已,前面三个打字与印刷到字符串中,后面一个则一贯在命令行上输出。那也以致sprintf
比printf 有用得多。

  sprintf 是个变参函数,定义如下:

  int sprintf( char *buffer, const char *format [, argument] …
);

  除了前四个参数类型定位外,后边能够接猖獗五个参数。而它的精华,分明就在其次个参数:

  格式化字符串上。

  printf 和sprintf
都施用格式化字符串来钦赐串的格式,在格式串内部使用部分以“%”开始的格式表明符(format
specifications)来损人益己三个岗位,在末端的变参列表中提供对应的变量,最后函数就能用相应地点的变量来代表那些表明符,发生多个调用者想要的字符串。

  格式化数字字符串

  sprintf 最粗心浮气的使用之一莫过于把整数打字与印刷到字符串中,所以,spritnf
在当先49%场所能够代替

  itoa。

  如:

  //把整数123 打印成多个字符串保存在s 中。

  sprintf(s, “%d”, 123); //产生”123″

  能够钦命宽度,不足的侧面补空格:

  sprintf(s, “%8d%8d”, 123, 4567); //产生:” 123 4567″

  当然也足以左对齐:

  sprintf(s, “%-8d%8d”, 123, 4567); //产生:”123 4567″

  也足以固守16 进制打字与印刷:

  sprintf(s, “%8x”, 4567); //小写16 进制,宽度占8 个位置,右对齐

  sprintf(s, “%-8X”, 4568); //大写16 进制,宽度占8 个位置,左对齐

  那样,三个卡尺头的16 进制字符串就比较轻松得到,但大家在打印16
进制内容时,日常想要一种左侧补0
的等宽格式,那该如何做啊?相当的粗略,在代表宽度的数字前边加个0 就能够了。

  sprintf(s, “%08X”, 4567); //产生:”000011D7″

  下边以”%d”举办的10 进制打字与印刷相通也足以动用这种左边补0 的法子。

  这里要专心二个标识增添的主题素材:比方,假若大家想打印短整数(short)-1
的内部存款和储蓄器16 进制表示格局,在Win32 平台上,一个short 型占2
个字节,所以大家自然希望用4 个16 进制数字来打字与印刷它:

  short si = -1;

  sprintf(s, “%04X”, si);

  产生“FFFFFFFF”,怎么回事?因为spritnf
是个变参函数,除了前边三个参数之外,前面包车型地铁参数都不是类别安全的,函数更不曾艺术只有经过二个“%X”就会认识到当初函数调用前参数压栈时被压进来的到底是个4
字节的板一寸照片旧个2 字节的短整数,所以接纳了联合4
字节的管理情势,招致参数压栈时做了符号扩充,扩大成了30位的平头-1,打字与印刷时4 个岗位缺乏了,就把32 位整数-1 的8 位16
进制都打字与印刷出来了。

  要是您想看si 的原来,那么就活该让编写翻译器做0
扩大并非标记扩充(扩张时二进制左侧补0 实际不是补符号位):

  sprintf(s, “%04X”, (unsigned short)si);

  就能够了。恐怕:

  unsigned short si = -1;

  sprintf(s, “%04X”, si);

  sprintf 和printf 还是可以够按8 进制打字与印刷整数字符串,使用”%o”。注意8
进制和16 进制都不会打

  印出负数,都是无符号的,实际上也正是变量的内部编码的直白的16 进制或8
进制表示。

  调节浮点数打字与印刷格式

  浮点数的打字与印刷和格式调节是sprintf
的又一大常用功效,浮点数使用格式符”%f”调控,暗中同意保

  留小数点后6 位数字,譬如:

  sprintf(s, “%f”, 3.1415926); //产生”3.141593″

  但奇迹大家盼望自身主宰打字与印刷的增进率和小数位数,这个时候就活该利用:”%m
/nf”格式,在那之中m 表

  示打字与印刷的肥瘦,n 代表小数点后的位数。举个例子:

  sprintf(s, “%10.3f”, 3.1415626); //产生:” 3.142″

  sprintf(s, “%-10.3f”, 3.1415626); //产生:”3.142 “

  sprintf(s, “%.3f”, 3.1415626卡塔尔(قطر‎; //不钦点总增长幅度,发生:”3.142″

  注意八个主题素材,你猜

  int i = 100;

  sprintf(s, “%.2f”, i);

  会打出什么样东东来?“100.00”?对吧?自个儿试试就理解了,同偶然候也尝试上面这几个:

  sprintf(s, “%.2f”, (double)i);

  第二个打出来的必定不是没有错结果,原因面前边提到的雷同,参数压栈时调用者并不知道跟i相对应的格式调整符是个”%f”。而函数实行时函数自己则并不知道当年被压入栈里的是个整数,于是丰硕的保存整数i
的那4
个字节就被没有什么可争辨的地强行作为浮点数格式来表达了,整个乱套了。不过,假诺有人风乐趣使用手工业编码一个浮点数,那么倒能够运用这种格局来视察一下您手工业编写制定的结果是还是不是正确。

  字符/Ascii 码对照

  我们清楚,在C/C++语言中,char
也是一种普通的scalable 类型,除了字长之外,它与short,

  int,long
这一个连串未有本质差距,只可是被我们习于旧贯用来代表字符和字符串而已。(或者当初该把

  这几个连串叫做“byte”,然后今后就能够依照实际意况,使用byte 或short
来把char 通过typedef
定义出来,那样更合适些)于是,使用”%d”只怕”%x”打字与印刷三个字符,便能搜查缴获它的10
进制或16 进制的ASCII
码;反过来,使用”%c”打印三个整数,便得以观望它所对应的ASCII
字符。以下程序段把全数可知字符的ASCII
码对照表打字与印刷到显示屏上(这里运用printf,注意”#”与”%X”合用时自动为16
进制数扩充”0X”前缀):

  for(int i = 32; i < 127; i++) {

  printf(“[ %c ]: %3d 0x%#04X/n”, i, i, i);

  }

连续几天来字符串

  sprintf
的格式调整串中既然能够插入各样东西,并最后把它们“连成一串”,自然也就能够连

  接字符串,进而在不菲场子能够代替strcat,但sprintf
能够三次接二连三四个字符串(自然也得以并且

  在它们中间插入其他内容,同理可得特别灵活)。举例:

  char* who = “I”;

  char* whom = “CSDN”;

  sprintf(s, “%s love %s.”, who, whom); //产生:”I love CSDN. “

  strcat
只好三番五次字符串(一段以’’结尾的字符数组或称为字符缓冲,null-terminated-string),但一时候我们有两段字符缓冲区,他们而不是以
’’结尾。比如好多从第三方库函数中回到的字符数组,从硬件依然互联网传输中读进去的字符流,它们未必每一段字符种类后边都有个照望的’’来最后。倘若一向连接,不管是sprintf
照旧strcat 断定会促成违规内部存款和储蓄器操作,而strncat
也最少需求首先个参数是个null-terminated-string,那该如何做吧?大家本来会想起前面介绍打字与印刷整数和浮点数时可以钦赐宽度,字符串也相像的。举个例子:

  char a1[] = {‘A’, ‘B’, ‘C’, ‘D’, ‘E’, ‘F’, ‘G’};

  char a2[] = {‘H’, ‘I’, ‘J’, ‘K’, ‘L’, ‘M’, ‘N’};

  如果:

  sprintf(s, “%s%s”, a1, a2); //Don’t do that!

  十之八九要出标题了。是还是不是足以改成:

  sprintf(s, “%7s%7s”, a1, a2);

  也没好到哪儿去,正确的相应是:

  sprintf(s, “%.7s%.7s”, a1, a2);//产生:”ABCDEFGHIJKLMN”

  那能够类比打字与印刷浮点数的”%m/nf”,在”%m.ns”中,m
代表占用宽度(字符串长度相差时补空格,超过了则根据实际拉长率打字与印刷),n
才表示从相应的字符串中最多取用的字符数。平日在打字与印刷字符串时m
没什么大用,还是点号后边的n 用的多。自然,也得从前后都只取部分字符:

  sprintf(s, “%.6s%.5s”, a1, a2);//产生:”ABCDEFHIJKL”

  在很多时候,我们兴许还期望那个格式调节符中用以钦赐长度音讯的数字是动态的,实际不是静态钦赐的,因为多数时候,程序要到运行时才会掌握到底必要取字符数组中的多少个字符,这种动态的大幅/精度设置效率在sprintf
的兑现中也被思量到了,sprintf
选取”*”来并吞二个当然要求三个内定宽度或精度的常数数字的岗位,相符,而其实的增长幅度或精度就足以和其余被打字与印刷的变量相符被提供出来,于是,上边的事例可以成为:

  sprintf(s, “%.*s%.*s”, 7, a1, 7, a2);

  或者:

  sprintf(s, “%.*s%.*s”, sizeof(a1), a1, sizeof(a2), a2);

  实际上,前面介绍的打字与印刷字符、整数、浮点数等都足以动态钦定那个常量值,举个例子:

  sprintf(s, “%-*d”, 4, ‘A’); //产生”65 “

  sprintf(s, “%#0*X”, 8, 128); //产生”0X000080″,”#”产生0X

  sprintf(s, “%*.*f”, 10, 2, 3.1415926); //产生” 3.14″

  打字与印刷地址新闻

  不常调节和测量检验程序时,大家只怕想查看有些变量或者成员的地点,由于地方也许指针也只是是个三九人的数,你一丝一毫能够应用打印无标记整数的”%u”把他们打字与印刷出来:

  sprintf(s, “%u”, &i);

  不过常常大家照旧合意使用16 进制而不是10 进制来呈现二个地方:

  sprintf(s, “%08X”, &i);

  不过,这一个都是直接的艺术,对于地方打字与印刷,sprintf 提供了非常的”%p”:

  sprintf(s, “%p”, &i);

  小编认为它事实上就约等于:

  sprintf(s, “%0*x”, 2 * sizeof(void *), &i);

  利用sprintf 的重回值

  较罕有人注意printf/sprintf 函数的重返值,但一时候它却是有用的,spritnf
再次回到了此番函数调用

  最后打字与印刷到字符缓冲区中的字符数目。也正是说每当叁遍sprinf
调用截至之后,你无须再调用三遍

  strlen 便已经驾驭了结果字符串的尺寸。如:

  int len = sprintf(s, “%d”, i);

  对刘阳整数来讲,len 便等于整数i 的10 进制位数。

  下边包车型大巴是个总体的例证,发生10 个[0,
100卡塔尔国之间的即兴数,并将她们打字与印刷到多个字符数组s 中,

  以逗号分隔绝。

  #include

  #include

  #include

  int main() {

  srand(time(0));

  char s[64];

  int offset = 0;

  for(int i = 0; i < 10; i++) {

  offset += sprintf(s + offset, “%d,”, rand() % 100);

  }

  s[offset – 1] = ‘/n’;//将最终贰个逗号换来换行符。

  printf(s);

  return 0;

  }

  杜撰当您从数据库中收取一条记下,然后希望把她们的次第字段按照某种法则连接成叁个字

  符串时,就能够动用这种情势,从理论上讲,他应有比不断的strcat
效用高,因为strcat 每一遍调用

  都供给先找到最终的那么些’’的岗位,而在上头给出的例子中,大家每一趟都选用sprintf
再次来到值把那

  个岗位一向记下来了。

  MSDN中例子:

  // crt_sprintf.c// compile with: /W3// This program uses sprintf to
format various// data and place them in the string named buffer.

  #include <stdio.h>

  int main( void )

  {

  char buffer[200], s[] = “computer”, c = ‘l’;

  int i = 35, j;

  float fp = 1.7320534f; // Format and print various data:

  j = sprintf( buffer, ” String: %s/n”, s ); // C4996

  j += sprintf( buffer + j, ” Character: %c/n”, c ); // C4996

  j += sprintf( buffer + j, ” Integer: %d/n”, i ); // C4996

  j += sprintf( buffer + j, ” Real: %f/n”, fp );// C4996

  // Note: sprintf is deprecated; consider using sprintf_s instead

  printf( “Output:/n%s/ncharacter count = %d/n”, buffer, j );

  }

  Copy

  Output:

  String: computer

  Character: l

  Integer: 35

  Real: 1.732053

  character count = 79

  编辑本段

  使用sprintf 的科学普及难题

  sprintf
是个变参函数,使用时平常出难题,况兼只要出标题普通正是能招致程序崩溃的内部存款和储蓄器访

  问错误,但还好由sprintf
误用招致的主题材料就算严重,却比较轻松寻找,无非正是那么三种状态,通

  常用眼睛再把失误的代码多看几眼就看出来了。

  ?? 缓冲区溢出

  第一个参数的长度太短了,没的说,给个大点的地点啊。当然也大概是背后的参数的问

  题,提议变参对应必供给精心,而打字与印刷字符串时,尽量利用”%.ns”的方式钦命最大字符数。

  ?? 忘记了第3个参数

  低端得无法再初级难题,用printf 用得太惯了。//偶就常犯。:。(

  ?? 变参对应出难点

  常常是忘记了提供相应有个别格式符的变参,招致随后的参数统统错位,检查检查吗。尤

  其是对应”*”的那叁个参数,都提供了吗?不要把贰个子弹头对应叁个”%s”,编译器会感觉你

  欺她太甚了(编写翻译器是obj 和exe 的母亲,应该是个女的,:P)。

  strftime

  sprnitf
还会有个科学的大嫂:strftime,特地用来格式化时间字符串的,用法跟她四弟很像,也

  是一大堆格式调整符,只是终究大妈婆家心细,她还要调用者钦命缓冲区的最大尺寸,或许是为

  了在现身难题时得以推卸权利吧。这里举个例证:

  time_t t = time(0);

  //发生”YYYY-MM-DD hh:mm:ss”格式的字符串。

  char s[32];

  strftime(s, sizeof(s), “%Y-%m-%d %H:%M:%S”, localtime(&t));

  sprintf 在MFC 中也能找到他的相守:CString::Format,strftime 在MFC
中自然也可能有她的同道:

  CTime::Format,这一对由于从面向对象何地得到了帮衬,用以写出的代码更觉文雅。

发表评论

电子邮件地址不会被公开。 必填项已用*标注