240

問題は、wstring を文字列に変換する方法です。

次の例があります:

#include <string>
#include <iostream>

int main()
{
    std::wstring ws = L"Hello";
    std::string s( ws.begin(), ws.end() );

  //std::cout <<"std::string =     "<<s<<std::endl;
    std::wcout<<"std::wstring =    "<<ws<<std::endl;
    std::cout <<"std::string =     "<<s<<std::endl;
}

コメントアウトされた行の出力は次のとおりです。

std::string =     Hello
std::wstring =    Hello
std::string =     Hello

ただし、なしは次のとおりです。

std::wstring =    Hello

例に何か問題がありますか?上記のように変換できますか?

編集

新しい例(いくつかの回答を考慮して)は

#include <string>
#include <iostream>
#include <sstream>
#include <locale>

int main()
{
    setlocale(LC_CTYPE, "");

    const std::wstring ws = L"Hello";
    const std::string s( ws.begin(), ws.end() );

    std::cout<<"std::string =     "<<s<<std::endl;
    std::wcout<<"std::wstring =    "<<ws<<std::endl;

    std::stringstream ss;
    ss << ws.c_str();
    std::cout<<"std::stringstream =     "<<ss.str()<<std::endl;
}

出力は次のとおりです。

std::string =     Hello
std::wstring =    Hello
std::stringstream =     0x860283c

したがって、stringstream を使用して wstring を文字列に変換することはできません。

4

18 に答える 18

361

