C++ 如何使用MultiByteToWideChar?

C++ 如何使用MultiByteToWideChar?,c++,winapi,visual-c++,character-encoding,C++,Winapi,Visual C++,Character Encoding,我想将普通的字符串转换为wstring。为此,我尝试使用WindowsAPI函数。 但这对我不起作用 以下是我所做的: string x = "This is c++ not java"; wstring Wstring; MultiByteToWideChar( CP_UTF8 , 0 , x.c_str() , x.size() , &Wstring , 0 ); 最后一行生成编译器错误: 'MultiByteToWideChar':无法将参数5从'std::wstring*'转

我想将普通的
字符串
转换为
wstring
。为此,我尝试使用WindowsAPI函数。 但这对我不起作用

以下是我所做的:

string x = "This is c++ not java";
wstring Wstring;
MultiByteToWideChar( CP_UTF8 , 0 , x.c_str() , x.size() , &Wstring , 0 ); 
最后一行生成编译器错误:

'MultiByteToWideChar':无法将参数5从'std::wstring*'转换为'LPWSTR'
如何修复此错误


另外,参数
cchWideChar
的值应该是多少?0是吗?< /P> < P>函数不能接受指向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 ); 

您必须调用
MultiByteToWideChar
两次:


  • 第一次调用
    MultiByteToWideChar
    用于查找宽字符串所需的缓冲区大小。看看它说:

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


    因此,要使
    MultiByteToWideChar
    为您提供所需的大小,请将0作为最后一个参数
    cchWideChar
    的值传递。您还应该将
    NULL
    作为前面的传递,
    lpWideCharStr


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

  • 一个粗略的例子:

    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;
    

    另外,请注意使用-1作为
    cbMultiByte
    参数。这将使生成的字符串以null结尾,从而避免您处理这些字符串。

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

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

    <>我在博客上有一个方便的C++包装,欢迎使用。
    这是今天早上的另一个

    您可以尝试下面的解决方案。我测试了它,它可以工作,可以检测特殊字符(例如:ºäçá),可以在Windows XP、带有SP4的Windows 2000以及更高版本的Windows 7、8、8.1和10上工作。 使用
    std::wstring
    代替
    new wchar\u t
    /
    delete
    ,我们减少了资源泄漏、缓冲区溢出和堆损坏的问题

    dwFlags
    被设置为
    MB_ERR_INVALID_CHARS
    以在使用SP4的Windows 2000和更高版本的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();
    }
    

    几个常见的转换:

    #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;
    }
    
    #定义WIN32_LEAN_和_MEAN
    #包括
    #包括
    std::string ConvertWideToANSI(常量std::wstring&wstr)
    {
    int count=WideCharToMultiByte(CP_ACP,0,wstr.c_str(),wstr.length(),NULL,0,NULL,NULL);
    std::字符串str(计数,0);
    WideChartMultiByte(CP_ACP,0,wstr.c_str(),-1,&str[0],count,NULL,NULL);
    返回str;
    }
    std::wstring convertansitowed(const std::string&str)
    {
    int count=MultiByteToWideChar(CP_ACP,0,str.c_str(),str.length(),NULL,0);
    std::wstring wstr(计数,0);
    MultiByteToWideChar(CP_ACP,0,str.c_str(),str.length(),&wstr[0],count);
    返回wstr;
    }
    std::string ConvertWideToUtf8(常量std::wstring&wstr)
    {
    int count=WideCharToMultiByte(CP_UTF8,0,wstr.c_str(),wstr.length(),NULL,0,NULL,NULL);
    std::字符串str(计数,0);
    WideChartMultiByte(CP_UTF8,0,wstr.c_str(),-1,&str[0],count,NULL,NULL);
    返回str;
    }
    std::wstring ConvertUtf8ToWide(常量std::string&str)
    {
    int count=MultiByteToWideChar(CP_UTF8,0,str.c_str(),str.length(),NULL,0);
    std::wstring wstr(计数,0);
    MultiByteToWideChar(CP_UTF8,0,str.c_str(),str.length(),&wstr[0],count);
    返回wstr;
    }
    
    您不能将指向
    std::wstring
    的指针传递给此函数。+1用于强调需要两次调用MultiByteToWideChar,这对于字符集转换函数是必不可少的。@eran
    wchar\u t*
    LPTSTR
    之间有什么区别?@Suhail Gupta,如果您是用Unicode编译的,那就完全一样了。在多字节构建中,LPTSTR将扩展为常规的
    char*
    。使用这些宏可以创建Unicode和非Unicode版本。不过,我现在想不出有什么理由这么做,因为Unicode现在是VS中的默认值,所以请使用其中任何一个。OWCH!没有免费的东西,即使有,我也不会宽恕这种代码。使用适当调整大小的
    std::vector
    。@DeadMG-Owch确实。。。这就是为什么我说它是粗略的。他很匆忙。修复了答案,谢谢。
    MultiByteToWideChar
    需要类型为
    wchar\u t*
    的参数。Wstring的类型为
    std::Wstring
    ——因此无法将其传递给
    MultiByteToWideChar
    (甚至连指向它的指针都没有)。但好消息是,
    std::wstring
    在内部将其数据存储为
    wchar\u t*
    ,并提供两个函数来访问此内部数据:
    data()
    (此处使用)和
    c_str()
    @DeadMG,请注意wstring.data()返回常量wchar\u t*,根据cpluplus.com的说法,不应该直接修改(你可能比我更清楚这样做的效果)。OTOH,MBTWC的最后一个参数是0,无论如何都不会在该缓冲区中放置任何东西…@eran:Oops,关于返回值是
    const
    ,您完全正确。它不能以这种方式工作,WSString使用32位字符,而win32使用16位unicode字符。。。