天天看點

printf,sprintf,vsprintf 差別

有C語言寫作曆史的程式員往往特别喜歡printf 函數。即使可以使用更簡單的指令(例如puts),但printf 出現在Kernighan和Ritchie的「hello, world」程式中一點也不會令人驚奇。我們知道,增強後的「hello, world」最終還是需要printf 的格式化輸出,是以我們最好從頭開始就使用它。

但有個壞消息:在Windows程式中不能使用printf。雖然Windows程式中可以使用大多數C的執行時期函數庫。實際上,許多程式寫作者更願意使用C的記憶體管理和I/O函數而不是Windows中等效的函數-Windows對标準輸入和标準輸出沒有概念。在Windows程式中可使用fprintf,而不是printf。

還有一個好消息,那就是仍然可以使用sprintf 及sprintf 系列中的其他函數來顯示文字。這些函數除了将内容格式化輸出到第一個參數所提供的字元串緩沖區以外,其功能與printf 相同。然後便可對該字元串進行操作(例如将其傳給MessageBox)。

如果您從未使用過sprintf (我第一次開始寫Windows程式時也沒用過此函數),這裡有一個簡短的執行實體。

printf 函數說明如下:

int printf (const char * szFormat, ...);

第一個參數是一個格式化字元串,後面是與格式化字元串中的代碼相對應的不同類型多個參數。

sprintf 函數定義如下:

int sprintf (char * szBuffer, const char * szFormat, ...);

第一個參數是字元串緩沖區,後面是一個格式字串。sprintf不是将格式化結果标準輸出,而是将其存入szBuffer。該函數傳回該字元串的長度。

在指令行程式中,

printf ("The sum of %i and %i is %i", 5, 3, 5+3) ;

的功能相同于

char szBuffer [100] ;

sprintf (szBuffer, "The sum of %i and %i is %i", 5, 3, 5+3) ;

puts (szBuffer) ;

在Windows中,使用MessageBox顯示結果優于puts。

幾乎每個人都經曆過,當格式化字元串與被格式化的變數不合時,可能使printf 執行錯誤并可能造成程式當掉。使用sprintf 時,您不但要擔心這些,而且還有一個新的負擔:您定義的字元串緩沖區必須足夠大以存放結果。Microsoft 專用函數_snprintf 解決了這一問題,此函數引進了另一個參數,表示以位元組計算的緩沖區大小。

vsprintf 函數定義如下:

int vsprintf(char *string, char *format, va_list param);

vsprintf 是sprintf 的一個變形,它隻有三個參數。vsprintf 用于執行有不定數量參數的函數,類似printf 格式。vsprintf的前兩個參數與sprintf相同:一個用于儲存結果的字元串緩沖區和一個格式化字元串。第三個參數是指向格式化參數隊列的指針。實際上,該指針指向在堆棧中供函數調用的變量。va_list、va_start和va_end宏(在STDARG.H中定義)幫助我們處理堆棧指針。本章最後的SCRNSIZE程式展示了使用這些宏的方法。使用vsprintf 函數,sprintf 函數可以這樣編寫:

int sprintf (char * szBuffer, const char * szFormat, ...)

{

int     iReturn ;

va_list pArgs ;

va_start (pArgs, szFormat) ;

iReturn = vsprintf (szBuffer, szFormat, pArgs) ;

va_end (pArgs) ;

return iReturn ;

}

va_start宏将pArg設定為指向一個堆棧變量,該變量位址在堆棧參數szFormat的上面。

由於許多Windows早期程式使用了sprintf 和vsprintf,最終導緻Microsoft 向Windows API中增添了兩個相似的函數。Windows的wsprintf 和wvsprintf 函數在功能上與sprintf 和vsprintf 相同,但它們不能處理浮點格式。

當然,随著寬字元的發表,sprintf 類型的函數增加了許多,使得函數名稱變得極為混亂。下面列出了Microsoft 的C執行時期函數庫和Windows支援的所有sprintf 函數。

ASCII 寬字元 正常

參數的變量個數       

标準版 sprintf swprintf _stprintf

最大長度版 _snprintf _snwprintf _sntprintf

Windows版 wsprintfA wsprintfW wsprintf 

參數隊列的指針       

标準版 vsprintf vswprintf _vstprintf

最大長度版 _vsnprintf _vsnwprintf _vsntprintf

Windows版 wvsprintfA wvsprintfW wvsprintf

在寬字元版的sprintf 函數中,将字元串緩沖區定義為寬字元串。在寬字元版的所有這些函數中,格式化字元串必須是寬字元串。不過,您必須確定傳遞給這些函數的其他字元串也必須由寬字元組成。