Windows 程式開發中,ANSI (char) 與 Unicode (TCHAR/WCHAR) 字串共存,轉換處理是必備技能。本文系統整理轉換規則、格式化字串技巧與 system() 呼叫 MSC 檔案實戰範例。
核心類型定義
| 類型 | 本質 | 適用編譯模式 |
char | 8-bit ANSI 字元 | 多位元組字元集 (MBCS) |
WCHAR | 16-bit Unicode 字元 | Unicode |
TCHAR | 條件編譯:MBCS=char, Unicode=WCHAR | 兩者通用 |
winnt.h 中:typedef WCHAR TCHAR, *PTCHAR; (Unicode 專案)
字串常值前綴
"string":ANSI 字串
L"string":Unicode 字串
_T("string") / TEXT("string"):自動適應編譯模式 (推薦)
格式化函數與格式指定符對照
| 函數 | 字串類型 | ANSI 輸入 | Unicode 輸入 |
sprintf | ANSI | %s | %S (大寫 S 轉換) |
swprintf | Unicode | %S | %s |
口訣:sprintf 寫 ANSI,%s 接 ANSI,%S 接 Unicode;swprintf 寫 Unicode,%s 接 Unicode,%S 接 ANSI。
實戰範例:system() 啟動 .msc 管理工具
system() 接受 char* (ANSI),Unicode 專案中需將 CString (TCHAR) 轉換。
void CMyDlg::OnLaunchMsc() {
CString strPath; // TCHAR 字串 (Unicode 專案為 wchar_t)
m_editPath.GetWindowTextW(strPath); // 獲取路徑
// 1. 路徑反斜線轉義:system 命令列需雙反斜線
strPath.Replace(_T("\\"), _T("\\\\")); // C:\Windows\System32 → C:\\Windows\\System32
// 2. TCHAR → char 轉換構建命令列
char szCmd[512];
// 方法一:sprintf + %S (Unicode→ANSI)
sprintf(szCmd, "mmc.exe \"%S\"", strPath);
// 方法二:WideCharToMultiByte (更安全、可控編碼頁)
// WideCharToMultiByte(CP_ACP, 0, strPath, -1, szCmd, 512, NULL, NULL);
// strcat(szCmd, "\"");
// 3. 執行
system(szCmd);
}
轉換方法完整對比
| 方法 | 適用場景 | 優點 | 缺點 |
sprintf(sz, "%S", tstr) | 簡單格式化 | 程式碼簡潔 | 緩衝區溢位風險、依賴當前 ANSI 頁 |
WideCharToMultiByte | 生產級轉換 | 指定編碼頁(CP_UTF8/CP_ACP)、回傳所需長度、安全 | 程式碼較長 |
CStringA strA = strT; | MFC/ATL 專案 | 自動轉換、RAII 管理 | 依賴 MFC/ATL |
_bstr_t(strT) | COM 互操作 | 支援 BSTR 轉換 | 效率較低 |
std::wstring_convert (C++11) | 標準庫 | 標準化、支援 UTF-8/16/32 | C++17 棄用、需 <locale> |
Unicode 專案最佳實踐
- 內部統一使用 TCHAR/CString,邊界處轉換
- Win32 API 呼叫:優先使用
XXXW 寬字元版本 (CreateFileW、MessageBoxW),避免轉換
system()/WinExec() 等 ANSI-only API:使用 WideCharToMultiByte(CP_ACP, ...) 明確轉換
- 檔案路徑、登錄表、網路通訊等外部介面:確認對端編碼要求,必要時指定 UTF-8
常見錯誤避坑
sprintf(sz, "%s", tstr) 直接傳 TCHAR → 亂碼/崩潰
- 緩衝區大小不足 → 緩衝區溢位,改用
snprintf / _snprintf_s
- 混用
CP_ACP (系統預設) 與 CP_UTF8 導致中文亂碼
- 忘記命令列參數雙引號包裹含空格路徑
- 上一篇文章: VC Picture Control 點擊事件處理完整指南:從屬性設定到訊息映射
- 下一篇文章: MFC CArray 作為函數參數與回傳值的正確姿勢:避開拷貝建構陷阱
Copyright ©
程式碼之家 All Rights Reserved