STL std::string 功能強大且跨平台,但習慣 MFC CString 的開發者可能覺得不夠直觀。本文演示如何包裝 std::string 實現類 CString 風格的 XString 類,重點實現 Format 與 MakeUpper 等常用方法。
int nMaxLen = 0;
va_list argList;
va_start(argList, pstrFormat);
for (const char* p = pstrFormat; *p; ++p) {
if (*p != '%' || *(p+1) == '%') { nMaxLen++; continue; }
++p; // 跳過 '%'
// 解析標志、寬度、精度、長度修飾符
for (; *p; ++p) {
if (*p == '#') nMaxLen += 2; // 為 "0x" 預留
else if (*p == '*') nWidth = va_arg(argList, int);
else if (strchr("-+0 ", *p)) continue; // 填充標志忽略長度
else break;
}
if (*p == '.') {
++p;
if (*p == '*') nPrecision = va_arg(argList, int);
else { nPrecision = atoi(p); while (isdigit(*p)) ++p; }
}
if (strchr("hlLIF", *p)) ++p; // 忽略長度修飾符
// 根據類型字符估算項長度
switch (*p) {
case 'c': case 'C': nItemLen = 2; va_arg(argList, char); break;
case 's': case 'S': {
const char* s = va_arg(argList, const char*);
nItemLen = strlen(s); nItemLen = max(1, nItemLen); break;
}
case 'd': case 'i': case 'u': case 'x': case 'X': case 'o':
va_arg(argList, int); nItemLen = 32; break;
case 'e': case 'f': case 'g': case 'G':
va_arg(argList, double); nItemLen = 32; break;
default: nItemLen = 1;
}
nMaxLen += nItemLen;
}
va_end(argList);
char* ch = new char[nMaxLen + 1]; va_start(argList, pstrFormat); vsprintf(ch, pstrFormat, argList); va_end(argList); append(ch); // std::string::append delete[] ch;
void MakeUpper() {
std::transform(begin(), end(), begin(), toupper);
}
// 類似可包裝:MakeLower, TrimLeft, TrimRight, Find, Replace 等
代碼在 VC++ 6.0 與 g++ (Linux) 均編譯通過。作者曾用 XString 替換 MFC 專案中所有 CString,成功移植至 Linux/g++ 環境。
通過薄包裝層,即可在享受 STL 跨平台優勢的同時保留 CString 熟悉的介面風格。完整源碼隨文提供。