string s = "おはよう";
wstring ws = FUNCTION(s, ws);
ฉันจะกำหนดเนื้อหาของ s ให้กับ ws ได้อย่างไร
ค้นหา google และใช้เทคนิคบางอย่าง แต่ไม่สามารถกำหนดเนื้อหาที่แน่นอนได้ เนื้อหาผิดเพี้ยน
"おはよう"
สตริงเข้ารหัสระบบ
string s = "おはよう";
wstring ws = FUNCTION(s, ws);
ฉันจะกำหนดเนื้อหาของ s ให้กับ ws ได้อย่างไร
ค้นหา google และใช้เทคนิคบางอย่าง แต่ไม่สามารถกำหนดเนื้อหาที่แน่นอนได้ เนื้อหาผิดเพี้ยน
"おはよう"
สตริงเข้ารหัสระบบ
คำตอบ:
สมมติว่าสตริงอินพุตในตัวอย่างของคุณ (おはよう) เป็น 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-library และทำงานกับบัฟเฟอร์ แต่นี่เป็นสำนวนที่ใช้งานง่ายโดยได้รับความอนุเคราะห์จาก 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());
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]
สุดท้ายให้แน่ใจ null สุดท้ายคือปัจจุบันหลังจากการแปลงโดยการทำstrW[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 เป็นสตริง (บางครั้งคุณจะต้องระบุเพจรหัส ):
#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 ) มาตรฐานวิธีการแปลงมาตรฐาน :: wstring เพื่อ utf8 มาตรฐาน :: สตริงแสดงให้เห็นในคำตอบนี้
//
// 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);
}
หากคุณต้องการทราบข้อมูลเพิ่มเติมเกี่ยวกับcodepagesมีบทความที่น่าสนใจเกี่ยวกับโจเอลซอฟแวร์: แน่นอนทุกขั้นต่ำของผู้พัฒนาซอฟท์แวแน่นอนบวกต้องทราบเกี่ยวกับ Unicode และชุดตัวอักษร
CA2W เหล่านี้ (แปลง Ansi กว้าง = Unicode) แมโครเป็นส่วนหนึ่งของATL และ MFC String แปลงแมโครตัวอย่างรวม
บางครั้งคุณจะต้องปิดการใช้งานคำเตือนความปลอดภัย # 4995 'ฉันไม่ทราบวิธีแก้ปัญหาอื่น ๆ (สำหรับฉันมันเกิดขึ้นเมื่อฉันคอมไพล์สำหรับ WindowsXp ใน VS2012)
#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
คลาส
สิ่งนี้ใช้ไม่ได้กับการเข้ารหัสอักขระแบบหลายไบต์ นี่เป็นเพียงวิธีใบ้ของการทิ้งความปลอดภัยประเภทและขยายอักขระ 7 บิตจาก std :: string ไปที่ 7 บิตต่ำกว่าของอักขระแต่ละตัวของ std: wstring สิ่งนี้มีประโยชน์เฉพาะถ้าคุณมีสตริง ASCII 7 บิตและคุณต้องเรียก 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 mulitbyte เป็นชุดของค่า 1 string
ไบต์เช่นในที่ คลาสสตริงไม่ได้ช่วยในการเข้ารหัส ฉันไม่ใช่ผู้เชี่ยวชาญในการเข้ารหัสคลาสใน c ++
std::string
ลงไปต่ำกว่า 7 std:wstring
บิตของตัวละครของแต่ละ สิ่งนี้มีประโยชน์เฉพาะถ้าคุณมีสตริง ASCII 7 บิตและคุณต้องเรียก 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
คุณควรใช้ ตรวจสอบคำตอบอื่น ๆ
ใช้ Boost.Locale:
ws = boost::locale::conv::utf_to_utf<wchar_t>(s);
ตัวแปรนี้เป็นสิ่งที่ฉันโปรดปรานในชีวิตจริง มันจะแปลงใส่ถ้ามันถูกต้อง 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 :: สตริง 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 มีแนวโน้มที่จะหยุดเมื่อพบอักขระที่ไม่รู้จักและตัดสตริงที่จุดนั้น (ฉันได้ทดสอบตัวอักษรภาษาเวียดนามบนหน้าต่างภาษาฟินแลนด์)
ดังนั้นชอบฟังก์ชั่น Multi * -windows api มากกว่าฟังก์ชั่นอนาล็อก ansi C
สิ่งที่ฉันสังเกตเห็นวิธีที่สั้นที่สุดในการเข้ารหัสสตริงจากเพจรหัสหนึ่งไปอีกอันหนึ่งไม่ได้ใช้ 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 ดังนั้นสแต็กจะถูกปลดปล่อยจากการแปลงชั่วคราว
สตริงเป็น 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);
}
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 แล้วหรือไม่