當前位置:名人名言大全網 - 笑話大全 - 詳細用法問std::ostringstream。下圖如何用上面的函數寫sprintf?

詳細用法問std::ostringstream。下圖如何用上面的函數寫sprintf?

Sprintf()打印格式函數(圖形)

函數:sprintf()用於格式化輸出。

用法:這個函數叫做intsprintf (char * string,char * format,arg _ list);

說明:s printf()函數的用法和printf()函數壹樣,只是sprintf()函數先給出參數字符串(通常是字符數組),然後調用outtextxy()函數在屏幕上顯示字符串中的字符。Arg_list是壹個不確定數目的參數表。通常在繪圖模式下輸出數字時,可以調用sprintf()函數,將想要輸出的格式發送給第壹個參數,然後顯示輸出。

函數名:sprintf

函數:將打印格式發送給字符串。

用法:intsprintf (char * string,char * farm [,argument,...]);

程序示例:

#包括

#包括

int main(void)

{

充電緩沖器[80];

sprintf(buffer," Pi的近似值是%f\n ",M _ PI);

puts(緩沖區);

返回0;

}

Sprintf用於將格式化字符串輸出到目標字符串,而printf用於將格式化字符串輸出到屏幕。sprintf的第壹個參數應該是目標字符串。如果不指定該參數,提示“該程序存在非法操作,即將關閉…”會在執行過程中出現。

由於C語言在操作字符串時不檢查字符串的空間是否足夠大,可能會出現數組越界,程序崩潰的問題。就算碰巧程序沒錯,也不要這麽用,因為遲早會出錯。所以在調用sprintf之前壹定要給buf分配足夠的空間。

因為sprintf和printf的用法幾乎壹樣,只是打印的目的地不同,前者打印成字符串,

後者直接在命令行上輸出。這也使得sprintf比printf有用得多。所以本文主要關註sprintf,有時

還穿插了pritnf的使用。

Sprintf是壹個可變參數函數,定義如下:

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

除了前兩個參數的固定類型之外,還可以跟任意數量的參數。而它的本質,顯然在第二個參數中:

格式化字符串。

printf和sprintf都使用格式字符串來指定字符串的格式,並且在格式字符串中使用了壹些以“%”開頭的字符。

格式說明符(formatspecifications)占據壹個位置,在變量列表的後面提供相應的變量,最後。

該函數將用相應位置的變量替換該說明符,以生成調用者需要的字符串。

格式化數字字符串

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就行了。

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

上面帶“%d”的10二進制打印也可以用這種左邊填0的方式。

這裏要註意符號擴展的問題:比如要打印壹個短整數(short)-1內存16十六進制表。

Form,在Win32平臺上,壹個短類型占2個字節,所以我們自然要用4個16的數字來打字。

打印它:

短si =-1;

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

產生“FFFFFFFF”。發生了什麽事?因為spritnf是壹個變參數函數,除了前兩個參數,後面的

沒有壹個參數是類型安全的,在函數調用之前,函數沒有辦法通過壹個" %X "知道參數堆棧。

無論是4字節整數還是2字節短整數都是壓入的,所以采用統壹的4字節處理方式。

結果參數的符號在堆棧的時候被展開了,展開成了32位整數-1。打印的時候四位不夠,取了32位整數。

打印-1的8位16系統。要想看清si的真面目,應該讓編譯器做0擴展,而不是。

符號擴展(擴展時,二進制左邊用0代替符號位填充):

sprintf(s," %04X ",(無符號短整型)si);

去做吧。或者:

無符號短si =-1;

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

Sprintf和printf也可以打印八進制的整數字符串,使用“%o”。註意,八進制和16都不能輸入。

打印出來的負數都是無符號的,實際上是變量內部編碼的直接16十六進制或八進制表示。

控制浮點數打印格式

浮點數的打印和格式控制是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的可憐的四個字節被強行解釋為浮點數格式,整個事情就亂套了。

但是,如果有人對手工編碼浮點數感興趣,可以用這個方法來測試壹下自己的手。

工作安排的結果是否正確。?

字符/Ascii代碼比較

我們知道,在C/C++語言中,char也是壹種常見的可伸縮類型,它不同於short,

int和long的類型沒有本質區別,只是習慣於表示字符和字符串。(也許是時候放下了

這種類型叫做“byte”,現在可以根據實際情況通過typedef使用byte或者short來定義char。

義,是比較恰當的)

然後用“%d”或“%x”打印壹個字符,可以得到它的ASCII碼在10或16;反面的

來,用“%c”打印壹個整數,可以看到它對應的ASCII字符。下面的程序段把所有可見的字符。

屏幕上打印出ASCII碼對照表(此處使用printf,請註意當“#”和“%X”壹起使用時,會自動在16的十六進制數上加“0X”。

前綴):

for(int I = 32;我& lt127;i++) {

printf("[ %c ]: %3d 0x%#04X\n ",I,I,I);

}

連接字符串

既然各種東西都可以插入到sprintf的格式控制字符串中,最後可以“連成壹串”,自然就可以連接起來。

String,在很多場合可以代替strcat,但是sprintf可以壹次連接多個字符串(自然也可以同時

中間插點別的,很靈活)。例如:

char * who = " I

