web-dev-qa-db-ja.com

MultiByteToWideCharを使用するにはどうすればよいですか?

通常のstringwstringに変換したい。このため、私はWindows API関数 MultiByteToWideChar を使用しようとしています。しかし、私にはうまくいきません。

これが私がやったことです:

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

最後の行でコンパイラエラーが発生します。

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

このエラーを修正するにはどうすればよいですか?

また、引数cchWideCharの値はどうあるべきですか? 0は大丈夫ですか?

24
Suhail Gupta

MultiByteToWideCharを2回呼び出す必要があります。

  1. MultiByteToWideCharの最初の呼び出しは、ワイド文字列に必要なバッファーサイズを見つけるために使用されます。 Microsoftのドキュメントをご覧ください ;それは述べています:

    関数が成功し、cchWideCharが0の場合、戻り値は、lpWideCharStrで示されるバッファーに必要な文字数です。 。

    したがって、MultiByteToWideCharに必要なサイズを与えるには、最後のパラメーターcchWideCharの値として0を渡します。また、その前のNULLとしてlpWideCharStrを渡す必要があります。

  2. 前の手順のバッファーサイズを使用して、ワイド文字列を収容するのに十分な大きさの非constバッファーを取得します。このバッファを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;

また、cbMultiByte引数として-1を使用していることに注意してください。これにより、結果の文字列がnullで終了し、それらを処理する必要がなくなります。

41
eran

これについての2番目の質問、今朝!

WideCharToMultiByte()とMultiByteToWideChar()を使用するのは面倒です。各変換にはルーチンへの2つの呼び出しが必要であり、メモリの割り当て/解放を行い、文字列が正しく終了していることを確認する必要があります。ラッパーが必要です!

私のブログには便利なC++ラッパー here があります。

これが他の 質問 今朝です

1
ravenspoint

以下の解決策を試すことができます。私はテストし、動作し、特殊文字を検出し(例:ºäçá)、Windows XP、Windows 2000 SP4以降、Windows 7、8、8.1および10で動作します。代わりにstd::wstringを使用new wchar_t/delete、リークリソース、オーバーフローバッファー、破損ヒープの問題を減らします。

dwFlagsMB_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();
}
1
Nix

いくつかの一般的な変換:

#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;
}
0
stax76

この関数は、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 ); 
0
Puppy