在 MFC 開發中,字符串處理是高頻需求。除了常用的 CString 成員函數,MFC 內部還提供了一組極其實用卻鮮少在 MSDN 中公開文檔的全局函數,例如 AfxFormatString1、AfxFormatString2、AfxFormatStrings 以及 AfxExtractSubString。這些函數能大幅簡化格式化輸出與子串提取的代碼編寫。本文將詳細介紹它們的用法、參數含義及內部實現邏輯。
這組函數的核心功能是:根據包含佔位符(%1、%2...)的格式字符串,將佔位符替換為指定的參數字符串,生成最終結果。
void AFXAPI AfxFormatString1(CString& rString, UINT nIDS, LPCTSTR lpsz1);void AFXAPI AfxFormatString2(CString& rString, UINT nIDS, LPCTSTR lpsz1, LPCTSTR lpsz2);void AFXAPI AfxFormatStrings(CString& rString, UINT nIDS, LPCTSTR const* rglpsz, int nString);void AFXAPI AfxFormatStrings(CString& rString, LPCTSTR lpszFormat, LPCTSTR const* rglpsz, int nString);參數說明:
rString:輸出參數,接收格式化後的字符串。nIDS:字符串資源表中的資源 ID,該資源字符串包含 %1、%2 等佔位符。lpszFormat:直接指定的格式字符串指針。rglpsz:指向字符串指針數組的指針,每個元素對應一個佔位符的替換值。nString:替換字符串的個數(即 rglpsz 數組長度)。lpsz1, lpsz2:具體的替換字符串。AfxExtractSubString 用於從一個由分隔符分隔的長字符串中,按索引提取某一段子串。
BOOL AFXAPI AfxExtractSubString(CString& rString, LPCTSTR lpszFullString, int iSubString, TCHAR chSep = _T('\n'));
參數:
rString:輸出,提取到的子串。lpszFullString:源字符串。iSubString:要提取的子串索引(從 0 開始)。chSep:分隔字符,默認為換行符 '\n'。返回值: 成功提取返回 TRUE,索引越界或源字符串為空返回 FALSE。
MFC 源碼中這些函數的實現邏輯清晰,核心在 AfxFormatStrings(LPCTSTR lpszFormat, ...) 這個重載版本中:
%1~%9、%A~%Z 形式的佔位符,累加對應替換字符串的長度;普通字符直接計長。同時處理雙字節字符(_istlead)。CString::GetBuffer(nTotalLen) 獲取寫入指針。'?')。ReleaseBuffer 確定最終長度。AfxFormatString1/2 只是構造臨時數組調用通用版本;AfxExtractSubString 則通過循環查找分隔符 _tcschr 定位子串範圍,再用 memcpy 複製內容。
假設資源表中有字符串 IDS_MSG = "用戶 %1 於 %2 登錄系統":
CString strResult;
AfxFormatString2(strResult, IDS_MSG, _T("Admin"), _T("2024-05-20 10:30"));
// strResult = "用戶 Admin 於 2024-05-20 10:30 登錄系統"
提取配置行 "key1=value1;key2=value2;key3=value3" 中第 2 段(索引 1):
CString strPart;
AfxExtractSubString(strPart, _T("key1=value1;key2=value2;key3=value3"), 1, _T(';'));
// strPart = "key2=value2"
這幾個「隱藏」函數雖未公開文檔,但已在 MFC 內部廣泛使用(如提示訊息格式化、日誌記錄等),穩定可靠。掌握它們能讓字符串拼接、模板替換、配置解析的代碼更簡潔、高效,是 MFC 開發者工具箱中的利器。