string s = "おはよう";
wstring ws = FUNCTION(s, ws);
我如何将s的内容分配给ws?
搜索谷歌,并使用了一些技巧,但他们不能分配确切的内容。内容失真。
"おはよう"
系统编码的字符串?
string s = "おはよう";
wstring ws = FUNCTION(s, ws);
我如何将s的内容分配给ws?
搜索谷歌,并使用了一些技巧,但他们不能分配确切的内容。内容失真。
"おはよう"
系统编码的字符串?
Answers:
假设示例(おはよう)中的输入字符串是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
此答案中的解决方案是安全且可移植的。
std::codecvt_utf8
为初学者提供一个例子
<codecvt>
自C ++ 17起不推荐使用。
int StringToWString(std::wstring &ws, const std::string &s)
{
std::wstring wsTmp(s.begin(), s.end());
ws = wsTmp;
return 0;
}
您的问题未指定。严格来说,该示例是语法错误。但是,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.
setlocale
或调整编译器标志。我不知道,因为我不使用Windows,但这就是为什么它不常见的原因。如果可能,请考虑其他答案。
std::string ws(s.size()); ws.resize(mbstowcs(&ws[0], s.c_str(), s.size());
RAII FTW
仅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);
}
vector
。只需保留字符串中的字符wstring strW(charsNeeded + 1);
,然后将其用作转换缓冲区:&strW[0]
。最后,通过执行以下操作确保转换后存在最后一个nullstrW[charsNeeded] = 0;
如果您使用的是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());
您可以指定一个代码页,甚至可以指定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 on Software的有趣文章:每个软件开发人员绝对,肯定地必须绝对了解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)
编辑: 那么,根据这篇文章的文章乔尔似乎是:“兼具娱乐,它是实际的技术细节很轻”。文章:每个程序员绝对肯定要了解与文本一起使用的编码和字符集。
char* str = "hello worlddd"; wstring wstr (str, str+strlen(str));
这是一种组合方式string
,wstring
并将字符串常量混合到wstring
。使用wstringstream
该类。
这不适用于多字节字符编码。这只是丢弃类型安全性并将std :: string的7位字符扩展为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();
string
存储1个字节的字符并wstring
存储2个字节的字符。像utf8这样的东西会将多字节字符存储为一系列1字节值,即在string
。中。字符串类对编码没有帮助。我不是用c ++编码类的专家。
std::string
为的每个字符的低7位的愚蠢方法std:wstring
。仅当您具有7位ASCII字符串并且需要调用需要宽字符串的API时,此功能才有用。如果您需要更高级的功能,请访问stackoverflow.com/a/8969776/3258851。
从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字符时才有效。
atlconv.h
。检查其他答案。
它的这种变体是我在现实生活中最喜欢的。它将输入(如果它是有效的 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;
}
}
如果您有QT,并且懒于实现功能和东西,则可以使用
std :: string str; QString(str).toStdWString()
QString
,因为QString
构造器由于某种原因不能接受字符串。
方法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;
}
根据我自己的测试(在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宏之后-请勿将循环用于同一功能的循环或递归循环-最好尽快返回,因此堆栈将免于临时转换。
串到串
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);
}
string s = "おはよう";
是一个错误。
您应该直接使用wstring:
wstring ws = L"おはよう";
使用此代码将您的字符串转换为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;
}
CP_ACP
无疑是错误的论点。突然之间,正在执行的线程的环境状态会影响代码的行为。不建议。在转换中指定固定的字符编码。(并考虑处理错误。)
strings
接受> 8位字符。它已经用UTF-8编码了吗?