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

我如何将 s 的内容分配给 ws?

搜索谷歌并使用了一些技术,但他们无法分配确切的内容。内容失真。

4

19 回答 19

275

假设您的示例中的输入字符串 (おはよう) 是 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 之间进行转换可能会在不同平台上产生意想不到的结果差异. 为了获得更好的转换,请std::codecvt_utf8按照http://en.cppreference.com/w/cpp/locale/codecvt_utf8上的说明进行考虑

注意(新)

由于codecvt标头在 C++17 中已弃用,因此有人担心此答案中提出的解决方案。但是,C++ 标准委员会在http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0618r0.html中添加了一条重要声明说

该库组件应与附件 D 一起退出,直到合适的替代品标准化。

所以在可预见的未来,codecvt这个答案中的解决方案是安全便携的。

于 2013-09-03T16:39:48.520 回答
59
int StringToWString(std::wstring &ws, const std::string &s)
{
    std::wstring wsTmp(s.begin(), s.end());

    ws = wsTmp;

    return 0;
}
于 2012-01-23T09:54:13.157 回答
38

您的问题未详细说明。严格来说,该示例是语法错误。但是,mbstowcs可能是您正在寻找的。

它是一个 C 库函数并在缓冲区上运行,但这里有一个易于使用的习惯用法,由 Mooing Duck 提供:

std::wstring ws(s.size(), L' '); // Overestimate number of code points.
ws.resize(::mbstowcs_s(&ws[0], ws.size(), s.c_str(), s.size())); // Shrink to fit.
于 2010-04-04T07:42:29.133 回答
21

如果您使用的是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 转换为 string 的相同过程(有时您需要指定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());

您可以指定一个代码页,甚至是 UTF8(在使用JNI / Java时这非常好)。此答案中显示了将 std::wstring 转换为 utf8 std::string标准方法。

// 
// using ATL
CA2W ca2w(str, CP_UTF8);

// 
// or the standard way taken from the answer above
#include <codecvt>
#include <string>

// convert UTF-8 string to wstring
std::wstring utf8_to_wstring (const std::string& str) {
    std::wstring_convert<std::codecvt_utf8<wchar_t>> myconv;
    return myconv.from_bytes(str);
}

// convert wstring to UTF-8 string
std::string wstring_to_utf8 (const std::wstring& str) {
    std::wstring_convert<std::codecvt_utf8<wchar_t>> myconv;
    return myconv.to_bytes(str);
}

如果您想了解有关代码页的更多信息,请参阅Joel 关于软件的一篇有趣的文章:每个软件开发人员绝对、肯定必须了解 Unicode 和字符集的绝对最低要求

这些 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)

编辑: 嗯,根据这篇文章,乔尔的文章似乎是:“虽然很有趣,但它对实际技术细节的了解却很轻”。文章:每个程序员都绝对需要知道的关于编码和字符集以使用文本的知识。

于 2014-08-22T16:52:37.727 回答
20

Windows API only, pre C++11 implementation, in case someone needs it:

#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);
}
于 2014-11-13T17:14:27.507 回答
19

这是一种将string,wstring和混合字符串常量组合到wstring. 使用wstringstream类。

这不适用于多字节字符编码。这只是丢弃类型安全并将 7 位字符从 std::string 扩展为 std:wstring 每个字符的低 7 位的愚蠢方式。这仅在您有 7 位 ASCII 字符串并且需要调用需要宽字符串的 API 时才有用。

#include <sstream>

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

std::wstringstream cls;
cls << " abc " << narrow.c_str() << L" def " << wide.c_str();
std::wstring total= cls.str();
于 2015-06-01T18:34:37.947 回答
13

char*wstring:

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

stringwstring:

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

请注意,这仅在被转换的字符串仅包含 ASCII 字符时才有效。

于 2013-03-05T16:10:47.833 回答
9

使用 Boost.Locale:

ws = boost::locale::conv::utf_to_utf<wchar_t>(s);
于 2015-09-21T09:42:31.620 回答
8

它的这种变体是我在现实生活中的最爱。它将输入(如果它是有效的 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;
    }
}
于 2016-08-18T12:33:38.697 回答
4

您可以使用 boost 路径或 std 路径;这要容易得多。跨平台应用程序更容易提升路径

#include <boost/filesystem/path.hpp>

namespace fs = boost::filesystem;

//s to w
std::string s = "xxx";
auto w = fs::path(s).wstring();

//w to s
std::wstring w = L"xxx";
auto s = fs::path(w).string();

如果你喜欢使用标准:

#include <filesystem>
namespace fs = std::filesystem;

//The same

c++ 旧版本

#include <experimental/filesystem>
namespace fs = std::experimental::filesystem;

//The same

其中的代码仍然实现了一个转换器,您不必解开细节。

于 2021-06-08T04:55:34.010 回答
2

对我来说,没有大开销的最简单的选择是:

包括:

#include <atlbase.h>
#include <atlconv.h>

兑换:

char* whatever = "test1234";
std::wstring lwhatever = std::wstring(CA2W(std::string(whatever).c_str()));

如果需要的话:

lwhatever.c_str();
于 2021-11-30T11:04:56.030 回答
2

字符串到 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 到字符串

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);
}
于 2019-03-20T03:07:46.160 回答
2

如果你有 QT 并且如果你懒得实现一个你可以使用的函数和东西

std::string str;
QString(str).toStdWString()
于 2019-04-01T09:11:30.593 回答
2

std::string -> wchar_t[]具有安全mbstowcs_s功能:

auto ws = std::make_unique<wchar_t[]>(s.size() + 1);
mbstowcs_s(nullptr, ws.get(), s.size() + 1, s.c_str(), s.size());

这是来自我的示例代码

于 2020-08-21T09:18:11.600 回答
1

方法 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;
}
于 2013-09-03T15:57:04.703 回答
1

根据我自己的测试(在 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 );
}

但请注意,这些宏大量使用堆栈 - 不要对相同的函数使用 for 循环或递归循环 - 在使用 W2A 或 A2W 宏之后 - 最好尽快返回,因此堆栈将从临时转换中释放出来。

于 2015-10-26T21:06:51.590 回答
0

这是我的超级基本解决方案,可能不适用于所有人。但会为很多人工作。

它需要使用指南支持库。这是一个由许多 C++ 委员会作者设计的非常官方的 C++ 库:

    std::string to_string(std::wstring const & wStr)
    {
        std::string temp = {};

        for (wchar_t const & wCh : wStr)
        {
            // If the string can't be converted gsl::narrow will throw
            temp.push_back(gsl::narrow<char>(wCh));
        }

        return temp;
    }

我的所有功能都是尽可能允许转换。否则抛出异常。

通过使用 gsl::narrow ( https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#es49-if-you-must-use-a-cast-use-a-named-cast )

于 2020-12-13T20:24:43.653 回答
-1

使用此代码将您的字符串转换为 wstring

std::wstring string2wString(const std::string& s){
    int len;
    int slength = (int)s.length() + 1;
    len = MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, 0, 0); 
    wchar_t* buf = new wchar_t[len];
    MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, buf, len);
    std::wstring r(buf);
    delete[] buf;
    return r;
}

int main(){
    std::wstring str="your string";
    std::wstring wStr=string2wString(str);
    return 0;
}
于 2015-04-08T11:48:38.283 回答
-3

string s = "おはよう";是一个错误。

您应该直接使用 wstring:

wstring ws = L"おはよう";
于 2010-04-04T07:45:08.027 回答