取wchar_t并放入char

Take wchar_t and put into char?

本文关键字:char wchar      更新时间:2023-10-16

我已经尝试了一些事情,但还不能弄清楚如何将const wchar_t *text(如下所示)传递到变量StoreText(如下所述)中。我做错了什么?

void KeyboardComplete(int localClientNum, const wchar_t *text, unsigned int len)
{
    char* StoreText = text; //This is where error occurs
}

不能将wchar_t*直接分配给char*,因为它们是不同且不兼容的数据类型。

如果StoreText需要指向text所指向的同一内存地址,例如,如果您计划循环遍历text数据的各个字节,那么简单的类型转换就足够了:

char* StoreText = (char*)text;

但是,如果StoreText需要指向其自己的单独的字符数据副本,则需要将宽字符数据转换为窄字符数据。例如:

  • 在Windows:上使用WideCharToMultiByte()功能

    void KeyboardComplete(int localClientNum, const wchar_t *text, unsigned int len)
    {
        int StoreTextLen = 1 + WideCharToMultiByte(CP_ACP, 0, text, len, NULL, 0, NULL, NULL);
        std::vector<char> StoreTextBuffer(StoreTextLen);
        WideCharToMultiByte(CP_ACP, 0, text, len, &StoreTextBuffer[0], StoreTextLen, NULL, NULL);
        char* StoreText = &StoreText[0];
        //...
    }
    
  • 使用std::wcsrtombs()函数:

    #include <cwchar>  
    void KeyboardComplete(int localClientNum, const wchar_t *text, unsigned int len)
    {
        std::mbstate_t state = std::mbstate_t();
        int StoreTextLen = 1 + std::wcsrtombs(NULL, &text, 0, &state);
        std::vector<char> StoreTextBuffer(StoreTextLen);
        std::wcsrtombs(&StoreTextBuffer[0], &text, StoreTextLen, &state);
        char *StoreText = &StoreTextBuffer[0];
        //...
    }
    
  • 使用std::wstring_convert类(C++11及更高版本):

    #include <locale>
    void KeyboardComplete(int localClientNum, const wchar_t *text, unsigned int len)
    {
        std::wstring_convert<std::codecvt<wchar_t, char, std::mbstate_t>> conv;
        std::string StoreTextBuffer = conv.to_bytes(text, text+len);
        char *StoreText = &StoreTextBuffer[0];
        //...
    }
    
  • 使用来自ICONV或ICU库的类似转换。

首先,对于字符串,应该使用std::wstring/std::string而不是原始指针。

C++11语言环境(http://en.cppreference.com/w/cpp/locale)库可以用于将宽字符串转换为窄字符串。

我在下面写了一个包装器函数,并使用了多年。希望这对你也有帮助。

#include <string>
#include <locale>
#include <codecvt>
std::string WstringToString(const std::wstring & wstr, const std::locale & loc /*= std::locale()*/)
{
    std::string buf(wstr.size(), 0);
    std::use_facet<std::ctype<wchar_t>>(loc).narrow(wstr.c_str(), wstr.c_str() + wstr.size(), '?', &buf[0]);
    return buf;
}

wchar_t是一个宽字符。它通常是每个字符16或32位,但这取决于系统。

char是一个很好的ol’CHAR_BIT大小的数据类型。同样,它有多大取决于系统。很可能是一个字节,但我想不出CHAR_BIT不能是16或32位的原因,使其与wchar_t大小相同。

如果它们的大小不同,那么直接分配就注定要失败。例如,对于16位wchar_t中的每1个字符,8位char将看到2个字符,并且很可能看到2个完全不相关的字符。这会很糟糕。

其次,即使它们大小相同,也可能有不同的编码。例如,分配给字母"A"的数值对于charwchar_t可能不同。在CCD_ 21和CCD_ 22中分别为65和16640。

为了在不同的数据类型中有任何意义,CCD_ 23和CCD_。std::wstring_convert通常会为您执行此翻译,但请查看语言环境库以了解更复杂的翻译。两者都需要一个支持C++11或更好版本的编译器。在以前的C++标准中,一小部分函数提供了转换支持。第三方库(如Boost::locale)有助于统一并提供更广泛的支持。

转换功能由操作系统提供,用于在OS使用的编码和其他常见编码之间进行转换。

您必须执行强制转换,您可以执行以下操作:

char* StoreText = (char*)text;

我认为这可能奏效。

但是您可以使用cstdlib库的wcstobbs函数。

char someText[12];
wcstombs(StoreText,text, 12);

最后一个参数大多数是指向的数组中可用的字节数。