整理:C++中sprintf()函数的使用详解
描述
C 庫(kù)函數(shù)?int sprintf(char *str, const char *format, ...)?發(fā)送格式化輸出到?str?所指向的字符串。
聲明
下面是 sprintf() 函數(shù)的聲明。
int sprintf(char *str, const char *format, ...)參數(shù)
- str?-- 這是指向一個(gè)字符數(shù)組的指針,該數(shù)組存儲(chǔ)了 C 字符串。
- format?-- 這是字符串,包含了要被寫(xiě)入到字符串 str 的文本。它可以包含嵌入的 format 標(biāo)簽,format 標(biāo)簽可被隨后的附加參數(shù)中指定的值替換,并按需求進(jìn)行格式化。format 標(biāo)簽屬性是?%[flags][width][.precision][length]specifier,具體講解如下:
| c | 字符 |
| d 或 i | 有符號(hào)十進(jìn)制整數(shù) |
| e | 使用 e 字符的科學(xué)科學(xué)記數(shù)法(尾數(shù)和指數(shù)) |
| E | 使用 E 字符的科學(xué)科學(xué)記數(shù)法(尾數(shù)和指數(shù)) |
| f | 十進(jìn)制浮點(diǎn)數(shù) |
| g | 自動(dòng)選擇 %e 或 %f 中合適的表示法 |
| G | 自動(dòng)選擇 %E 或 %f 中合適的表示法 |
| o | 有符號(hào)八進(jìn)制 |
| s | 字符的字符串 |
| u | 無(wú)符號(hào)十進(jìn)制整數(shù) |
| x | 無(wú)符號(hào)十六進(jìn)制整數(shù) |
| X | 無(wú)符號(hào)十六進(jìn)制整數(shù)(大寫(xiě)字母) |
| p | 指針地址 |
| n | 無(wú)輸出 |
| % | 字符 |
| - | 在給定的字段寬度內(nèi)左對(duì)齊,默認(rèn)是右對(duì)齊(參見(jiàn) width 子說(shuō)明符)。 |
| + | 強(qiáng)制在結(jié)果之前顯示加號(hào)或減號(hào)(+ 或 -),即正數(shù)前面會(huì)顯示 + 號(hào)。默認(rèn)情況下,只有負(fù)數(shù)前面會(huì)顯示一個(gè) - 號(hào)。 |
| (space) | 如果沒(méi)有寫(xiě)入任何符號(hào),則在該值前面插入一個(gè)空格。 |
| # | 與 o、x 或 X 說(shuō)明符一起使用時(shí),非零值前面會(huì)分別顯示 0、0x 或 0X。 與 e、E 和 f 一起使用時(shí),會(huì)強(qiáng)制輸出包含一個(gè)小數(shù)點(diǎn),即使后邊沒(méi)有數(shù)字時(shí)也會(huì)顯示小數(shù)點(diǎn)。默認(rèn)情況下,如果后邊沒(méi)有數(shù)字時(shí)候,不會(huì)顯示顯示小數(shù)點(diǎn)。 與 g 或 G 一起使用時(shí),結(jié)果與使用 e 或 E 時(shí)相同,但是尾部的零不會(huì)被移除。 |
| 0 | 在指定填充 padding 的數(shù)字左邊放置零(0),而不是空格(參見(jiàn) width 子說(shuō)明符)。 |
| (number) | 要輸出的字符的最小數(shù)目。如果輸出的值短于該數(shù),結(jié)果會(huì)用空格填充。如果輸出的值長(zhǎng)于該數(shù),結(jié)果不會(huì)被截?cái)唷?/span> |
| * | 寬度在 format 字符串中未指定,但是會(huì)作為附加整數(shù)值參數(shù)放置于要被格式化的參數(shù)之前。 |
| .number | 對(duì)于整數(shù)說(shuō)明符(d、i、o、u、x、X):precision 指定了要寫(xiě)入的數(shù)字的最小位數(shù)。如果寫(xiě)入的值短于該數(shù),結(jié)果會(huì)用前導(dǎo)零來(lái)填充。如果寫(xiě)入的值長(zhǎng)于該數(shù),結(jié)果不會(huì)被截?cái)?。精度?0 意味著不寫(xiě)入任何字符。 對(duì)于 e、E 和 f 說(shuō)明符:要在小數(shù)點(diǎn)后輸出的小數(shù)位數(shù)。 對(duì)于 g 和 G 說(shuō)明符:要輸出的最大有效位數(shù)。 對(duì)于 s: 要輸出的最大字符數(shù)。默認(rèn)情況下,所有字符都會(huì)被輸出,直到遇到末尾的空字符。 對(duì)于 c 類型:沒(méi)有任何影響。 當(dāng)未指定任何精度時(shí),默認(rèn)為 1。如果指定時(shí)不帶有一個(gè)顯式值,則假定為 0。 |
| .* | 精度在 format 字符串中未指定,但是會(huì)作為附加整數(shù)值參數(shù)放置于要被格式化的參數(shù)之前。 |
| h | 參數(shù)被解釋為短整型或無(wú)符號(hào)短整型(僅適用于整數(shù)說(shuō)明符:i、d、o、u、x 和 X)。 |
| l | 參數(shù)被解釋為長(zhǎng)整型或無(wú)符號(hào)長(zhǎng)整型,適用于整數(shù)說(shuō)明符(i、d、o、u、x 和 X)及說(shuō)明符 c(表示一個(gè)寬字符)和 s(表示寬字符字符串)。 |
| L | 參數(shù)被解釋為長(zhǎng)雙精度型(僅適用于浮點(diǎn)數(shù)說(shuō)明符:e、E、f、g 和 G)。 |
- 附加參數(shù)?-- 根據(jù)不同的 format 字符串,函數(shù)可能需要一系列的附加參數(shù),每個(gè)參數(shù)包含了一個(gè)要被插入的值,替換了 format 參數(shù)中指定的每個(gè) % 標(biāo)簽。參數(shù)的個(gè)數(shù)應(yīng)與 % 標(biāo)簽的個(gè)數(shù)相同。
返回值
如果成功,則返回寫(xiě)入的字符總數(shù),不包括字符串追加在字符串末尾的空字符。如果失敗,則返回一個(gè)負(fù)數(shù)。
實(shí)例
下面的實(shí)例演示了 sprintf() 函數(shù)的用法。
#include <stdio.h> #include <math.h>int main() {char str[80];sprintf(str, "Pi 的值 = %f", M_PI);puts(str);return(0); }讓我們編譯并運(yùn)行上面的程序,這將產(chǎn)生以下結(jié)果:
Pi 的值 = 3.141593
資料二
在將各種類型的數(shù)據(jù)構(gòu)造成字符串時(shí),sprintf 的強(qiáng)大功能很少會(huì)讓你失望。由于sprintf 跟printf 在用法上幾乎一樣,只是打印的目的地不同而已,前者打印到字符串中,后者則直接在命令行上輸出。這也導(dǎo)致sprintf 比printf 有用得多。
sprintf 是個(gè)變參函數(shù),定義如下:int sprintf( char *buffer, const char *format [, argument] ... );
除了前兩個(gè)參數(shù)類型固定外,后面可以接任意多個(gè)參數(shù)。而它的精華,顯然就在第二個(gè)參數(shù):
(1)格式化字符串上。
printf 和sprintf 都使用格式化字符串來(lái)指定串的格式,在格式串內(nèi)部使用一些以“%”開(kāi)頭的格式說(shuō)明符(format specifications)來(lái)占據(jù)一個(gè)位置,在后邊的變參列表中提供相應(yīng)的變量,最終函數(shù)就會(huì)用相應(yīng)位置的變量來(lái)替代那個(gè)說(shuō)明符,產(chǎn)生一個(gè)調(diào)用者想要的字符串。
格式化數(shù)字字符串
sprintf 最常見(jiàn)的應(yīng)用之一莫過(guò)于把整數(shù)打印到字符串中,所以,spritnf 在大多數(shù)場(chǎng)合可以替代itoa。
如:
//把整數(shù)123 打印成一個(gè)字符串保存在s 中。
sprintf(s, "%d", 123); //產(chǎn)生"123"
可以指定寬度,不足的左邊補(bǔ)空格:
sprintf(s, "%8d%8d", 123, 4567); //產(chǎn)生:" 123 4567"
當(dāng)然也可以左對(duì)齊:
sprintf(s, "%-8d%8d", 123, 4567); //產(chǎn)生:"123 4567"
也可以按照16 進(jìn)制打印:
sprintf(s, "%8x", 4567); //小寫(xiě)16 進(jìn)制,寬度占8 個(gè)位置,右對(duì)齊
sprintf(s, "%-8X", 4568); //大寫(xiě)16 進(jìn)制,寬度占8 個(gè)位置,左對(duì)齊
這樣,一個(gè)整數(shù)的16 進(jìn)制字符串就很容易得到,但我們?cè)诖蛴?6 進(jìn)制內(nèi)容時(shí),通常想要一種左邊補(bǔ)0 的等寬格式,那該怎么做呢?很簡(jiǎn)單,在表示寬度的數(shù)字前面加個(gè)0 就可以了。
sprintf(s, "%08X", 4567); //產(chǎn)生:"000011D7"
上面以”%d”進(jìn)行的10 進(jìn)制打印同樣也可以使用這種左邊補(bǔ)0 的方式。
這里要注意一個(gè)符號(hào)擴(kuò)展的問(wèn)題:比如,假如我們想打印短整數(shù)(short)-1 的內(nèi)存16 進(jìn)制表示形式,在Win32 平臺(tái)上,一個(gè)short 型占2 個(gè)字節(jié),所以我們自然希望用4 個(gè)16 進(jìn)制數(shù)字來(lái)打印它:
short si = -1;
sprintf(s, "%04X", si);
產(chǎn)生“FFFFFFFF”,怎么回事?因?yàn)閟pritnf 是個(gè)變參函數(shù),除了前面兩個(gè)參數(shù)之外,后面的參數(shù)都不是類型安全的,函數(shù)更沒(méi)有辦法僅僅通過(guò)一個(gè)“%X”就能得知當(dāng)初函數(shù)調(diào)用前參數(shù)壓棧時(shí)被壓進(jìn)來(lái)的到底是個(gè)4 字節(jié)的整數(shù)還是個(gè)2 字節(jié)的短整數(shù),所以采取了統(tǒng)一4 字節(jié)的處理方式,導(dǎo)致參數(shù)壓棧時(shí)做了符號(hào)擴(kuò)展,擴(kuò)展成了32 位的整數(shù)-1,打印時(shí)4 個(gè)位置不夠了,就把32 位整數(shù)-1 的8 位16 進(jìn)制都打印出來(lái)了。
如果你想看si 的本來(lái)面目,那么就應(yīng)該讓編譯器做0 擴(kuò)展而不是符號(hào)擴(kuò)展(擴(kuò)展時(shí)二進(jìn)制左邊補(bǔ)0 而不是補(bǔ)符號(hào)位):
sprintf(s, "%04X", (unsigned short)si);
就可以了?;蛘?#xff1a;
unsigned short si = -1;
sprintf(s, "%04X", si);
sprintf 和printf 還可以按8 進(jìn)制打印整數(shù)字符串,使用”%o”。注意8 進(jìn)制和16 進(jìn)制都不會(huì)打
印出負(fù)數(shù),都是無(wú)符號(hào)的,實(shí)際上也就是變量的內(nèi)部編碼的直接的16 進(jìn)制或8 進(jìn)制表示。
控制浮點(diǎn)數(shù)打印格式
浮點(diǎn)數(shù)的打印和格式控制是sprintf 的又一大常用功能,浮點(diǎn)數(shù)使用格式符”%f”控制,默認(rèn)保
留小數(shù)點(diǎn)后6 位數(shù)字,比如:
sprintf(s, "%f", 3.1415926); //產(chǎn)生"3.141593"
但有時(shí)我們希望自己控制打印的寬度和小數(shù)位數(shù),這時(shí)就應(yīng)該使用:”%m.nf”格式,其中m 表
示打印的寬度,n 表示小數(shù)點(diǎn)后的位數(shù)。比如:
sprintf(s, "%10.3f", 3.1415626); //產(chǎn)生:" 3.142"
sprintf(s, "%-10.3f", 3.1415626); //產(chǎn)生:"3.142 "
sprintf(s, "%.3f", 3.1415626); //不指定總寬度,產(chǎn)生:"3.142"
注意一個(gè)問(wèn)題,你猜
int i = 100;
sprintf(s, "%.2f", i);
會(huì)打出什么東東來(lái)?“100.00”?對(duì)嗎?自己試試就知道了,同時(shí)也試試下面這個(gè):
sprintf(s, "%.2f", (double)i);
第一個(gè)打出來(lái)的肯定不是正確結(jié)果,原因跟前面提到的一樣,參數(shù)壓棧時(shí)調(diào)用者并不知道跟i相對(duì)應(yīng)的格式控制符是個(gè)”%f”。而函數(shù)執(zhí)行時(shí)函數(shù)本身則并不知道當(dāng)年被壓入棧里的是個(gè)整數(shù),于是可憐的保存整數(shù)i 的那4 個(gè)字節(jié)就被不由分說(shuō)地強(qiáng)行作為浮點(diǎn)數(shù)格式來(lái)解釋了,整個(gè)亂套了。不過(guò),如果有人有興趣使用手工編碼一個(gè)浮點(diǎn)數(shù),那么倒可以使用這種方法來(lái)檢驗(yàn)一下你手工編排的結(jié)果是否正確。
資料三
int sprintf( char *buffer, const char *format [, argument] ... );
除了前兩個(gè)參數(shù)類型固定外,后面可以接任意多個(gè)參數(shù)。而它的精華,顯然就在第二個(gè)參數(shù):格式化字符串上。 printf和sprintf都使用格式化字符串來(lái)指定串的格式,在格式串內(nèi)部使用一些以“%”開(kāi)頭的格式說(shuō)明符(format specifications)來(lái)占據(jù)一個(gè)位置,在后邊的變參列表中提供相應(yīng)的變量,最終函數(shù)就會(huì)用相應(yīng)位置的變量來(lái)替代那個(gè)說(shuō)明符,產(chǎn)生一個(gè)調(diào)用者想要 的字符串。 1. 格式化數(shù)字字符串 sprintf最常見(jiàn)的應(yīng)用之一莫過(guò)于把整數(shù)打印到字符串中,所以,spritnf在大多數(shù)場(chǎng)合可以替代itoa。如:
//把整數(shù)123打印成一個(gè)字符串保存在s中。
sprintf(s, "%d", 123); //產(chǎn)生"123" 可以指定寬度,不足的左邊補(bǔ)空格:
sprintf(s, "%8d%8d", 123, 4567); //產(chǎn)生:" 123 4567" 當(dāng)然也可以左對(duì)齊:
sprintf(s, "%-8d%8d", 123, 4567); //產(chǎn)生:"123 4567" 也可以按照16進(jìn)制打印:
sprintf(s, "%8x", 4567); //小寫(xiě)16進(jìn)制,寬度占8個(gè)位置,右對(duì)齊
sprintf(s, "%-8X", 4568); //大寫(xiě)16進(jìn)制,寬度占8個(gè)位置,左對(duì)齊 這樣,一個(gè)整數(shù)的16進(jìn)制字符串就很容易得到,但我們?cè)诖蛴?6進(jìn)制內(nèi)容時(shí),通常想要一種左邊補(bǔ)0的等寬格式,那該怎么做呢?很簡(jiǎn)單,在表示寬度的數(shù)字前面加個(gè)0就可以了。
sprintf(s, "%08X", 4567); //產(chǎn)生:"000011D7" 上面以”%d”進(jìn)行的10進(jìn)制打印同樣也可以使用這種左邊補(bǔ)0的方式。 這里要注意一個(gè)符號(hào)擴(kuò)展的問(wèn)題:比如,假如我們想打印短整數(shù)(short)-1的內(nèi)存16進(jìn)制表示形式,在Win32平臺(tái)上,一個(gè)short型占2個(gè)字節(jié),所以我們自然希望用4個(gè)16進(jìn)制數(shù)字來(lái)打印它:
short si = -1;
sprintf(s, "%04X", si); 產(chǎn)生“FFFFFFFF”,怎么回事?因?yàn)閟pritnf是個(gè)變參函數(shù),除了前面兩個(gè)參數(shù)之外,后面的參數(shù)都不是類型安全的,函數(shù)更沒(méi)有辦法僅僅通過(guò)一個(gè) “%X”就能得知當(dāng)初函數(shù)調(diào)用前參數(shù)壓棧時(shí)被壓進(jìn)來(lái)的到底是個(gè)4字節(jié)的整數(shù)還是個(gè)2字節(jié)的短整數(shù),所以采取了統(tǒng)一4字節(jié)的處理方式,導(dǎo)致參數(shù)壓棧時(shí)做了符 號(hào)擴(kuò)展,擴(kuò)展成了32位的整數(shù)-1,打印時(shí)4個(gè)位置不夠了,就把32位整數(shù)-1的8位16進(jìn)制都打印出來(lái)了。如果你想看si的本來(lái)面目,那么就應(yīng)該讓編譯 器做0擴(kuò)展而不是符號(hào)擴(kuò)展(擴(kuò)展時(shí)二進(jìn)制左邊補(bǔ)0而不是補(bǔ)符號(hào)位):
sprintf(s, "%04X", (unsigned short)si); 就可以了?;蛘?#xff1a;
unsigned short si = -1;
sprintf(s, "%04X", si); sprintf和printf還可以按8進(jìn)制打印整數(shù)字符串,使用”%o”。注意8進(jìn)制和16進(jìn)制都不會(huì)打印出負(fù)數(shù),都是無(wú)符號(hào)的,實(shí)際上也就是變量的內(nèi)部編碼的直接的16進(jìn)制或8進(jìn)制表示。 2. 控制浮點(diǎn)數(shù)打印格式 浮點(diǎn)數(shù)的打印和格式控制是sprintf的又一大常用功能,浮點(diǎn)數(shù)使用格式符”%f”控制,默認(rèn)保留小數(shù)點(diǎn)后6位數(shù)字,比如:
sprintf(s, "%f", 3.1415926); //產(chǎn)生"3.141593" 但有時(shí)我們希望自己控制打印的寬度和小數(shù)位數(shù),這時(shí)就應(yīng)該使用:”%m.nf”格式,其中m表示打印的寬度,n表示小數(shù)點(diǎn)后的位數(shù)。比如:
sprintf(s, "%10.3f", 3.1415626); //產(chǎn)生:" 3.142"
sprintf(s, "%-10.3f", 3.1415626); //產(chǎn)生:"3.142 "
sprintf(s, "%.3f", 3.1415626); //不指定總寬度,產(chǎn)生:"3.142" 注意一個(gè)問(wèn)題,你猜
int i = 100;
sprintf(s, "%.2f", i); 會(huì)打出什么東東來(lái)?“100.00”?對(duì)嗎?自己試試就知道了,同時(shí)也試試下面這個(gè):
sprintf(s, "%.2f", (double)i); 第一個(gè)打出來(lái)的肯定不是正確結(jié)果,原因跟前面提到的一樣,參數(shù)壓棧時(shí)調(diào)用者并不知道跟i相對(duì)應(yīng)的格式控制符是個(gè)”%f”。而函數(shù)執(zhí)行時(shí)函數(shù)本身則并不知道 當(dāng)年被壓入棧里的是個(gè)整數(shù),于是可憐的保存整數(shù)i的那4個(gè)字節(jié)就被不由分說(shuō)地強(qiáng)行作為浮點(diǎn)數(shù)格式來(lái)解釋了,整個(gè)亂套了。 不過(guò),如果有人有興趣使用手工編碼一個(gè)浮點(diǎn)數(shù),那么倒可以使用這種方法來(lái)檢驗(yàn)一下你手工編排的結(jié)果是否正確。J 字符/Ascii碼對(duì)照 我們知道,在C/C++語(yǔ)言中,char也是一種普通的scalable類型,除了字長(zhǎng)之外,它與short,int,long這些類型沒(méi)有本質(zhì)區(qū)別,只 不過(guò)被大家習(xí)慣用來(lái)表示字符和字符串而已。(或許當(dāng)年該把這個(gè)類型叫做“byte”,然后現(xiàn)在就可以根據(jù)實(shí)際情況,使用byte或short來(lái)把char 通過(guò)typedef定義出來(lái),這樣更合適些) 于是,使用”%d”或者”%x”打印一個(gè)字符,便能得出它的10進(jìn)制或16進(jìn)制的ASCII碼;反過(guò)來(lái),使用”%c”打印一個(gè)整數(shù),便可以看到它所對(duì)應(yīng)的 ASCII字符。
int snprintf(char *restrict buf, size_t n, const char * restrict??format, ...);
函數(shù)說(shuō)明:最多從源串中拷貝n-1個(gè)字符到目標(biāo)串中,然后再在后面加一個(gè)0。所以如果目標(biāo)串的大小為n 的話,將不會(huì)溢出。
函數(shù)返回值:若成功則返回欲寫(xiě)入的字符串長(zhǎng)度,若出錯(cuò)則返回負(fù)值。
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;
}
root] /root/lindatest
$ ./test?
str=012345678
Result2:(不推薦使用)
#include <stdio.h>
#include <stdlib.h>
int main()
{
??? char str[10]={0, };
??? snprintf(str, 18, "0123456789012345678");
??? printf("str=%s/n", str);
??? return 0;
}
root] /root/lindatest
$ ./test
str=01234567890123456
snprintf函數(shù)返回值的測(cè)試:
#include <stdio.h>
#include <stdlib.h>
int main()
{
??? char str1[10] ={0, };
??? char str2[10] ={0, };
??? int ret1=0,ret2=0;
??? ret1=snprintf(str1, sizeof(str1), "%s", "abc");
??? ret2=snprintf(str2, 4, "%s", "aaabbbccc");
??? printf("aaabbbccc length=%d/n", strlen("aaabbbccc"));
??? printf("str1=%s,ret1=%d/n", str1, ret1);
??? printf("str2=%s,ret2=%d/n", str2, ret2);
??? return 0;
}
[root] /root/lindatest
$ ./test?
aaabbbccc length=9
str1=abc,ret1=3
str2=aaa,ret2=9
解釋SIZE:
?#include <stdio.h>
#include <stdlib.h>
int main()
{
char dst1[10] ={0, },dst2[10] ={0, };
char src1[10] ="aaa",src2[15] ="aaabbbcccddd";
int size=sizeof(dst1);
int ret1=0, ret2=0;
ret1=snprintf(dst1, size, "str :%s", src1);
ret2=snprintf(dst2, size, "str :%s", src2);
printf("sizeof(dst1)=%d, src1=%s, /"str :%%s/"=%s%s, dst1=%s, ret1=%d/n", sizeof(dst1), src1, "str :", src1, dst1, ret1);
printf("sizeof(dst2)=%d, src2=%s, /"str :%%s/"=%s%s, dst2=%s, ret2=%d/n", sizeof(dst2), src2, "str :", src2, dst2, ret2);
return 0;
}
root] /root/lindatest
$ ./test?
sizeof(dst1)=10, src1=aaa, "str :%s"=str :aaa, dst1=str :aaa, ret1=8
sizeof(dst2)=10, src2=aaabbbcccddd, "str :%s"=str :aaabbbcccddd, dst2=str :aaab, ret2=17
補(bǔ)充一下,snprintf的返回值是欲寫(xiě)入的字符串長(zhǎng)度,而不是實(shí)際寫(xiě)入的字符串度。如:
char test[8];
int ret = snprintf(test,5,"1234567890");
printf("%d|%s/n",ret,test);
運(yùn)行結(jié)果為:
10|1234
數(shù)原型:
int snprintf(char *str, size_t size, const char *format, ...);
資料四
在將各種類型的數(shù)據(jù)構(gòu)造成字符串時(shí),sprintf 的強(qiáng)大功能很少會(huì)讓你失望。由于sprintf 跟printf 在用法上幾乎一樣,只是打印的目的地不同而已,前者打印到字符串中,后者則直接在命令行上輸出。這也導(dǎo)致sprintf 比printf 有用得多。
sprintf 是個(gè)變參函數(shù),定義如下:
int sprintf( char *buffer, const char *format [, argument] ... );
除了前兩個(gè)參數(shù)類型固定外,后面可以接任意多個(gè)參數(shù)。而它的精華,顯然就在第二個(gè)參數(shù):
(1)格式化字符串上。
printf 和sprintf 都使用格式化字符串來(lái)指定串的格式,在格式串內(nèi)部使用一些以“%”開(kāi)頭的格式說(shuō)明符(format specifications)來(lái)占據(jù)一個(gè)位置,在后邊的變參列表中提供相應(yīng)的變量,最終函數(shù)就會(huì)用相應(yīng)位置的變量來(lái)替代那個(gè)說(shuō)明符,產(chǎn)生一個(gè)調(diào)用者想要的字符串。
格式化數(shù)字字符串
sprintf 最常見(jiàn)的應(yīng)用之一莫過(guò)于把整數(shù)打印到字符串中,所以,spritnf 在大多數(shù)場(chǎng)合可以替代itoa。
如:
//把整數(shù)123 打印成一個(gè)字符串保存在s 中。
sprintf(s, "%d", 123); //產(chǎn)生"123"
可以指定寬度,不足的左邊補(bǔ)空格:
sprintf(s, "%8d%8d", 123, 4567); //產(chǎn)生:" 123 4567"
當(dāng)然也可以左對(duì)齊:
sprintf(s, "%-8d%8d", 123, 4567); //產(chǎn)生:"123 4567"
也可以按照16 進(jìn)制打印:
sprintf(s, "%8x", 4567); //小寫(xiě)16 進(jìn)制,寬度占8 個(gè)位置,右對(duì)齊
sprintf(s, "%-8X", 4568); //大寫(xiě)16 進(jìn)制,寬度占8 個(gè)位置,左對(duì)齊
這樣,一個(gè)整數(shù)的16 進(jìn)制字符串就很容易得到,但我們?cè)诖蛴?6 進(jìn)制內(nèi)容時(shí),通常想要一種左邊補(bǔ)0 的等寬格式,那該怎么做呢?很簡(jiǎn)單,在表示寬度的數(shù)字前面加個(gè)0 就可以了。
sprintf(s, "%08X", 4567); //產(chǎn)生:"000011D7"
上面以”%d”進(jìn)行的10 進(jìn)制打印同樣也可以使用這種左邊補(bǔ)0 的方式。
這里要注意一個(gè)符號(hào)擴(kuò)展的問(wèn)題:比如,假如我們想打印短整數(shù)(short)-1 的內(nèi)存16 進(jìn)制表示形式,在Win32 平臺(tái)上,一個(gè)short 型占2 個(gè)字節(jié),所以我們自然希望用4 個(gè)16 進(jìn)制數(shù)字來(lái)打印它:
short si = -1;
sprintf(s, "%04X", si);
產(chǎn)生“FFFFFFFF”,怎么回事?因?yàn)閟pritnf 是個(gè)變參函數(shù),除了前面兩個(gè)參數(shù)之外,后面的參數(shù)都不是類型安全的,函數(shù)更沒(méi)有辦法僅僅通過(guò)一個(gè)“%X”就能得知當(dāng)初函數(shù)調(diào)用前參數(shù)壓棧時(shí)被壓進(jìn)來(lái)的到底是個(gè)4 字節(jié)的整數(shù)還是個(gè)2 字節(jié)的短整數(shù),所以采取了統(tǒng)一4 字節(jié)的處理方式,導(dǎo)致參數(shù)壓棧時(shí)做了符號(hào)擴(kuò)展,擴(kuò)展成了32 位的整數(shù)-1,打印時(shí)4 個(gè)位置不夠了,就把32 位整數(shù)-1 的8 位16 進(jìn)制都打印出來(lái)了。
如果你想看si 的本來(lái)面目,那么就應(yīng)該讓編譯器做0 擴(kuò)展而不是符號(hào)擴(kuò)展(擴(kuò)展時(shí)二進(jìn)制左邊補(bǔ)0 而不是補(bǔ)符號(hào)位):
sprintf(s, "%04X", (unsigned short)si);
就可以了?;蛘?#xff1a;
unsigned short si = -1;
sprintf(s, "%04X", si);
sprintf 和printf 還可以按8 進(jìn)制打印整數(shù)字符串,使用”%o”。注意8 進(jìn)制和16 進(jìn)制都不會(huì)打
印出負(fù)數(shù),都是無(wú)符號(hào)的,實(shí)際上也就是變量的內(nèi)部編碼的直接的16 進(jìn)制或8 進(jìn)制表示。
控制浮點(diǎn)數(shù)打印格式
浮點(diǎn)數(shù)的打印和格式控制是sprintf 的又一大常用功能,浮點(diǎn)數(shù)使用格式符”%f”控制,默認(rèn)保
留小數(shù)點(diǎn)后6 位數(shù)字,比如:
sprintf(s, "%f", 3.1415926); //產(chǎn)生"3.141593"
但有時(shí)我們希望自己控制打印的寬度和小數(shù)位數(shù),這時(shí)就應(yīng)該使用:”%m.nf”格式,其中m 表
示打印的寬度,n 表示小數(shù)點(diǎn)后的位數(shù)。比如:
sprintf(s, "%10.3f", 3.1415626); //產(chǎn)生:" 3.142"
sprintf(s, "%-10.3f", 3.1415626); //產(chǎn)生:"3.142 "
sprintf(s, "%.3f", 3.1415626); //不指定總寬度,產(chǎn)生:"3.142"
注意一個(gè)問(wèn)題,你猜
int i = 100;
sprintf(s, "%.2f", i);
會(huì)打出什么東東來(lái)?“100.00”?對(duì)嗎?自己試試就知道了,同時(shí)也試試下面這個(gè):
sprintf(s, "%.2f", (double)i);
第一個(gè)打出來(lái)的肯定不是正確結(jié)果,原因跟前面提到的一樣,參數(shù)壓棧時(shí)調(diào)用者并不知道跟i相對(duì)應(yīng)的格式控制符是個(gè)”%f”。而函數(shù)執(zhí)行時(shí)函數(shù)本身則并不知道當(dāng)年被壓入棧里的是個(gè)整數(shù),于是可憐的保存整數(shù)i 的那4 個(gè)字節(jié)就被不由分說(shuō)地強(qiáng)行作為浮點(diǎn)數(shù)格式來(lái)解釋了,整個(gè)亂套了。不過(guò),如果有人有興趣使用手工編碼一個(gè)浮點(diǎn)數(shù),那么倒可以使用這種方法來(lái)檢驗(yàn)一下你手工編排的結(jié)果是否正確。
資料五
將字串格式化命令。sprintf 是個(gè)變參函數(shù),使用時(shí)經(jīng)常出問(wèn)題,而且只要出問(wèn)題通常就是能導(dǎo)致程序崩潰的內(nèi)存訪 問(wèn)錯(cuò)誤,但好在由sprintf 誤用導(dǎo)致的問(wèn)題雖然嚴(yán)重,卻很容易找出,無(wú)非就是那么幾種情況,通 常用眼睛再把出錯(cuò)的代碼多看幾眼就看出來(lái)了。
sprintf 將字串格式化。
在頭文件 #include<stdio.h
>中
語(yǔ)法: int sprintf(string format, mixed [args]...);
返回值:字符串長(zhǎng)度(strlen)
sprintf格式的規(guī)格如下所示。[]中的部分是可選的。
%[指定參數(shù)$][標(biāo)識(shí)符][寬度][.精度]指示符
若想輸出`%'本身時(shí), 請(qǐng)這樣`%%'處理。
1. 處理字符方向。負(fù)號(hào)時(shí)表示從后向前處理。
2. 填空字元。 0 的話表示空格填 0;空格是內(nèi)定值,表示空格就放著。
3. 字符總寬度。為最小寬度。
4. 精確度。指在小數(shù)點(diǎn)后的浮點(diǎn)數(shù)位數(shù)。
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
轉(zhuǎn)換字符
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
%% 印出百分比符號(hào),不轉(zhuǎn)換。
%c 整數(shù)轉(zhuǎn)成對(duì)應(yīng)的 ASCII 字元。
%d 整數(shù)轉(zhuǎn)成十進(jìn)位。
%f 倍精確度數(shù)字轉(zhuǎn)成浮點(diǎn)數(shù)。
%o 整數(shù)轉(zhuǎn)成八進(jìn)位。
%s 整數(shù)轉(zhuǎn)成字串。
%x 整數(shù)轉(zhuǎn)成小寫(xiě)十六進(jìn)位。
%X 整數(shù)轉(zhuǎn)成大寫(xiě)十六進(jìn)位。
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
<?
$money = 123.1
$formatted = sprintf ("%06.2f", $money); // 此時(shí)變數(shù) $ formatted 值為 "123.10"
$formatted = sprintf ("%08.2f", $money); // 此時(shí)變數(shù) $ formatted 值為 "00123.10"
$formatted = sprintf ("%-08.2f", $money); // 此時(shí)變數(shù) $ formatted 值為 "123.1000"
$formatted = sprintf ("%.2f%%", 0.95 * 100); // 格式化為百分比
?>
¢%08.2f 解釋:
%開(kāi)始符
0是 "填空字元" 表示,如果長(zhǎng)度不足時(shí)就用0來(lái)填滿。
8格式化后總長(zhǎng)度
2f小數(shù)位長(zhǎng)度,即2位
¢第3行值為"00123.10" 解釋:
因?yàn)?f是(2位)+小數(shù)點(diǎn)符號(hào)(1)+前面123(3位)=6位,總長(zhǎng)度為8位,故前面用[填空字元]0表示,即00123.10
¢第4行值為"123.1000" 解釋:
-號(hào)為反向操作,然后填空字元0添加在最后面了
/********************************************************
以下選自《CSDN 社區(qū)電子雜志——C/C++雜志》
*********************************************************/
在將各種類型的數(shù)據(jù)構(gòu)造成字符串時(shí),sprintf 的強(qiáng)大功能很少會(huì)讓你失望。由于sprintf 跟printf 在用法上幾乎一樣,只是打印的目的地不同而已,前者打印到字符串中,后者則直接在命令行上輸出。這也導(dǎo)致sprintf 比printf 有用得多。
sprintf 是個(gè)變參函數(shù),定義如下:
int sprintf( char *buffer, const char *format [, argument] ... );
除了前兩個(gè)參數(shù)類型固定外,后面可以接任意多個(gè)參數(shù)。而它的精華,顯然就在第二個(gè)參數(shù):
格式化字符串上。
printf 和sprintf 都使用格式化字符串來(lái)指定串的格式,在格式串內(nèi)部使用一些以“%”開(kāi)頭的格式說(shuō)明符(format specifications)來(lái)占據(jù)一個(gè)位置,在后邊的變參列表中提供相應(yīng)的變量,最終函數(shù)就會(huì)用相應(yīng)位置的變量來(lái)替代那個(gè)說(shuō)明符,產(chǎn)生一個(gè)調(diào)用者想要的字符串。
格式化數(shù)字字符串
sprintf 最常見(jiàn)的應(yīng)用之一莫過(guò)于把整數(shù)打印到字符串中,所以,spritnf 在大多數(shù)場(chǎng)合可以替代
itoa。
如:
//把整數(shù)123 打印成一個(gè)字符串保存在s 中。
sprintf(s, "%d", 123); //產(chǎn)生"123"
可以指定寬度,不足的左邊補(bǔ)空格:
sprintf(s, "%8d%8d", 123, 4567); //產(chǎn)生:" 123 4567"
當(dāng)然也可以左對(duì)齊:
sprintf(s, "%-8d%8d", 123, 4567); //產(chǎn)生:"123 4567"
也可以按照16 進(jìn)制打印:
sprintf(s, "%8x", 4567); //小寫(xiě)16 進(jìn)制,寬度占8 個(gè)位置,右對(duì)齊
sprintf(s, "%-8X", 4568); //大寫(xiě)16 進(jìn)制,寬度占8 個(gè)位置,左對(duì)齊
這樣,一個(gè)整數(shù)的16 進(jìn)制字符串就很容易得到,但我們?cè)诖蛴?6 進(jìn)制內(nèi)容時(shí),通常想要一種左邊補(bǔ)0 的等寬格式,那該怎么做呢?很簡(jiǎn)單,在表示寬度的數(shù)字前面加個(gè)0 就可以了。
sprintf(s, "%08X", 4567); //產(chǎn)生:"000011D7"
上面以”%d”進(jìn)行的10 進(jìn)制打印同樣也可以使用這種左邊補(bǔ)0 的方式。
這里要注意一個(gè)符號(hào)擴(kuò)展的問(wèn)題:比如,假如我們想打印短整數(shù)(short)-1 的內(nèi)存16 進(jìn)制表示形式,在Win32 平臺(tái)上,一個(gè)short 型占2 個(gè)字節(jié),所以我們自然希望用4 個(gè)16 進(jìn)制數(shù)字來(lái)打印它:
short si = -1;
sprintf(s, "%04X", si);
產(chǎn)生“FFFFFFFF”,怎么回事?因?yàn)閟pritnf 是個(gè)變參函數(shù),除了前面兩個(gè)參數(shù)之外,后面的參數(shù)都不是類型安全的,函數(shù)更沒(méi)有辦法僅僅通過(guò)一個(gè)“%X”就能得知當(dāng)初函數(shù)調(diào)用前參數(shù)壓棧時(shí)被壓進(jìn)來(lái)的到底是個(gè)4 字節(jié)的整數(shù)還是個(gè)2 字節(jié)的短整數(shù),所以采取了統(tǒng)一4 字節(jié)的處理方式,導(dǎo)致參數(shù)壓棧時(shí)做了符號(hào)擴(kuò)展,擴(kuò)展成了32 位的整數(shù)-1,打印時(shí)4 個(gè)位置不夠了,就把32 位整數(shù)-1 的8 位16 進(jìn)制都打印出來(lái)了。
如果你想看si 的本來(lái)面目,那么就應(yīng)該讓編譯器做0 擴(kuò)展而不是符號(hào)擴(kuò)展(擴(kuò)展時(shí)二進(jìn)制左邊補(bǔ)0 而不是補(bǔ)符號(hào)位):
sprintf(s, "%04X", (unsigned short)si);
就可以了。或者:
unsigned short si = -1;
sprintf(s, "%04X", si);
sprintf 和printf 還可以按8 進(jìn)制打印整數(shù)字符串,使用”%o”。注意8 進(jìn)制和16 進(jìn)制都不會(huì)打
印出負(fù)數(shù),都是無(wú)符號(hào)的,實(shí)際上也就是變量的內(nèi)部編碼的直接的16 進(jìn)制或8 進(jìn)制表示。
控制浮點(diǎn)數(shù)打印格式
浮點(diǎn)數(shù)的打印和格式控制是sprintf 的又一大常用功能,浮點(diǎn)數(shù)使用格式符”%f”控制,默認(rèn)保
留小數(shù)點(diǎn)后6 位數(shù)字,比如:
sprintf(s, "%f", 3.1415926); //產(chǎn)生"3.141593"
但有時(shí)我們希望自己控制打印的寬度和小數(shù)位數(shù),這時(shí)就應(yīng)該使用:”%m /nf”格式,其中m 表
示打印的寬度,n 表示小數(shù)點(diǎn)后的位數(shù)。比如:
sprintf(s, "%10.3f", 3.1415626); //產(chǎn)生:" 3.142"
sprintf(s, "%-10.3f", 3.1415626); //產(chǎn)生:"3.142 "
sprintf(s, "%.3f", 3.1415626); //不指定總寬度,產(chǎn)生:"3.142"
注意一個(gè)問(wèn)題,你猜
int i = 100;
sprintf(s, "%.2f", i);
會(huì)打出什么東東來(lái)?“100.00”?對(duì)嗎?自己試試就知道了,同時(shí)也試試下面這個(gè):
sprintf(s, "%.2f", (double)i);
第一個(gè)打出來(lái)的肯定不是正確結(jié)果,原因跟前面提到的一樣,參數(shù)壓棧時(shí)調(diào)用者并不知道跟i相對(duì)應(yīng)的格式控制符是個(gè)”%f”。而函數(shù)執(zhí)行時(shí)函數(shù)本身則并不知道當(dāng)年被壓入棧里的是個(gè)整數(shù),于是可憐的保存整數(shù)i 的那4 個(gè)字節(jié)就被不由分說(shuō)地強(qiáng)行作為浮點(diǎn)數(shù)格式來(lái)解釋了,整個(gè)亂套了。不過(guò),如果有人有興趣使用手工編碼一個(gè)浮點(diǎn)數(shù),那么倒可以使用這種方法來(lái)檢驗(yàn)一下你手工編排的結(jié)果是否正確。
字符/Ascii 碼對(duì)照
我們知道,在C/C++語(yǔ)言中,char 也是一種普通的scalable 類型,除了字長(zhǎng)之外,它與short,
int,long 這些類型沒(méi)有本質(zhì)區(qū)別,只不過(guò)被大家習(xí)慣用來(lái)表示字符和字符串而已。(或許當(dāng)年該把
這個(gè)類型叫做“byte”,然后現(xiàn)在就可以根據(jù)實(shí)際情況,使用byte 或short 來(lái)把char 通過(guò)typedef 定義出來(lái),這樣更合適些)于是,使用”%d”或者”%x”打印一個(gè)字符,便能得出它的10 進(jìn)制或16 進(jìn)制的ASCII 碼;反過(guò)來(lái),使用”%c”打印一個(gè)整數(shù),便可以看到它所對(duì)應(yīng)的ASCII 字符。以下程序段把所有可見(jiàn)字符的ASCII 碼對(duì)照表打印到屏幕上(這里采用printf,注意”#”與”%X”合用時(shí)自動(dòng)為16 進(jìn)制數(shù)增加”0X”前綴):
for(int i = 32; i < 127; i++) {
printf("[ %c ]: %3d 0x%#04X/n", i, i, i);
}
連接字符串
sprintf 的格式控制串中既然可以插入各種東西,并最終把它們“連成一串”,自然也就能夠連
接字符串,從而在許多場(chǎng)合可以替代strcat,但sprintf 能夠一次連接多個(gè)字符串(自然也可以同時(shí)
在它們中間插入別的內(nèi)容,總之非常靈活)。比如:
char* who = "I";
char* whom = "CSDN";
sprintf(s, "%s love %s.", who, whom); //產(chǎn)生:"I love CSDN. "
strcat 只能連接字符串(一段以’’結(jié)尾的字符數(shù)組或叫做字符緩沖,null-terminated-string),但有時(shí)我們有兩段字符緩沖區(qū),他們并不是以 ’’結(jié)尾。比如許多從第三方庫(kù)函數(shù)中返回的字符數(shù)組,從硬件或者網(wǎng)絡(luò)傳輸中讀進(jìn)來(lái)的字符流,它們未必每一段字符序列后面都有個(gè)相應(yīng)的’’來(lái)結(jié)尾。如果直接連接,不管是sprintf 還是strcat 肯定會(huì)導(dǎo)致非法內(nèi)存操作,而strncat 也至少要求第一個(gè)參數(shù)是個(gè)null-terminated-string,那該怎么辦呢?我們自然會(huì)想起前面介紹打印整數(shù)和浮點(diǎn)數(shù)時(shí)可以指定寬度,字符串也一樣的。比如:
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!
十有八九要出問(wèn)題了。是否可以改成:
sprintf(s, "%7s%7s", a1, a2);
也沒(méi)好到哪兒去,正確的應(yīng)該是:
sprintf(s, "%.7s%.7s", a1, a2);//產(chǎn)生:"ABCDEFGHIJKLMN"
這可以類比打印浮點(diǎn)數(shù)的”%m/nf”,在”%m.ns”中,m 表示占用寬度(字符串長(zhǎng)度不足時(shí)補(bǔ)空格,超出了則按照實(shí)際寬度打印),n 才表示從相應(yīng)的字符串中最多取用的字符數(shù)。通常在打印字符串時(shí)m 沒(méi)什么大用,還是點(diǎn)號(hào)后面的n 用的多。自然,也可以前后都只取部分字符:
sprintf(s, "%.6s%.5s", a1, a2);//產(chǎn)生:"ABCDEFHIJKL"
在許多時(shí)候,我們或許還希望這些格式控制符中用以指定長(zhǎng)度信息的數(shù)字是動(dòng)態(tài)的,而不是靜態(tài)指定的,因?yàn)樵S多時(shí)候,程序要到運(yùn)行時(shí)才會(huì)清楚到底需要取字符數(shù)組中的幾個(gè)字符,這種動(dòng)態(tài)的寬度/精度設(shè)置功能在sprintf 的實(shí)現(xiàn)中也被考慮到了,sprintf 采用”*”來(lái)占用一個(gè)本來(lái)需要一個(gè)指定寬度或精度的常數(shù)數(shù)字的位置,同樣,而實(shí)際的寬度或精度就可以和其它被打印的變量一樣被提供出來(lái),于是,上面的例子可以變成:
sprintf(s, "%.*s%.*s", 7, a1, 7, a2);
或者:
sprintf(s, "%.*s%.*s", sizeof(a1), a1, sizeof(a2), a2);
實(shí)際上,前面介紹的打印字符、整數(shù)、浮點(diǎn)數(shù)等都可以動(dòng)態(tài)指定那些常量值,比如:
sprintf(s, "%-*d", 4, 'A'); //產(chǎn)生"65 "
sprintf(s, "%#0*X", 8, 128); //產(chǎn)生"0X000080","#"產(chǎn)生0X
sprintf(s, "%*.*f", 10, 2, 3.1415926); //產(chǎn)生" 3.14"
打印地址信息
有時(shí)調(diào)試程序時(shí),我們可能想查看某些變量或者成員的地址,由于地址或者指針也不過(guò)是個(gè)32 位的數(shù),你完全可以使用打印無(wú)符號(hào)整數(shù)的”%u”把他們打印出來(lái):
sprintf(s, "%u", &i);
不過(guò)通常人們還是喜歡使用16 進(jìn)制而不是10 進(jìn)制來(lái)顯示一個(gè)地址:
sprintf(s, "%08X", &i);
然而,這些都是間接的方法,對(duì)于地址打印,sprintf 提供了專門(mén)的”%p”:
sprintf(s, "%p", &i);
我覺(jué)得它實(shí)際上就相當(dāng)于:
sprintf(s, "%0*x", 2 * sizeof(void *), &i);
利用sprintf 的返回值
較少有人注意printf/sprintf 函數(shù)的返回值,但有時(shí)它卻是有用的,spritnf 返回了本次函數(shù)調(diào)用
最終打印到字符緩沖區(qū)中的字符數(shù)目。也就是說(shuō)每當(dāng)一次sprinf 調(diào)用結(jié)束以后,你無(wú)須再調(diào)用一次
strlen 便已經(jīng)知道了結(jié)果字符串的長(zhǎng)度。如:
int len = sprintf(s, "%d", i);
對(duì)于正整數(shù)來(lái)說(shuō),len 便等于整數(shù)i 的10 進(jìn)制位數(shù)。
下面的是個(gè)完整的例子,產(chǎn)生10 個(gè)[0, 100)之間的隨機(jī)數(shù),并將他們打印到一個(gè)字符數(shù)組s 中,
以逗號(hào)分隔開(kāi)。
#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';//將最后一個(gè)逗號(hào)換成換行符。
printf(s);
return 0;
}
設(shè)想當(dāng)你從數(shù)據(jù)庫(kù)中取出一條記錄,然后希望把他們的各個(gè)字段按照某種規(guī)則連接成一個(gè)字
符串時(shí),就可以使用這種方法,從理論上講,他應(yīng)該比不斷的strcat 效率高,因?yàn)閟trcat 每次調(diào)用
都需要先找到最后的那個(gè)’’的位置,而在上面給出的例子中,我們每次都利用sprintf 返回值把這
個(gè)位置直接記下來(lái)了。
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 的常見(jiàn)問(wèn)題
sprintf 是個(gè)變參函數(shù),使用時(shí)經(jīng)常出問(wèn)題,而且只要出問(wèn)題通常就是能導(dǎo)致程序崩潰的內(nèi)存訪
問(wèn)錯(cuò)誤,但好在由sprintf 誤用導(dǎo)致的問(wèn)題雖然嚴(yán)重,卻很容易找出,無(wú)非就是那么幾種情況,通
常用眼睛再把出錯(cuò)的代碼多看幾眼就看出來(lái)了。
?? 緩沖區(qū)溢出
第一個(gè)參數(shù)的長(zhǎng)度太短了,沒(méi)的說(shuō),給個(gè)大點(diǎn)的地方吧。當(dāng)然也可能是后面的參數(shù)的問(wèn)
題,建議變參對(duì)應(yīng)一定要細(xì)心,而打印字符串時(shí),盡量使用”%.ns”的形式指定最大字符數(shù)。
?? 忘記了第一個(gè)參數(shù)
低級(jí)得不能再低級(jí)問(wèn)題,用printf 用得太慣了。//偶就常犯。:。(
?? 變參對(duì)應(yīng)出問(wèn)題
通常是忘記了提供對(duì)應(yīng)某個(gè)格式符的變參,導(dǎo)致以后的參數(shù)統(tǒng)統(tǒng)錯(cuò)位,檢查檢查吧。尤
其是對(duì)應(yīng)”*”的那些參數(shù),都提供了嗎?不要把一個(gè)整數(shù)對(duì)應(yīng)一個(gè)”%s”,編譯器會(huì)覺(jué)得你
欺她太甚了(編譯器是obj 和exe 的媽媽,應(yīng)該是個(gè)女的,:P)。
strftime
sprnitf 還有個(gè)不錯(cuò)的表妹:strftime,專門(mén)用于格式化時(shí)間字符串的,用法跟她表哥很像,也
是一大堆格式控制符,只是畢竟小姑娘家心細(xì),她還要調(diào)用者指定緩沖區(qū)的最大長(zhǎng)度,可能是為
了在出現(xiàn)問(wèn)題時(shí)可以推卸責(zé)任吧。這里舉個(gè)例子:
time_t t = time(0);
//產(chǎn)生"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,這一對(duì)由于從面向?qū)ο竽睦锏玫搅速澲?#xff0c;用以寫(xiě)出的代碼更覺(jué)優(yōu)雅。
資料六
在將各種類型的數(shù)據(jù)構(gòu)造成字符串時(shí),sprintf 的強(qiáng)大功能很少會(huì)讓你失望。由于sprintf 跟printf 在用法上幾乎一樣,只是打印的目的地不同而已,前者打印到字符串中,后者則直接在命令行上輸出。這也導(dǎo)致sprintf 比printf 有用得多。
sprintf 是個(gè)變參函數(shù),定義如下:
int sprintf( char *buffer, const char *format [, argument] ... );
除了前兩個(gè)參數(shù)類型固定外,后面可以接任意多個(gè)參數(shù)。而它的精華,顯然就在第二個(gè)參數(shù):
(1)格式化字符串上。
printf 和sprintf 都使用格式化字符串來(lái)指定串的格式,在格式串內(nèi)部使用一些以“%”開(kāi)頭的格式說(shuō)明符(format specifications)來(lái)占據(jù)一個(gè)位置,在后邊的變參列表中提供相應(yīng)的變量,最終函數(shù)就會(huì)用相應(yīng)位置的變量來(lái)替代那個(gè)說(shuō)明符,產(chǎn)生一個(gè)調(diào)用者想要的字符串。
格式化數(shù)字字符串
sprintf 最常見(jiàn)的應(yīng)用之一莫過(guò)于把整數(shù)打印到字符串中,所以,spritnf 在大多數(shù)場(chǎng)合可以替代itoa。
如:
//把整數(shù)123 打印成一個(gè)字符串保存在s 中。
sprintf(s, "%d", 123); //產(chǎn)生"123"
可以指定寬度,不足的左邊補(bǔ)空格:
sprintf(s, "%8d%8d", 123, 4567); //產(chǎn)生:" 123 4567"
當(dāng)然也可以左對(duì)齊:
sprintf(s, "%-8d%8d", 123, 4567); //產(chǎn)生:"123 4567"
也可以按照16 進(jìn)制打印:
sprintf(s, "%8x", 4567); //小寫(xiě)16 進(jìn)制,寬度占8 個(gè)位置,右對(duì)齊
sprintf(s, "%-8X", 4568); //大寫(xiě)16 進(jìn)制,寬度占8 個(gè)位置,左對(duì)齊
這樣,一個(gè)整數(shù)的16 進(jìn)制字符串就很容易得到,但我們?cè)诖蛴?6 進(jìn)制內(nèi)容時(shí),通常想要一種左邊補(bǔ)0 的等寬格式,那該怎么做呢?很簡(jiǎn)單,在表示寬度的數(shù)字前面加個(gè)0 就可以了。
sprintf(s, "%08X", 4567); //產(chǎn)生:"000011D7"
上面以”%d”進(jìn)行的10 進(jìn)制打印同樣也可以使用這種左邊補(bǔ)0 的方式。
這里要注意一個(gè)符號(hào)擴(kuò)展的問(wèn)題:比如,假如我們想打印短整數(shù)(short)-1 的內(nèi)存16 進(jìn)制表示形式,在Win32 平臺(tái)上,一個(gè)short 型占2 個(gè)字節(jié),所以我們自然希望用4 個(gè)16 進(jìn)制數(shù)字來(lái)打印它:
short si = -1;
sprintf(s, "%04X", si);
產(chǎn)生“FFFFFFFF”,怎么回事?因?yàn)閟pritnf 是個(gè)變參函數(shù),除了前面兩個(gè)參數(shù)之外,后面的參數(shù)都不是類型安全的,函數(shù)更沒(méi)有辦法僅僅通過(guò)一個(gè)“%X”就能得知當(dāng)初函數(shù)調(diào)用前參數(shù)壓棧時(shí)被壓進(jìn)來(lái)的到底是個(gè)4 字節(jié)的整數(shù)還是個(gè)2 字節(jié)的短整數(shù),所以采取了統(tǒng)一4 字節(jié)的處理方式,導(dǎo)致參數(shù)壓棧時(shí)做了符號(hào)擴(kuò)展,擴(kuò)展成了32 位的整數(shù)-1,打印時(shí)4 個(gè)位置不夠了,就把32 位整數(shù)-1 的8 位16 進(jìn)制都打印出來(lái)了。
如果你想看si 的本來(lái)面目,那么就應(yīng)該讓編譯器做0 擴(kuò)展而不是符號(hào)擴(kuò)展(擴(kuò)展時(shí)二進(jìn)制左邊補(bǔ)0 而不是補(bǔ)符號(hào)位):
sprintf(s, "%04X", (unsigned short)si);
就可以了?;蛘?#xff1a;
unsigned short si = -1;
sprintf(s, "%04X", si);
sprintf 和printf 還可以按8 進(jìn)制打印整數(shù)字符串,使用”%o”。注意8 進(jìn)制和16 進(jìn)制都不會(huì)打
印出負(fù)數(shù),都是無(wú)符號(hào)的,實(shí)際上也就是變量的內(nèi)部編碼的直接的16 進(jìn)制或8 進(jìn)制表示。
控制浮點(diǎn)數(shù)打印格式
浮點(diǎn)數(shù)的打印和格式控制是sprintf 的又一大常用功能,浮點(diǎn)數(shù)使用格式符”%f”控制,默認(rèn)保
留小數(shù)點(diǎn)后6 位數(shù)字,比如:
sprintf(s, "%f", 3.1415926); //產(chǎn)生"3.141593"
但有時(shí)我們希望自己控制打印的寬度和小數(shù)位數(shù),這時(shí)就應(yīng)該使用:”%m.nf”格式,其中m 表
示打印的寬度,n 表示小數(shù)點(diǎn)后的位數(shù)。比如:
sprintf(s, "%10.3f", 3.1415626); //產(chǎn)生:" 3.142"
sprintf(s, "%-10.3f", 3.1415626); //產(chǎn)生:"3.142 "
sprintf(s, "%.3f", 3.1415626); //不指定總寬度,產(chǎn)生:"3.142"
注意一個(gè)問(wèn)題,你猜
int i = 100;
sprintf(s, "%.2f", i);
會(huì)打出什么東東來(lái)?“100.00”?對(duì)嗎?自己試試就知道了,同時(shí)也試試下面這個(gè):
sprintf(s, "%.2f", (double)i);
第一個(gè)打出來(lái)的肯定不是正確結(jié)果,原因跟前面提到的一樣,參數(shù)壓棧時(shí)調(diào)用者并不知道跟i相對(duì)應(yīng)的格式控制符是個(gè)”%f”。而函數(shù)執(zhí)行時(shí)函數(shù)本身則并不知道當(dāng)年被壓入棧里的是個(gè)整數(shù),于是可憐的保存整數(shù)i 的那4 個(gè)字節(jié)就被不由分說(shuō)地強(qiáng)行作為浮點(diǎn)數(shù)格式來(lái)解釋了,整個(gè)亂套了。不過(guò),如果有人有興趣使用手工編碼一個(gè)浮點(diǎn)數(shù),那么倒可以使用這種方法來(lái)檢驗(yàn)一下你手工編排的結(jié)果是否正確。
??? (2)字符/Ascii 碼對(duì)照
我們知道,在C/C++語(yǔ)言中,char 也是一種普通的scalable 類型,除了字長(zhǎng)之外,它與short,
int,long 這些類型沒(méi)有本質(zhì)區(qū)別,只不過(guò)被大家習(xí)慣用來(lái)表示字符和字符串而已。(或許當(dāng)年該把
這個(gè)類型叫做“byte”,然后現(xiàn)在就可以根據(jù)實(shí)際情況,使用byte 或short 來(lái)把char 通過(guò)typedef 定義出來(lái),這樣更合適些)于是,使用”%d”或者”%x”打印一個(gè)字符,便能得出它的10 進(jìn)制或16 進(jìn)制的ASCII 碼;反過(guò)來(lái),使用”%c”打印一個(gè)整數(shù),便可以看到它所對(duì)應(yīng)的ASCII 字符。以下程序段把所有可見(jiàn)字符的ASCII 碼對(duì)照表打印到屏幕上(這里采用printf,注意”#”與”%X”合用時(shí)自動(dòng)為16 進(jìn)制數(shù)增加”0X”前綴):
for(int i = 32; i < 127; i++) {
printf("[ %c ]: %3d 0x%#04X/n", i, i, i);
}
(3)連接字符串
sprintf 的格式控制串中既然可以插入各種東西,并最終把它們“連成一串”,自然也就能夠連
接字符串,從而在許多場(chǎng)合可以替代strcat,但sprintf 能夠一次連接多個(gè)字符串(自然也可以同時(shí)
在它們中間插入別的內(nèi)容,總之非常靈活)。比如:
char* who = "I";
char* whom = "CSDN";
sprintf(s, "%s love %s.", who, whom); //產(chǎn)生:"I love CSDN. "
strcat 只能連接字符串(一段以’’結(jié)尾的字符數(shù)組或叫做字符緩沖,null-terminated-string),但有時(shí)我們有兩段字符緩沖區(qū),他們并不是以 ’’結(jié)尾。比如許多從第三方庫(kù)函數(shù)中返回的字符數(shù)組,從硬件或者網(wǎng)絡(luò)傳輸中讀進(jìn)來(lái)的字符流,它們未必每一段字符序列后面都有個(gè)相應(yīng)的’’來(lái)結(jié)尾。如果直接連接,不管是sprintf 還是strcat 肯定會(huì)導(dǎo)致非法內(nèi)存操作,而strncat 也至少要求第一個(gè)參數(shù)是個(gè)null-terminated-string,那該怎么辦呢?我們自然會(huì)想起前面介紹打印整數(shù)和浮點(diǎn)數(shù)時(shí)可以指定寬度,字符串也一樣的。比如:
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!
十有八九要出問(wèn)題了。是否可以改成:
sprintf(s, "%7s%7s", a1, a2);
也沒(méi)好到哪兒去,正確的應(yīng)該是:
sprintf(s, "%.7s%.7s", a1, a2);//產(chǎn)生:"ABCDEFGHIJKLMN"
這可以類比打印浮點(diǎn)數(shù)的”%m.nf”,在”%m.ns”中,m 表示占用寬度(字符串長(zhǎng)度不足時(shí)補(bǔ)空格,超出了則按照實(shí)際寬度打印),n 才表示從相應(yīng)的字符串中最多取用的字符數(shù)。通常在打印字符串時(shí)m 沒(méi)什么大用,還是點(diǎn)號(hào)后面的n 用的多。自然,也可以前后都只取部分字符:
sprintf(s, "%.6s%.5s", a1, a2);//產(chǎn)生:"ABCDEFHIJKL"
在許多時(shí)候,我們或許還希望這些格式控制符中用以指定長(zhǎng)度信息的數(shù)字是動(dòng)態(tài)的,而不是靜態(tài)指定的,因?yàn)樵S多時(shí)候,程序要到運(yùn)行時(shí)才會(huì)清楚到底需要取字符數(shù)組中的幾個(gè)字符,這種動(dòng)態(tài)的寬度/精度設(shè)置功能在sprintf 的實(shí)現(xiàn)中也被考慮到了,sprintf 采用”*”來(lái)占用一個(gè)本來(lái)需要一個(gè)指定寬度或精度的常數(shù)數(shù)字的位置,同樣,而實(shí)際的寬度或精度就可以和其它被打印的變量一樣被提供出來(lái),于是,上面的例子可以變成:
sprintf(s, "%.*s%.*s", 7, a1, 7, a2);
或者:
sprintf(s, "%.*s%.*s", sizeof(a1), a1, sizeof(a2), a2);
實(shí)際上,前面介紹的打印字符、整數(shù)、浮點(diǎn)數(shù)等都可以動(dòng)態(tài)指定那些常量值,比如:
sprintf(s, "%-*d", 4, 'A'); //產(chǎn)生"65 "
sprintf(s, "%#0*X", 8, 128); //產(chǎn)生"0X000080","#"產(chǎn)生0X
sprintf(s, "%*.*f", 10, 2, 3.1415926); //產(chǎn)生" 3.14"
(4)打印地址信息
有時(shí)調(diào)試程序時(shí),我們可能想查看某些變量或者成員的地址,由于地址或者指針也不過(guò)是個(gè)32 位的數(shù),你完全可以使用打印無(wú)符號(hào)整數(shù)的”%u”把他們打印出來(lái):
sprintf(s, "%u", &i);
不過(guò)通常人們還是喜歡使用16 進(jìn)制而不是10 進(jìn)制來(lái)顯示一個(gè)地址:
sprintf(s, "%08X", &i);
然而,這些都是間接的方法,對(duì)于地址打印,sprintf 提供了專門(mén)的”%p”:
sprintf(s, "%p", &i);
我覺(jué)得它實(shí)際上就相當(dāng)于:
sprintf(s, "%0*x", 2 * sizeof(void *), &i);
(5)利用sprintf 的返回值
較少有人注意printf/sprintf 函數(shù)的返回值,但有時(shí)它卻是有用的,spritnf 返回了本次函數(shù)調(diào)用
最終打印到字符緩沖區(qū)中的字符數(shù)目。也就是說(shuō)每當(dāng)一次sprinf 調(diào)用結(jié)束以后,你無(wú)須再調(diào)用一次
strlen 便已經(jīng)知道了結(jié)果字符串的長(zhǎng)度。如:
int len = sprintf(s, "%d", i);
對(duì)于正整數(shù)來(lái)說(shuō),len 便等于整數(shù)i 的10 進(jìn)制位數(shù)。
下面的是個(gè)完整的例子,產(chǎn)生10 個(gè)[0, 100)之間的隨機(jī)數(shù),并將他們打印到一個(gè)字符數(shù)組s 中,
以逗號(hào)分隔開(kāi)。
#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';//將最后一個(gè)逗號(hào)換成換行符。
printf(s);
return 0;
}
設(shè)想當(dāng)你從數(shù)據(jù)庫(kù)中取出一條記錄,然后希望把他們的各個(gè)字段按照某種規(guī)則連接成一個(gè)字
符串時(shí),就可以使用這種方法,從理論上講,他應(yīng)該比不斷的strcat 效率高,因?yàn)閟trcat 每次調(diào)用
都需要先找到最后的那個(gè)’’的位置,而在上面給出的例子中,我們每次都利用sprintf 返回值把這
個(gè)位置直接記下來(lái)了。
使用sprintf 的常見(jiàn)問(wèn)題
sprintf 是個(gè)變參函數(shù),使用時(shí)經(jīng)常出問(wèn)題,而且只要出問(wèn)題通常就是能導(dǎo)致程序崩潰的內(nèi)存訪
問(wèn)錯(cuò)誤,但好在由sprintf 誤用導(dǎo)致的問(wèn)題雖然嚴(yán)重,卻很容易找出,無(wú)非就是那么幾種情況,通
常用眼睛再把出錯(cuò)的代碼多看幾眼就看出來(lái)了。
?? 緩沖區(qū)溢出
第一個(gè)參數(shù)的長(zhǎng)度太短了,沒(méi)的說(shuō),給個(gè)大點(diǎn)的地方吧。當(dāng)然也可能是后面的參數(shù)的問(wèn)
題,建議變參對(duì)應(yīng)一定要細(xì)心,而打印字符串時(shí),盡量使用”%.ns”的形式指定最大字符數(shù)。
?? 忘記了第一個(gè)參數(shù)
低級(jí)得不能再低級(jí)問(wèn)題,用printf 用得太慣了。//偶就常犯。:。(
?? 變參對(duì)應(yīng)出問(wèn)題
通常是忘記了提供對(duì)應(yīng)某個(gè)格式符的變參,導(dǎo)致以后的參數(shù)統(tǒng)統(tǒng)錯(cuò)位,檢查檢查吧。尤
其是對(duì)應(yīng)”*”的那些參數(shù),都提供了嗎?不要把一個(gè)整數(shù)對(duì)應(yīng)一個(gè)”%s”,編譯器會(huì)覺(jué)得你
欺她太甚了(編譯器是obj 和exe 的媽媽,應(yīng)該是個(gè)女的,:P)。
strftime
sprnitf 還有個(gè)不錯(cuò)的表妹:strftime,專門(mén)用于格式化時(shí)間字符串的,用法跟她表哥很像,也
是一大堆格式控制符,只是畢竟小姑娘家心細(xì),她還要調(diào)用者指定緩沖區(qū)的最大長(zhǎng)度,可能是為
了在出現(xiàn)問(wèn)題時(shí)可以推卸責(zé)任吧。這里舉個(gè)例子:
time_t t = time(0);
//產(chǎn)生"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,這一對(duì)由于從面向?qū)ο竽睦锏玫搅速澲?#xff0c;用以寫(xiě)出的代碼更覺(jué)優(yōu)雅。
?
?
?
資料七
?
sprintf 用法總結(jié)(2009-08-25 09:36:24)標(biāo)簽:it?? 分類:C++?
sprintf,將各種類型的數(shù)據(jù)夠造成字符串。
sprintf是個(gè)變參函數(shù),int sprintf(char *buffer,const char *format[,argument]...);除了前兩個(gè)參數(shù)類型固定外,后面可以接任意多個(gè)參數(shù),而它的精華,則在第二個(gè)參數(shù):格式化字符串上。
printf和sprintf都使用格式化字符串來(lái)指定串的格式,在格式串內(nèi)部使用一些以“%”開(kāi)頭的格式說(shuō)明符(format specification)來(lái)占據(jù)一個(gè)位置,在后邊的變參列表中提供相應(yīng)的變量,最終函數(shù)就會(huì)用相應(yīng)位置的變量來(lái)替代那個(gè)說(shuō)明符,產(chǎn)生一個(gè)調(diào)用者想要的字符串。
一、格式化數(shù)字字符串
sprintf最常見(jiàn)的應(yīng)用之一莫過(guò)于把整數(shù)打印到字符串中,所以sprintf在大多數(shù)場(chǎng)合可以替代itoa.
??? %-8d 代表寬度八位,左對(duì)齊(沒(méi)有負(fù)號(hào)為右對(duì)齊),整數(shù)的十進(jìn)制
%x小寫(xiě)16進(jìn)制 %X大寫(xiě)16進(jìn)制
??? 符號(hào)擴(kuò)展問(wèn)題:參數(shù)壓棧默認(rèn)四字節(jié),即8位16進(jìn)制。應(yīng)該讓編譯器做0擴(kuò)展而不是符號(hào)擴(kuò)展。
如 sprintf(s,"%04X",(unsigned short)si);
??? %o 8進(jìn)制格式化字符串。
控制浮點(diǎn)數(shù)打印格式,使用格式符"%f"控制,默認(rèn)保留小數(shù)點(diǎn)后6位數(shù)字。
%m.nf m表示打印的寬度,n表示小數(shù)點(diǎn)后的位數(shù)
sprintf(s,"%m.nf",i)其中i 必須為浮點(diǎn)類型的
二、字符/ASCII碼對(duì)照
%c打印一個(gè)整數(shù),可以看到整數(shù)所對(duì)應(yīng)的ASCII值
? for(int i=32 ;i<127;i++)
? {
? printf("[%c]:%3d 0x%#04X/n",i,i,i);
? }
#與%X合用時(shí)自動(dòng)為16進(jìn)制數(shù)增加“0X”前綴。
三、連接字符串
可以在許多場(chǎng)合替代strcat,sprintf能夠一次連接多個(gè)字符串。
%s可以參照浮點(diǎn)數(shù)控制的%m.n m表示寬度,n表示從相應(yīng)的字符串中最多取用的字符數(shù),通常m沒(méi)什么用。
對(duì)于動(dòng)態(tài)的,可以采用sprintf(s,"%.*s%.*s",7,a1,7,a2)或sprintf(s,"%.*s%.*s",sizeof(a1),a1,sizeof(a2),a2);
四、打印地址信息
有時(shí)調(diào)試程序時(shí),我們可能想查看某些變量或者成員的地址,由于地址或者指針也不過(guò)是個(gè)32 位的數(shù),你完全可以使用打印無(wú)符號(hào)整數(shù)的”%u”把他們打印出來(lái):
sprintf(s, "%u", &i);
不過(guò)通常人們還是喜歡使用16 進(jìn)制而不是10 進(jìn)制來(lái)顯示一個(gè)地址:
sprintf(s, "%08X", &i);
然而,這些都是間接的方法,對(duì)于地址打印,sprintf 提供了專門(mén)的”%p”:
sprintf(s, "%p", &i);
我覺(jué)得它實(shí)際上就相當(dāng)于:
sprintf(s, "%0*x", 2 * sizeof(void *), &i);
五、返回值
返回了本次函數(shù)調(diào)用最終打印到字符緩沖區(qū)中的字符數(shù)目。?
六、strftime
專門(mén)用于格式化時(shí)間字符串。需調(diào)用者指定緩沖區(qū)的最大長(zhǎng)度。
strftime(s,sizeof(s),"%Y-%m-%d %H:%M:%S",localtime(&t));
資料八
sprintf
int sprintf ( char * str, const char * format, ... ); Write formatted data to string Composes a string with the same text that would be printed if?format?was used on?printf, but instead of being printed, the content is stored as a?C string?in the buffer pointed by?str.The size of the buffer should be large enough to contain the entire resulting string (see?snprintf?for a safer version).
A terminating null character is automatically appended after the content.
After the?format?parameter, the function expects at least as many additional arguments as needed for?format.
Parameters
strThe buffer should be large enough to contain the resulting string.
There should be at least as many of these arguments as the number of values specified in the?format specifiers. Additional arguments are ignored by the function.
Return Value
On success, the total number of characters written is returned. This count does not include the additional null-character automatically appended at the end of the string.On failure, a negative number is returned.
Example
| 1 2 3 4 5 6 7 8 9 10 11 | /* sprintf example */ #include <stdio.h>int main () {char buffer [50];int n, a=5, b=3;n=sprintf (buffer, "%d plus %d is %d", a, b, a+b);printf ("[%s] is a string %d chars long\n",buffer,n);return 0; } | Edit & Run |
Output:
| [5 plus 3 is 8] is a string 13 chars long |
See also
snprintf總結(jié)
以上是生活随笔為你收集整理的整理:C++中sprintf()函数的使用详解的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 4加密问题漏洞修复_Apache Shi
- 下一篇: Win7下运行VC程序UAC权限问题