コメントの 1 つで Cubbi が指摘したように、std::wstring_convert(C++11) はすっきりとしたシンプルなソリューションを提供します (および する必要が#include <locale>あります<codecvt>)。

std::wstring string_to_convert;

//setup converter
using convert_type = std::codecvt_utf8<wchar_t>;
std::wstring_convert<convert_type, wchar_t> converter;

//use converter (.to_bytes: wstr->str, .from_bytes: str->wstr)
std::string converted_str = converter.to_bytes( string_to_convert );

wcstombsこれに遭遇する前に、メモリの面倒な割り当て/割り当て解除の組み合わせを使用していました。

http://en.cppreference.com/w/cpp/locale/wstring_convert

更新(2013.11.28)

1つのライナーは次のように述べることができます(Gussのコメントに感謝します):

std::wstring str = std::wstring_convert<std::codecvt_utf8<wchar_t>>().from_bytes("some string");

ラッパー関数は次のように記述できます: (ArmanSchwarz さん、コメントありがとうございます)

std::wstring s2ws(const std::string& str)
{
    using convert_typeX = std::codecvt_utf8<wchar_t>;
    std::wstring_convert<convert_typeX, wchar_t> converterX;

    return converterX.from_bytes(str);
}

std::string ws2s(const std::wstring& wstr)
{
    using convert_typeX = std::codecvt_utf8<wchar_t>;
    std::wstring_convert<convert_typeX, wchar_t> converterX;

    return converterX.to_bytes(wstr);
}

注: string/wstringを関数に参照として渡すかリテラルとして渡すかについては、いくつかの論争があります (C++11 とコンパイラの更新のため)。決定は実装者に任せますが、知っておく価値はあります。

注:std::codecvt_utf8上記のコードで使用していますが、UTF-8 を使用していない場合は、使用している適切なエンコーディングに変更する必要があります。

http://en.cppreference.com/w/cpp/header/codecvt

于 2013-08-22T07:57:20.553 に答える
153
于 2012-08-23T18:18:29.473 に答える
35

これは、他の提案に基づいた解決策です。

#include <string>
#include <iostream>
#include <clocale>
#include <locale>
#include <vector>

int main() {
  std::setlocale(LC_ALL, "");
  const std::wstring ws = L"ħëłlö";
  const std::locale locale("");
  typedef std::codecvt<wchar_t, char, std::mbstate_t> converter_type;
  const converter_type& converter = std::use_facet<converter_type>(locale);
  std::vector<char> to(ws.length() * converter.max_length());
  std::mbstate_t state;
  const wchar_t* from_next;
  char* to_next;
  const converter_type::result result = converter.out(state, ws.data(), ws.data() + ws.length(), from_next, &to[0], &to[0] + to.size(), to_next);
  if (result == converter_type::ok or result == converter_type::noconv) {
    const std::string s(&to[0], to_next);
    std::cout <<"std::string =     "<<s<<std::endl;
  }
}

これは通常、Linux では機能しますが、Windows では問題が発生します。

于 2011-01-26T14:06:15.567 に答える
12

ロケールとそのすべての凝ったものを含める代わりに、FACTについて知っている場合は、文字列が変換可能である場合は、次のようにします。

#include <iostream>
#include <string>

using namespace std;

int main()
{
  wstring w(L"bla");
  string result;
  for(char x : w)
    result += x;

  cout << result << '\n';
}

ここでの実例

于 2012-07-21T02:35:22.053 に答える
7

コードには2つの問題があります。

  1. const std::string s( ws.begin(), ws.end() );ワイド文字をナロー文字に正しくマップするために、の変換は必要ありません。ほとんどの場合、各ワイド文字はに型キャストされcharます。
    この問題の解決策は、kemによる回答narrowですでに示され、ロケールのctypeファセットの機能が含まれています。

  2. 同じプログラムの両方std::coutに出力を書き込んでいます。とはstd::wcout両方とも同じストリーム()に関連付けられており、同じストリームをバイト指向のストリーム(のように)とワイド指向のストリーム(のように)の両方として使用した結果は定義されていません。 最良のオプションは、狭い出力と広い出力を同じ(基になる)ストリームに混合しないようにすることです。//の場合、ワイド出力とナロー出力を切り替えるときに方向を切り替えてみることができます(またはその逆)。coutwcoutstdoutcoutwcout
    stdoutcoutwcoutstdout

    #include <iostream>
    #include <stdio.h>
    #include <wchar.h>
    
    int main() {
        std::cout << "narrow" << std::endl;
        fwide(stdout, 1); // switch to wide
        std::wcout << L"wide" << std::endl;
        fwide(stdout, -1); // switch to narrow
        std::cout << "narrow" << std::endl;
        fwide(stdout, 1); // switch to wide
        std::wcout << L"wide" << std::endl;
    }
    
于 2011-01-26T13:33:26.810 に答える
7

次のように、公式の方法はまだcodecvtファセットを通過することだと思います(ある種のロケール対応の翻訳が必要です)。

resultCode = use_facet<codecvt<char, wchar_t, ConversionState> >(locale).
  in(stateVar, scratchbuffer, scratchbufferEnd, from, to, toLimit, curPtr);

またはそのようなもの、私は横たわっている作業コードを持っていません。しかし、最近何人の人がその機械を使用しているのか、どれだけの人が単にメモリへのポインターを要求し、ICU や他のライブラリに面倒な詳細を処理させているのかはわかりません。

于 2011-01-26T12:11:29.953 に答える
6

この回答を書いている時点で、「convert string wstring」の一番の Google 検索でこのページにたどり着きます。私の答えは、文字列を wstring に変換する方法を示していますが、これは実際の質問ではありません。おそらくこの答えを削除する必要がありますが、それは悪い形式と見なされます。この StackOverflow answer にジャンプすることをお勧めします。これは現在、このページより上位にランクされています。


文字列、wstring、および混合文字列定数を 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();
于 2011-07-19T22:48:18.480 に答える
6

ctypeファセットのnarrowメソッドを直接使用することもできます:

#include <clocale>
#include <ロケール>
#include <文字列>
#include <ベクター>

インライン std::string ナロー(std::wstring const& text)
{
    std::locale const loc("");
    wchar_t const* from = text.c_str();
    std::size_t const len = text.size();
    std::vector<char> buffer(len + 1);
    std::use_facet<std::ctype<wchar_t> >(loc).narrow(from, from + len, '_', &buffer[0]);
    return std::string(&buffer[0], &buffer[len]);
}
于 2011-11-07T21:58:53.523 に答える
4

このソリューションはdk123 のソリューションに触発されていますが、ロケール依存の codecvt ファセットを使用しています。結果は、UTF-8 ではなく、ロケールでエンコードされた文字列になります (ロケールとして設定されていない場合)。

std::string w2s(const std::wstring &var)
{
   static std::locale loc("");
   auto &facet = std::use_facet<std::codecvt<wchar_t, char, std::mbstate_t>>(loc);
   return std::wstring_convert<std::remove_reference<decltype(facet)>::type, wchar_t>(&facet).to_bytes(var);
}

std::wstring s2w(const std::string &var)
{
   static std::locale loc("");
   auto &facet = std::use_facet<std::codecvt<wchar_t, char, std::mbstate_t>>(loc);
   return std::wstring_convert<std::remove_reference<decltype(facet)>::type, wchar_t>(&facet).from_bytes(var);
}

探していたのですが、見つかりません。最後に、正しい型名を持つ関数をstd::locale使用することで、正しいファセットを取得できることがわかりました。std::use_facet()お役に立てれば。

于 2016-04-27T14:57:25.977 に答える
1

他の誰かが興味を持っている場合に備えて:stringまたはwstringが期待される場所ならどこでも交換可能に使用できるクラスが必要でした。dk123 のソリューションconvertible_stringに基づく次のクラスは、 、、またはのいずれかで初期化でき、またはによって割り当てられるか、または に暗黙的に変換されます(したがって、いずれかを取る関数に渡すことができます)。stringchar const*wstringwchar_t const*stringwstring

class convertible_string
{
public:
    // default ctor
    convertible_string()
    {}

    /* conversion ctors */
    convertible_string(std::string const& value) : value_(value)
    {}
    convertible_string(char const* val_array) : value_(val_array)
    {}
    convertible_string(std::wstring const& wvalue) : value_(ws2s(wvalue))
    {}
    convertible_string(wchar_t const* wval_array) : value_(ws2s(std::wstring(wval_array)))
    {}

    /* assignment operators */
    convertible_string& operator=(std::string const& value)
    {
        value_ = value;
        return *this;
    }
    convertible_string& operator=(std::wstring const& wvalue)
    {
        value_ = ws2s(wvalue);
        return *this;
    }

    /* implicit conversion operators */
    operator std::string() const { return value_; }
    operator std::wstring() const { return s2ws(value_); }
private:
    std::string value_;
};
于 2015-08-31T17:53:24.337 に答える