C++ 如何使用 MultiByteToWideChar?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6693010/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 20:33:09  来源:igfitidea点击:

How do I use MultiByteToWideChar?

c++winapivisual-c++character-encoding

提问by Suhail Gupta

I want to convert a normal stringto a wstring. For this, I am trying to use the Windows API function MultiByteToWideChar. But it does not work for me.

我想将法线转换stringwstring. 为此,我正在尝试使用 Windows API 函数MultiByteToWideChar。但它对我不起作用。

Here is what I have done:

这是我所做的:

string x = "This is c++ not java";
wstring Wstring;
MultiByteToWideChar( CP_UTF8 , 0 , x.c_str() , x.size() , &Wstring , 0 ); 

The last line produces the compiler error:

最后一行产生编译器错误:

'MultiByteToWideChar' : cannot convert parameter 5 from 'std::wstring *' to 'LPWSTR'

How do I fix this error?

我该如何解决这个错误?

Also, what should be the value of the argument cchWideChar? Is 0 okay?

另外,参数的值应该是cchWideChar多少?0好吗?

回答by eran

You must call MultiByteToWideChartwice:

您必须调用MultiByteToWideChar两次:

  1. The first call to MultiByteToWideCharis used to find the buffer size you need for the wide string. Look at Microsoft's documentation; it states:

    If the function succeeds and cchWideCharis 0, the return value is the required size, in characters, for the buffer indicated by lpWideCharStr.

    Thus, to make MultiByteToWideChargive you the required size, pass 0 as the value of the last parameter, cchWideChar. You should also pass NULLas the one before it, lpWideCharStr.

  2. Obtain a non-const buffer large enough to accommodate the wide string, using the buffer size from the previous step. Pass this buffer to another call to MultiByteToWideChar. And this time, the last argument should be the actual size of the buffer, not 0.

  1. 第一次调用MultiByteToWideChar用于查找宽字符串所需的缓冲区大小。查看微软的文档;它指出:

    如果函数成功并且cchWideChar为 0,则返回值是lpWideCharStr指示的缓冲区所需的大小(以字符为单位)

    因此,为了使MultiByteToWideChar您获得所需的大小,请将 0 作为最后一个参数的值传递给cchWideChar. 你也应该通过NULL它之前的那个,lpWideCharStr.

  2. 使用上一步中的缓冲区大小,获取足够大以容纳宽字符串的非常量缓冲区。将此缓冲区传递给另一个调用MultiByteToWideChar. 而这一次,最后一个参数应该是缓冲区的实际大小,而不是 0。

A sketchy example:

一个粗略的例子:

int wchars_num = MultiByteToWideChar( CP_UTF8 , 0 , x.c_str() , -1, NULL , 0 );
wchar_t* wstr = new wchar_t[wchars_num];
MultiByteToWideChar( CP_UTF8 , 0 , x.c_str() , -1, wstr , wchars_num );
// do whatever with wstr
delete[] wstr;

Also, note the use of -1 as the cbMultiByteargument. This will make the resulting string null-terminated, saving you from dealing with them.

另外,请注意使用 -1 作为cbMultiByte参数。这将使结果字符串以空字符结尾,从而避免您处理它们。

回答by ravenspoint

Second question about this, this morning!

关于这个的第二个问题,今天早上!

WideCharToMultiByte() and MultiByteToWideChar() are a pain to use. Each conversion requires two calls to the routines and you have to look after allocating/freeing memory and making sure the strings are correctly terminated. You need a wrapper!

WideCharToMultiByte() 和 MultiByteToWideChar() 使用起来很痛苦。每次转换都需要对例程进行两次调用,您必须注意分配/释放内存并确保字符串正确终止。你需要一个包装!

I have a convenient C++ wrapper on my blog, here, which you are welcome to use.

我的博客上有一个方便的 C++ 包装器,这里,欢迎您使用。

Here's the other questionthis morning

这是今天早上的另一个问题

回答by Nix

You can try this solution below. I tested, it works, detect special characters (example: o ? ? á ) and works on Windows XP, Windows 2000 with SP4 and later, Windows 7, 8, 8.1 and 10. Using std::wstringinstead new wchar_t/ delete, we reduce problems with leak resources, overflow buffer and corrupt heap.

您可以在下面尝试此解决方案。我测试过,它可以工作,检测特殊字符(例如:o ? ? á )并且可以在 Windows XP、Windows 2000 SP4 及更高版本、Windows 7、8、8.1 和 10 上运行。使用/std::wstring代替,我们减少了泄漏资源的问题,溢出缓冲区和损坏的堆。new wchar_tdelete

dwFlagswas set to MB_ERR_INVALID_CHARSto works on Windows 2000 with SP4 and later, Windows XP. If this flag is not set, the function silently drops illegal code points.

dwFlags被设置为MB_ERR_INVALID_CHARS在 Windows 2000 SP4 和更高版本的 Windows XP 上工作。如果未设置此标志,则该函数会静默删除非法代码点。

std::wstring ConvertStringToWstring(const std::string &str)
{
    if (str.empty())
    {
        return std::wstring();
    }
    int num_chars = MultiByteToWideChar(CP_ACP, MB_ERR_INVALID_CHARS, str.c_str(), str.length(), NULL, 0);
    std::wstring wstrTo;
    if (num_chars)
    {
        wstrTo.resize(num_chars);
        if (MultiByteToWideChar(CP_ACP, MB_ERR_INVALID_CHARS, str.c_str(), str.length(), &wstrTo[0], num_chars))
        {
            return wstrTo;
        }
    }
    return std::wstring();
}

回答by stax76

Few common conversions:

几个常见的转换:

#define WIN32_LEAN_AND_MEAN

#include <Windows.h>

#include <string>

std::string ConvertWideToANSI(const std::wstring& wstr)
{
    int count = WideCharToMultiByte(CP_ACP, 0, wstr.c_str(), wstr.length(), NULL, 0, NULL, NULL);
    std::string str(count, 0);
    WideCharToMultiByte(CP_ACP, 0, wstr.c_str(), -1, &str[0], count, NULL, NULL);
    return str;
}

std::wstring ConvertAnsiToWide(const std::string& str)
{
    int count = MultiByteToWideChar(CP_ACP, 0, str.c_str(), str.length(), NULL, 0);
    std::wstring wstr(count, 0);
    MultiByteToWideChar(CP_ACP, 0, str.c_str(), str.length(), &wstr[0], count);
    return wstr;
}

std::string ConvertWideToUtf8(const std::wstring& wstr)
{
    int count = WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), wstr.length(), NULL, 0, NULL, NULL);
    std::string str(count, 0);
    WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), -1, &str[0], count, NULL, NULL);
    return str;
}

std::wstring ConvertUtf8ToWide(const std::string& str)
{
    int count = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), str.length(), NULL, 0);
    std::wstring wstr(count, 0);
    MultiByteToWideChar(CP_UTF8, 0, str.c_str(), str.length(), &wstr[0], count);
    return wstr;
}

回答by Puppy

The function cannot take a pointer to a C++ string. It will expect a pointer to a buffer of wide characters of sufficient size- you must allocate this buffer yourself.

该函数不能采用指向 C++ 字符串的指针。它将需要一个指向足够大小的宽字符缓冲区的指针 - 您必须自己分配此缓冲区。

string x = "This is c++ not java";
wstring Wstring;
Wstring.resize(x.size());
int c =  MultiByteToWideChar( CP_UTF8 , 0 , x.c_str() , x.size() , &Wstring[0], 0 );