字符串格式化輸出


    C 語言中提供了一些基本字符串格式化處理函數,包括:

    1)puts("this is a string");  簡單輸出字符串到 standard output 中,該函數只有多字節版本;

    2)int len = printf("1 + 2 = %d", 1 + 2); 格式化輸出字符串到 standard output 中,返回值表示輸出字符串長度,其 Unicode 版本為 wprintf(const wchar_t *_Format, ...);

    3)int len = sprintf(szBuffer, "1 + 2 = %d", 1 + 2); 格式化輸出字符串到 szBuffer 中,返回值表示輸出字符串長度,其中 szBuffer 定義:char szBuffer[1024];

    4)當需要自己構造 printf-like 格式函數,可以借助 vsprintf 函數,具體如下:

 

 1 int MyMessageBox (char* szCaption, char* szFormat, ...)
 2 {
 3      char szBuffer [1024] ;
 4      va_list pArgList ;
 5 
 6      // The va_start macro (defined in STDARG.H) is usually equivalent to:
 7      // pArgList = &szFormat + sizeof (szFormat) ;
 8 
 9      va_start (pArgList, szFormat) ;
10 
11      vsprintf (szBuffer, szFormat, pArgList) ;
12 
13      // The va_end macro just zeroes out pArgList for no good reason
14      va_end (pArgList) ;
15 
16      return MessageBoxA (NULL, szBuffer, szCaption, 0) ;
17 }

     va_list 保存了函數參數棧第一個可變參數指針,結合格式化字符串 szFormat 給出每個格式化數據類型,vsprintf 訪問每一個參數,完成格式化工作。這是可變參數函數工作原理。具體解析如下:

    a. 定義 typedef char *va_list;

    b. va_start (pArgList, szFormat) ;語句使 pArgList 指向第一個可變參數,szFormat 給出第一個可變參數前一個參數位置;

    c. type va_arg(va_list ap, type);語句取出下一個可變參數值,其中 type 指定該可變參數類型;在以上代碼中 vsprintf 內部完成了該工作;

    d. va_end (pArgList) ; 語句關閉 pArgList 指針,保持程序健壯性;

    以上方法實現可變參數訪問,在函數調用中,函數參數從右到左入棧。只要直到其中任意一個參數位置,可以根據參數位置以及參數類型訪問到任意一個參數。下面構造一個簡單的可變參數訪問函數以說明其原理:

    

 1 // agrc 表示可變參數個數,可變參數類型均為整數
 2 void ArgAnalyze(int argc, ...)
 3 {
 4     int *ptr = &argc;
 5     ++ptr;
 6     for(int i = 0; i < argc; ++i)
 7     {
 8         std::cout<<"argv"<<i + 1<<" = "<<*ptr<<std::endl;
 9         ++ptr;
10     }
11 }

    5) sprintf, vsprintf 函數存在一些缺陷,當傳入 Buffer 空間小於格式化字符串空間時,函數會覆蓋鄰近區域,可能導致程序異常錯誤。因此,微軟特別定義了一些安全函數:_snprintf, _vsnprintf,通過增加傳入空間參數來避免該錯誤。同時,微軟也給出了對應的 windows 版本函數,基本與C庫版本一致。以下給出 sprintf, vsprintf 相關的安全版本, Unicode 版本以及通用版本:

                                        ASCII            Wide-Character      Generic

    standard version         sprintf            swprintf                  _stprintf

    safe version                _snprintf         _snwprintf              _sntprintf

    windows version         wsprintfA        wsprintfW              wsprintf

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

    standar version           vsprintf            vswprintf               _vstprintf

    safe version                _vsnprintf        _vsnwprintf           _vsntprintf

    windows version         wvsprintfA       wvsprintfW            wvsprintf

 

   在 c++ 庫中,也提供了相應的字符串格式化輸出,具體如下:

    

 1 // 輸出到 standart output(多字節版本)
 2 std::cout<<"1 + 2 = "<<1 + 2<<std::endl;  
 3 
 4 // 輸出到 standart output(寬字節版本)
 5 std::wcout<<L"1 + 2 = "<<1 + 2<<std::endl; 
 6 
 7 // 輸出到字符串中(多字節版本)
 8 std::stringstream ss;
 9 ss<<"1 + 2 = "<<1 + 2<<std::endl;
10 std::string s = ss.str();
11 
12 // 輸出到字符串中(寬字節版本)
13 std::wstringstream wss;
14 wss<<L"1 + 2 = "<<1 + 2<<std::endl;
15 std::wstring ws = wss.str();

 

 

    參考資料 Programming Windows by Charles Petzold


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM