web-dev-qa-db-ja.com

C ++文字列(またはchar *)をwstring(またはwchar_t *)に変換

string s = "おはよう";
wstring ws = FUNCTION(s, ws);

Sのコンテンツをwsにどのように割り当てますか?

グーグルを検索し、いくつかのテクニックを使用しましたが、正確なコンテンツを割り当てることはできません。コンテンツがゆがんでいます。

147
Samir

あなたの例の入力文字列(おはよう)はUTF-8でエンコードされていると仮定します(見た目ではそうではありませんが、この説明のためだと仮定しましょう:-))Unicode文字列の表現興味のある場合は、標準ライブラリ(C++ 11以降)だけで問題を完全に解決できます。

TL; DRバージョン:

#include <locale>
#include <codecvt>
#include <string>

std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
std::string narrow = converter.to_bytes(wide_utf16_source_string);
std::wstring wide = converter.from_bytes(narrow_utf8_source_string);

オンラインでコンパイルおよび実行可能な長い例:

(これらはすべて同じ例を示しています。冗長性のためだけに多数あります...)

注(古い)

コメントで指摘され、 https://stackoverflow.com/a/17106065/6345 で説明されているように、標準ライブラリを使用してUTF-8とUTF-16を変換すると予期しない結果が生じる場合があります異なるプラットフォームでの結果の違い。より良い変換のために、 http://en.cppreference.com/w/cpp/locale/codecvt_utf8 で説明されているようにstd::codecvt_utf8を検討してください

注(新規)

codecvtヘッダーはC++ 17で非推奨になったため、この回答で示された解決策についての懸念が提起されました。ただし、C++標準委員会は http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0618r0.html に重要な声明を追加しました

適切な代替品が標準化されるまで、このライブラリコンポーネントはとともに、付録Dで廃止する必要があります。

近い将来、この回答のcodecvtソリューションは安全で移植性があります。

205
Johann Gerell
int StringToWString(std::wstring &ws, const std::string &s)
{
    std::wstring wsTmp(s.begin(), s.end());

    ws = wsTmp;

    return 0;
}
44
Pietro M

あなたの質問は未指定です。厳密には、その例は構文エラーです。ただし、 std::mbstowcs がおそらく探しているものです。

これはCライブラリ関数であり、バッファで動作しますが、TBohne(以前のMooing Duck)の好意により、使いやすいイディオムがあります。

std::wstring ws(s.size(), L' '); // Overestimate number of code points.
ws.resize(std::mbstowcs(&ws[0], s.c_str(), s.size())); // Shrink to fit.
28
Potatoswatter

誰かがそれを必要とする場合に備えて、Windows APIのみ、C++ 11以前の実装:

#include <stdexcept>
#include <vector>
#include <windows.h>

using std::runtime_error;
using std::string;
using std::vector;
using std::wstring;

wstring utf8toUtf16(const string & str)
{
   if (str.empty())
      return wstring();

   size_t charsNeeded = ::MultiByteToWideChar(CP_UTF8, 0, 
      str.data(), (int)str.size(), NULL, 0);
   if (charsNeeded == 0)
      throw runtime_error("Failed converting UTF-8 string to UTF-16");

   vector<wchar_t> buffer(charsNeeded);
   int charsConverted = ::MultiByteToWideChar(CP_UTF8, 0, 
      str.data(), (int)str.size(), &buffer[0], buffer.size());
   if (charsConverted == 0)
      throw runtime_error("Failed converting UTF-8 string to UTF-16");

   return wstring(&buffer[0], charsConverted);
}
17
Alex Che

Windows/Visual Studioを使用していて、文字列をwstringに変換する必要がある場合は、次を使用できます。

#include <AtlBase.h>
#include <atlconv.h>
...
string s = "some string";
CA2W ca2w(s.c_str());
wstring w = ca2w;
printf("%s = %ls", s.c_str(), w.c_str());

Wstringを文字列に変換するための同じ手順(codepageを指定する必要がある場合があります):

#include <AtlBase.h>
#include <atlconv.h>
...
wstring w = L"some wstring";
CW2A cw2a(w.c_str());
string s = cw2a;
printf("%s = %ls", s.c_str(), w.c_str());

codepageとUTF8さえ指定できます(JNI/Java )。

CA2W ca2w(str, CP_UTF8);

codepagesについてもっと知りたい場合は、ソフトウェアに関するJoelの興味深い記事があります: ユニコードと文字セットについて絶対に、積極的に知っていなければならない絶対最小値

これらのCA2W(ANSIをWide = unicodeに変換)マクロは、 ATLおよびMFC文字列変換マクロ 、サンプルを含む)の一部です。

セキュリティ警告#4995 'を無効にする必要がある場合がありますが、他の回避策はわかりません(VS2012でWindowsXp用にコンパイルしたときに発生します)。

#pragma warning(Push)
#pragma warning(disable: 4995)
#include <AtlBase.h>
#include <atlconv.h>
#pragma warning(pop)

Edit:まあ、 この記事 によると、Joelの記事はこうです。 "。記事: すべてのプログラマーが、テキストを扱うためにエンコードと文字セットについて絶対に、積極的に知る必要があるもの

12
lmiguelmh

char*からwstringへ:

char* str = "hello worlddd";
wstring wstr (str, str+strlen(str));

stringからwstringへ:

string str = "hello worlddd";
wstring wstr (str.begin(), str.end());

これは、変換される文字列にASCII文字のみが含まれている場合にのみ機能することに注意してください。

10
Ghominejad

stringwstring、および混合文字列定数をwstringに結合する方法を次に示します。 wstringstreamクラスを使用します。

#include <sstream>

std::string narrow = "narrow";
std::wstring wide = "wide";

std::wstringstream cls;
cls << " abc " << narrow.c_str() << L" def " << wide.c_str();
std::wstring total= cls.str();
10
Mark Lakata

boost.Localeを使用:

ws = boost::locale::conv::utf_to_utf<wchar_t>(s);
6
vladon

それのこのバリアントは、実際の生活で私のお気に入りです。入力有効な場合 UTF-8をそれぞれのwstringに変換します。入力が破損している場合、wstringは単一バイトから構成されます。これは、入力データの品質を本当に確認できない場合に非常に役立ちます。

std::wstring convert(const std::string& input)
{
    try
    {
        std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
        return converter.from_bytes(input);
    }
    catch(std::range_error& e)
    {
        size_t length = input.length();
        std::wstring result;
        result.reserve(length);
        for(size_t i = 0; i < length; i++)
        {
            result.Push_back(input[i] & 0xFF);
        }
        return result;
    }
}
3
Matthias Ronge

メソッドs2wsはうまく機能します。希望が役立ちます。

std::wstring s2ws(const std::string& s) {
    std::string curLocale = setlocale(LC_ALL, ""); 
    const char* _Source = s.c_str();
    size_t _Dsize = mbstowcs(NULL, _Source, 0) + 1;
    wchar_t *_Dest = new wchar_t[_Dsize];
    wmemset(_Dest, 0, _Dsize);
    mbstowcs(_Dest,_Source,_Dsize);
    std::wstring result = _Dest;
    delete []_Dest;
    setlocale(LC_ALL, curLocale.c_str());
    return result;
}
1
hahakubile

私自身のテスト(windows 8、vs2010)に基づいて、mbstowcsは実際に元の文字列を損傷する可能性があり、ANSIコードページでのみ機能します。 MultiByteToWideChar/WideCharToMultiByteも文字列の破損を引き起こす可能性がありますが、知らない文字を「?」に置き換える傾向があります。疑問符ですが、mbstowcsは不明な文字に遭遇すると停止する傾向があり、その時点で文字列を切り取ります。 (フィンランド語のウィンドウでベトナム語の文字をテストしました)。

したがって、アナログANSI C関数よりもMulti * -windows API関数をお勧めします。

また、あるコードページから別のコードページに文字列をエンコードする最短の方法に気づいたのは、MultiByteToWideChar/WideCharToMultiByte API関数呼び出しを使用するのではなく、アナログATLマクロであるW2A/A2Wです。

したがって、上記のアナログ機能は次のように聞こえます。

wstring utf8toUtf16(const string & str)
{
   USES_CONVERSION;
   _acp = CP_UTF8;
   return A2W( str.c_str() );
}

_acpはUSES_CONVERSIONマクロで宣言されています。

または、古いデータから新しいデータへの変換を実行するときによく見逃す機能もあります。

string ansi2utf8( const string& s )
{
   USES_CONVERSION;
   _acp = CP_ACP;
   wchar_t* pw = A2W( s.c_str() );

   _acp = CP_UTF8;
   return W2A( pw );
}

しかし、これらのマクロは重度のスタックを使用していることに注意してください-同じ関数のループや再帰ループには使用しないでください-W2AまたはA2Wマクロを使用した後-ASAPを返す方がよいため、スタックは一時的な変換から解放されます。

1
TarmoPikaro

文字列からwstring

std::wstring Str2Wstr(const std::string& str)
{
    int size_needed = MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), NULL, 0);
    std::wstring wstrTo(size_needed, 0);
    MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), &wstrTo[0], size_needed);
    return wstrTo;
}

wstringからString

std::string Wstr2Str(const std::wstring& wstr)
{
    typedef std::codecvt_utf8<wchar_t> convert_typeX;
    std::wstring_convert<convert_typeX, wchar_t> converterX;
    return converterX.to_bytes(wstr);
}
1

QTを使用していて、関数やものを実装するのが面倒な場合は、

std :: string str; QString(str).toStdWString()

0