char * whom = " CSDN ";

sprintf(s,“%s愛%s”,誰,誰);//生成:“我愛CSDN。”

Strcat只能連接字符串(以' \0 '結尾的字符數組或稱為字符緩沖區,以null結尾的字符串)。

但有時我們有兩個不以' \0 '結尾的字符緩沖區。比如很多第三方庫函數返回的字符數。

組,從硬件或網絡傳輸中讀取的字符流,不壹定在每個字符序列後都有相應的' \0 '。

尾巴。如果直接連接,無論是sprintf還是strcat都肯定會導致內存操作非法,strcat也要求至少是第壹種

壹個參數是空終止字符串,我該怎麽辦?我們自然會想到打印前面介紹的整數和浮點數。

您可以指定寬度,字符串也可以。例如:

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

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

如果:

sprintf(s," %s%s ",a1,a2);//不要這樣!

十有八九會出問題。可以改成:

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(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”

打印地址信息

有時在調試程序時,我們可能想檢查壹些變量或成員的地址。因為地址或指針只是壹個32位的數字,所以您可以通過使用“%u”打印無符號整數來打印它們:

sprintf(s," %u ",& ampI);

但是人們通常更喜歡用16而不是10來顯示地址:

sprintf(s," %08X ",& ampI);

然而,這些都是間接的方法,sprintf為地址打印提供了壹個特殊的“%p”:

sprintf(s," %p ",& ampI);

我認為它實際上相當於:

sprintf(s," %0*x ",2 * sizeof(void *),& ampI);

使用sprintf的返回值

很少有人關註printf/sprintf函數的返回值,但有時候很有用。spritnf返回這個函數調用。

最終打印到字符緩沖區中的字符數。也就是說,每次sprinf通話結束,都不需要再打壹次。

Strlen已經知道結果字符串的長度。比如:

int len = sprintf(s," %d ",I);

對於正整數,len等於整數I的10位數。

下面是壹個完整的例子,生成10 [0,100]之間的隨機數,並打印成字符數組S,

用逗號分隔。

#包括

#包括

#包括

int main() {

srand(time(0));

char s[64];

int offset = 0;

for(int I = 0;我& lt10;i++) {

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

}

s[offset-1]= ' \ n ';//用換行符替換最後壹個逗號。

printf

返回0;

}

想象壹下,當妳從數據庫中取出壹條記錄,然後妳想按照壹些規則把它們的字段連接成壹個單詞。

操作符字符串,可以用這個方法,理論上應該比常量strcat更高效,因為strcat每次調用。

我們首先需要找到最後壹個' \0 '的位置,在上面給出的例子中,我們總是使用sprintf返回值來放置它。

地點直接寫了下來。

關於使用sprintf的常見問題

Sprintf是壹個可變參數函數,使用時經常會出現問題,而且只要出現問題,通常都是壹次內存訪問就能導致程序崩潰。

問錯了問題,不過還好,sprintf誤用造成的問題雖然嚴重,但是很容易查出來,無非就是幾種情況。

用眼睛看就能看出代碼不對。

緩沖區溢出

第壹個參數的長度太短。讓我們給它壹個更大的地方。當然也可能是後期參數的問題。

問題,建議您在相應的參數更改時壹定要小心,並且在打印字符串時,盡量以" % "的形式指定最大字符數。ns”。

忘記了第壹個參數。

低級的問題不能再低級了,printf也太用了。//我經常做。:。(

可變參數對應問題。

通常忘記提供某個格式字符對應的變量參數,導致以後所有參數錯位。檢查壹下。特別

是否提供了與“*”對應的參數?不要把壹個整數對應到壹個“%s”,編譯器會認為妳

太欺負她了(編譯器是obj和exe的母親,應該是女的,:p)。

strftime

Sprnitf還有壹個很好的表親:strftime,專門用來格式化時間字符串。用法和她表姐的很像,也

是很多格式控制器,但畢竟小姑娘比較謹慎,要調用調用者指定緩沖區的最大長度,可能是

有問題的時候可以推卸責任。這裏有壹個例子:

time _ t t = time(0);

//生成“YYYY-MM-DDhh:mm:ss”格式的字符串。

char s[32];

strftime(s,sizeof(s)," %Y-%m-%d %H:%M:%S ",local time(& amp;t));

Sprintf也能在MFC中找到知音:CString::Format,strftime自然有她在MFC中的朋友:

CTime::Format,這對贊助面向對象,用來寫的代碼更優雅。

附言

本文介紹的這些功能在MSDN都很容易找到,作者只是根據自己的經驗來使用。

結合壹些實例,介紹壹些可能很多初學者不知道的常用且有用的用法,望大家多多指教。

不要在家裏開玩笑,也希望大家批評指正。

有人認為這種參數可變的函數會產生各種問題,所以不推薦。但作者本人往往也無法抗拒。

被其強大的功能所吸引,在實際工作中得到了應用。其實C#。NET從壹開始就支持參數變化,現在才剛剛發布。

很快Java5.0也支持參數變化。

感謝ericzhangali(另壹個空間)仔細審閱了整篇稿件,改正了很多小錯誤,並提出了壹些建議。

也感謝老麥看完整稿,並給出增刪部分內容的建議。