C++ Windows平台字符串编码转换

一、Windows API

本文介绍使用Windows API进行字符编码的转换,涉及WideCharToMultiByteMultiByteToWideChar2个API,

API接口名中的MultiByte对应着多字节编码,如ASCII、UTF-8等都是多字节编码,而WideChar字面意思是宽字符,在windows内部宽字符特指UTF-16编码。 原型如下:

int WideCharToMultiByte(
  UINT CodePage, 
  DWORD dwFlags, 
  LPCWSTR lpWideCharStr, 
  int cchWideChar, 
  LPSTR lpMultiByteStr, 
  int cbMultiByte, 
  LPCSTR lpDefaultChar, 
  LPBOOL lpUsedDefaultChar 
);

int MultiByteToWideChar(
  UINT CodePage, 
  DWORD dwFlags, 
  LPCSTR lpMultiByteStr, 
  int cbMultiByte, 
  LPWSTR lpWideCharStr, 
  int cchWideChar 
);


二、字符串编码转换

std::string UnicodeToANSI(const std::wstring &str, UINT iCodePage = CP_ACP) {
    std::string strRes;
    int iSize = ::WideCharToMultiByte(iCodePage, 0, str.c_str(), -1, NULL, 0, NULL, NULL);

    if (iSize == 0)
        return strRes;

    char *szBuf = new (std::nothrow) char[iSize];
    if (!szBuf)
        return strRes;
    memset(szBuf, 0, iSize);

    ::WideCharToMultiByte(iCodePage, 0, str.c_str(), -1, szBuf, iSize, NULL, NULL);

    strRes = szBuf;
    delete[] szBuf;

    return strRes;
}

std::wstring ANSIToUnicode(const std::string &str, UINT iCodePage = CP_ACP) {
    std::wstring strRes;

    int iSize = ::MultiByteToWideChar(iCodePage, 0, str.c_str(), -1, NULL, 0);

    if (iSize == 0)
        return strRes;

    wchar_t *szBuf = new (std::nothrow) wchar_t[iSize];
    if (!szBuf)
        return strRes;
    memset(szBuf, 0, iSize * sizeof(wchar_t));

    ::MultiByteToWideChar(iCodePage, 0, str.c_str(), -1, szBuf, iSize);

    strRes = szBuf;
    delete[] szBuf;

    return strRes;
}

std::string UnicodeToUTF8(const std::wstring &str) {
    std::string strRes;

    int iSize = ::WideCharToMultiByte(CP_UTF8, 0, str.c_str(), -1, NULL, 0, NULL, NULL);

    if (iSize == 0)
        return strRes;

    char *szBuf = new (std::nothrow) char[iSize];
    if (!szBuf)
        return strRes;
    memset(szBuf, 0, iSize);

    ::WideCharToMultiByte(CP_UTF8, 0, str.c_str(), -1, szBuf, iSize, NULL, NULL);

    strRes = szBuf;
    delete[] szBuf;

    return strRes;
}

std::string UnicodeToUTF8BOM(const std::wstring &str) {
    std::string strRes;

    int iSize = ::WideCharToMultiByte(CP_UTF8, 0, str.c_str(), -1, NULL, 0, NULL, NULL);

    if (iSize == 0)
        return strRes;

    unsigned char *szBuf = new (std::nothrow) unsigned char[iSize + 3];
    if (!szBuf)
        return strRes;
    memset(szBuf, 0, iSize + 3);

    if (::WideCharToMultiByte(CP_UTF8, 0, str.c_str(), -1, (LPSTR)(szBuf + 3), iSize, NULL, NULL) > 0) {
        szBuf[0] = 0xEF;
        szBuf[1] = 0xBB;
        szBuf[2] = 0xBF;
    }

    strRes = (char*)szBuf;
    delete[] szBuf;

    return strRes;
}

