web-dev-qa-db-ja.com

「通常の」std :: stringをutf-8に変換する

あまりにも多くの事実上の誤りなしにこれを説明できるか見てみましょう...

文字列クラスを作成していて、内部ストレージとしてutf-8(std :: stringに保存されている)を使用したいと考えています。 「通常」のstd::stringstd::wstringの両方を入力と出力として使用できるようにしたい。

Std :: wstringでの作業は問題ありません。std::codecvt_utf8<wchar_t>を使用して、std :: wstringとの間で変換できます。

ただし、SOを広範囲にグーグル検索した後、「通常/デフォルト」のC++ std :: string(Windowsではローカルシステムのローカリゼーションを使用していると想定しています)の間で変換する方法をまだ見つけていません?)とutf-8 std :: string。

1つのオプションは、最初にstd::codecvt<wchar_t, char>を使用してstd :: stringをstd :: wstringに変換してから、上記のようにutf-8に変換することですが、少なくとも最初の128個の値を考えると、これはかなり非効率的です私が正しく理解していれば、ローカライズに関係なく、charの変換は変換せずにutf-8に直接変換されるはずです。

私はこの同様の質問を見つけました: C++:ASCIIまたはANSIをUTF8に変換してstd :: stringに保存する方法 私はその答えに少し懐疑的ですがラテン語1にハードコーディングされているので、これをすべての種類のローカリゼーションで安全に機能させる必要があります。

ブーストの感謝に関する答えはありません。コードベースを機能させるために頭痛の種を抱えたくありません。

15
DaedalusAlpha

「通常の文字列」がシステムのコードページを使用してエンコードされていて、それをUTF-8に変換したい場合、これは機能するはずです。

std::string codepage_str;
int size = MultiByteToWideChar(CP_ACP, MB_COMPOSITE, codepage_str.c_str(),
                               codepage_str.length(), nullptr, 0);
std::wstring utf16_str(size, '\0');
MultiByteToWideChar(CP_ACP, MB_COMPOSITE, codepage_str.c_str(),
                    codepage_str.length(), &utf16_str[0], size);

int utf8_size = WideCharToMultiByte(CP_UTF8, 0, utf16_str.c_str(),
                                    utf16_str.length(), nullptr, 0,
                                    nullptr, nullptr);
std::string utf8_str(utf8_size, '\0');
WideCharToMultiByte(CP_UTF8, 0, utf16_str.c_str(),
                    utf16_str.length(), &utf8_str[0], utf8_size,
                    nullptr, nullptr);
18
Simple