std::wstring UTF8ToUnicode(const std::string &str) {
    std::wstring strRes;
    int iSize = ::MultiByteToWideChar(CP_UTF8, 0, str.c_str(), -1, NULL, 0);

    if (iSize == 0)
        return strRes;

    wchar_t *szBuf = new (std::nothrow) wchar_t[iSize];
    if (!szBuf)
        return strRes;
    memset(szBuf, 0, iSize * sizeof(wchar_t));
    ::MultiByteToWideChar(CP_UTF8, 0, str.c_str(), -1, szBuf, iSize);

    strRes = szBuf;
    delete[] szBuf;

    return strRes;
}

std::string ANSIToUTF8(const std::string &str, UINT iCodePage = CP_ACP) {
    return UnicodeToUTF8(ANSIToUnicode(str, iCodePage));
}

std::string ANSIToUTF8BOM(const std::string &str, UINT iCodePage = CP_ACP) {
    return UnicodeToUTF8BOM(ANSIToUnicode(str, iCodePage));
}

std::string UTF8ToANSI(const std::string &str, UINT iCodePage = CP_ACP) {
    return UnicodeToANSI(UTF8ToUnicode(str), iCodePage);
}


对于只支持简体中文(部分韩文、日文)的系统,iCodePage可以使用CP_ACP,这时API会使用系统当前的代码页(简体中文系统为CP936,即GBK字符集)来进行编码转换。 但遇到如下情况就需要手动指定代码页了:

  1. 需要转换的字符串中的文字是系统当前代码页不支持的。如字符串中含有中文,而当前系统代码页确是英文的;
  2. GBK字符集中只包含了一部分韩文和日文,部分韩文和日文的转换可以正常转换,若遇到不能转换的情况也需要将指定iCodePage为特定的支持韩文或日文的代码页了,特别是中文和韩文、日文等混合的情况下。如韩文“탉”不包含在GBK中,若这时仍然使用CP_ACP就会得到错误的转换结果?,十六进制3F。但GB18030(代码页为54936)支持“탉”,可以手动指定iCodePage为54936。


如果代码中含有GBK不支持的字符,如“탉”等特殊字符,Visual Studio会弹出如下提示:
Visual Studio选择代码页
选择“以其他编码保存”,选择“Unicode(UTF-8带签名)- 代码页65001”保存。
虽然“简体中文(GB18030) - 代码页54936”也支持这些字符,但不能选择该选项进行保存,具体原因在拨开字符编码的迷雾--编译器如何处理文件编码 中有详细的介绍。

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
以下是使用 C++ 搜索名称包含某个字符串Windows 窗口的代码: ```cpp #include <iostream> #include <Windows.h> #include <vector> using namespace std; BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam) { vector<wchar_t>* str = reinterpret_cast<vector<wchar_t>*>(lParam); wchar_t title[256]; GetWindowText(hwnd, title, sizeof(title)); if (wcsstr(title, &(*str)[0])) { wcout << title << endl; } return TRUE; } int main() { vector<wchar_t> str{ L"search_string" }; EnumWindows(EnumWindowsProc, reinterpret_cast<LPARAM>(&str)); return 0; } ``` 在这个代码中,我们使用 `EnumWindows` 函数来枚举所有顶层窗口。对于每个窗口,我们获取其标题,然后在标题中搜索指定字符串。如果找到,则将窗口标题打印到控制台中。 请注意,我们使用 `vector` 存储搜索字符串,并将其作为 `LPARAM` 参数传递给 `EnumWindowsProc` 回调函数。这是因为 `EnumWindowsProc` 函数只能接受一个 `LPARAM` 参数,但是我们需要传递两个参数:窗口句柄和搜索字符串。因此,我们将搜索字符串存储在 `vector` 中,然后将其地址通过 `reinterpret_cast` 转换为 `LPARAM` 类型,传递给 `EnumWindowsProc` 函数。在回调函数中,我们再次使用 `reinterpret_cast` 将 `LPARAM` 参数转换回 `vector` 类型,并获取搜索字符串的地址。 另外,请注意,我们使用了 `wchar_t` 类型来处理 Unicode 字符串。这是因为 Windows 使用 Unicode 字符编码。在 `wcout` 中使用 `<<` 运算符打印 Unicode 字符串

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

china_jeffery

你的鼓励是我前进的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值