C ++ แปลงสตริง (หรืออักขระ *) เป็น wstring (หรือ wchar_t *)


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

ฉันจะกำหนดเนื้อหาของ s ให้กับ ws ได้อย่างไร

ค้นหา google และใช้เทคนิคบางอย่าง แต่ไม่สามารถกำหนดเนื้อหาที่แน่นอนได้ เนื้อหาผิดเพี้ยน


7
ฉันไม่คิดว่าstringsจะยอมรับอักขระ 8 บิต มีการเข้ารหัสใน UTF-8 แล้วหรือไม่
kennytm

3
ระบบของคุณเข้ารหัสอะไรที่จะทำให้"おはよう"สตริงเข้ารหัสระบบ
sbi

ฉันเชื่อว่า MSVC จะยอมรับและทำการเข้ารหัสแบบหลายไบต์หรืออาจเป็น UTF-8
Potatoswatter

1
@Potatoswatter: MSVC ไม่ได้ใช้ UTF-8 ตามค่าเริ่มต้นสำหรับทุกสิ่ง หากคุณป้อนอักขระเหล่านั้นระบบจะถามว่าการเข้ารหัสใดที่จะแปลงไฟล์เป็นและตั้งค่าเริ่มต้นเป็นเพจรหัส 1252
Mooing Duck

2
@ ซามีร์: สำคัญกว่านั้นคือการเข้ารหัสของไฟล์คืออะไร? คุณสามารถย้ายสตริงนั้นไปยังจุดเริ่มต้นของไฟล์และแสดง hexdump ของส่วนนั้นได้หรือไม่? เราอาจระบุได้จากสิ่งนั้น
Mooing Duck

คำตอบ:


239

สมมติว่าสตริงอินพุตในตัวอย่างของคุณ (おはよう) เป็น 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แก้ปัญหาในคำตอบนี้มีความปลอดภัยและพกพาได้


2
ตรวจสอบสิ่งที่เข้ารหัสคุณบันทึกไฟล์ VS ด้วย
Johann Gerell

9
ระวังว่านี่คือ C ++ 11 เท่านั้น!
bk138

1
ใน minGW (gcc / g ++ 4.8.1 และ -std = c ++ 11) ส่วนหัว codecvt ไม่มีอยู่ มีทางเลือกอื่นหรือไม่?
Brian Jack

1
ขอให้คุณยกตัวอย่างstd::codecvt_utf8สำหรับผู้เริ่มต้น
Noitidart

15
โปรดทราบว่า<codecvt>เลิกใช้แล้วตั้งแต่ C ++ 17
tambre

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

    ws = wsTmp;

    return 0;
}

93
นี้จะทำงานเฉพาะถ้าตัวละครทั้งหมดที่มี byte เดียวคือ ASCII หรือISO-8859-1 สิ่งที่หลายไบต์จะล้มเหลวอย่างน่าสังเวชรวมถึง UTF-8 คำถามมีอักขระหลายไบต์อย่างชัดเจน
Mark Ransom

28
คำตอบนี้เห็นได้ชัดว่าไม่เพียงพอและไม่ทำอะไรเลยนอกจากคัดลอกอักขระที่แคบตามที่เป็นตัวกว้าง ดูคำตอบอื่น ๆ โดยเฉพาะคำตอบของ Johann Gerell สำหรับวิธีการเปลี่ยนจากสตริงที่เข้ารหัสแบบหลายไบต์หรือ utf8 ไปเป็นสตริง utf16
DLRdave

10
คำตอบนี้เป็นสิ่งที่อันตรายและอาจเกิดขึ้นกับระบบที่ไม่ใช่ ASCII เช่นชื่อไฟล์ภาษาอาหรับจะถูกแฮ็กโดยแฮ็คนี้
Stephen

9
คำตอบนี้มีประโยชน์หากคุณเพิกเฉยต่อความแตกต่างของคำถามและมุ่งเน้นไปที่ชื่อคำถามซึ่งเป็นสิ่งที่นำฉันมาที่นี่จาก Google เช่นเดียวกับชื่อของคำถามนั้นทำให้เข้าใจผิดอย่างยิ่งและควรปรับเปลี่ยนเพื่อสะท้อนคำถามที่แท้จริงที่ถูกถาม
Anne Quinn

3
ใช้ได้กับอักขระ ASCII 7 บิตเท่านั้น สำหรับ latin1 มันจะทำงานเฉพาะถ้าถ่านถูกกำหนดค่าเป็น unsigned หากประเภท char มีการลงชื่อ (ซึ่งส่วนใหญ่เป็นกรณี) ตัวละคร> 127 จะให้ผลลัพธ์ที่ผิด
huyc

32

คำถามของคุณไม่ได้รับการระบุด้านล่าง อย่างเคร่งครัดตัวอย่างนั้นเป็นข้อผิดพลาดทางไวยากรณ์ อย่างไรก็ตาม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.

1
string s = "おはよう"; wchar_t * buf = ใหม่ wchar_t [s.size ()]; size_t num_chars = mbstowcs (buf, s.c_str (), s.size ()); wstring ws (buf, num_chars); // ws = บิดเบี้ยว
Samir

1
@Samir: คุณต้องแน่ใจว่าการเข้ารหัสรันไทม์เหมือนกับการเข้ารหัสเวลาคอมไพล์ คุณอาจต้องการsetlocaleหรือปรับเปลี่ยนธงคอมไพเลอร์ ฉันไม่รู้เพราะฉันไม่ได้ใช้ Windows แต่นี่คือเหตุผลว่าทำไมมันจึงไม่ใช่คุณสมบัติทั่วไป พิจารณาคำตอบอื่น ๆ ถ้าเป็นไปได้
Potatoswatter

1
std::string ws(s.size()); ws.resize(mbstowcs(&ws[0], s.c_str(), s.size());
Raii

2
@WaffleSouffle ล้าสมัยแล้ว การใช้งานที่ต่อเนื่องเป็นสิ่งจำเป็นมาตั้งแต่ปี 2011 และการใช้งานได้เลิกใช้เทคนิคดังกล่าวมานานก่อนหน้านั้น
Potatoswatter

1
และสภาพแวดล้อมบางอย่างเช่น mingw ยังไม่มีส่วนหัว codecvt ดังนั้นโซลูชัน 'ดีกว่า' บางรุ่นก่อนหน้านี้จึงไม่ทำงานหมายความว่าปัญหานี้ยังไม่มีวิธีแก้ปัญหาที่ดีใน mingw แม้ในเดือนธันวาคม 2014
Brian Jack

18

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;
c00000fd

1
@ c00000fd เท่าที่ฉันทราบบัฟเฟอร์ภายใน std :: basic_string จำเป็นต้องต่อเนื่องตั้งแต่มาตรฐาน C ++ 11 เท่านั้น รหัสของฉันคือ pre C ++ 11 ตามที่ระบุไว้ด้านบนของโพสต์ ดังนั้นรหัส & strW [0] จะไม่เป็นไปตามมาตรฐานและอาจผิดพลาดในขณะใช้งานจริง
Alex Che

13

หากคุณใช้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)

แก้ไข: ตามบทความนี้บทความของโจเอลดูเหมือนจะเป็น: "ในขณะที่ให้ความบันเทิงมันค่อนข้างเบาในรายละเอียดทางเทคนิคที่เกิดขึ้นจริง" บทความ: อะไรทุกโปรแกรมเมอร์แน่นอนบวกต้องการทราบเกี่ยวกับการเข้ารหัสและตัวอักษรชุดที่จะทำงานกับข้อความ


ขออภัยฉันไม่ใช่เจ้าของภาษา โปรดแก้ไขตามที่เห็นสมควร
lmiguelmh

ขึ้นกับ downvoter อะไร เกิดอะไรขึ้นกับคำตอบ?
lmiguelmh

อาจเป็นความจริงที่ว่ามันส่งเสริมรหัสที่ไม่ใช่พกพา
Pavel Minaev

ใช่นั่นเป็นเหตุผลที่ฉันระบุว่าใช้งานได้เฉพาะใน Windows / Visual Studio แต่อย่างน้อยวิธีนี้คือการที่ถูกต้องและไม่นี้:char* str = "hello worlddd"; wstring wstr (str, str+strlen(str));
lmiguelmh

หมายเหตุเพิ่มเติม: CA2W อยู่ภายใต้ namespace ของ ATL (ATL :: CA2W)
Val

12

นี่คือวิธีการรวม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();

คำตอบนั้นน่าสนใจ คุณช่วยอธิบายหน่อยได้ไหม: มันจะใช้ได้กับการเข้ารหัสแบบหลายไบต์และทำไม / อย่างไร?
wh1t3cat1k

รูปแบบการเข้ารหัสเป็นมุมฉากของคลาสหน่วยเก็บข้อมูล stringเก็บอักขระ 1 ไบต์และwstringเก็บอักขระ 2 ไบต์ สิ่งที่ชอบตัวละครที่ร้านค้า utf8 mulitbyte เป็นชุดของค่า 1 stringไบต์เช่นในที่ คลาสสตริงไม่ได้ช่วยในการเข้ารหัส ฉันไม่ใช่ผู้เชี่ยวชาญในการเข้ารหัสคลาสใน c ++
Mark Lakata

2
ไม่ว่าด้วยเหตุผลใดทำไมอันนี้จึงไม่ใช่คำตอบที่ดีที่สุดเพราะสั้นและเรียบง่ายแค่ไหน? กรณีใด ๆ ที่มันไม่ครอบคลุม?
Ryuu

@ MarkLakata ฉันอ่านคำตอบของคุณในความคิดเห็นแรก แต่ยังไม่แน่ใจ ใช้ได้กับอักขระหลายไบต์หรือไม่ กล่าวอีกนัยหนึ่งคือมันไม่ได้มีแนวโน้มที่จะเป็นอันตรายเหมือนกับคำตอบนี้หรือไม่?
Marc.2377

@ Marc.2377 วิธีนี้ใช้ไม่ได้กับการเข้ารหัสอักขระแบบหลายไบต์ นี่เป็นเพียงวิธีใบ้ของทิ้งความปลอดภัยประเภทและการขยายตัวอักษร 7 บิตจากstd::stringลงไปต่ำกว่า 7 std:wstringบิตของตัวละครของแต่ละ สิ่งนี้มีประโยชน์เฉพาะถ้าคุณมีสตริง ASCII 7 บิตและคุณต้องเรียก API ที่ต้องใช้สตริงที่กว้าง ดูstackoverflow.com/a/8969776/3258851หากคุณต้องการบางสิ่งที่ซับซ้อนกว่านี้
Mark Lakata

11

จาก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 เท่านั้น


7
เพราะจะใช้งานได้ก็ต่อเมื่อการเข้ารหัสเป็น Windows-1252 ซึ่งไม่สามารถถือจดหมายในคำถามได้
Mooing Duck

3
นี่เป็นข้อผิดพลาดน้อยที่สุดในการทำเช่นนั้นเมื่อคุณรู้ว่าคุณจัดการกับ ASCII ซึ่งเป็น usecase ที่โดดเด่นเมื่อทำการย้ายแอพไปยัง API ที่ใหม่กว่า
Sid Sarasvati

นี่ไม่ใช่วิธี หากคุณกำลังใช้ Visual Studio atlconv.hคุณควรใช้ ตรวจสอบคำตอบอื่น ๆ
lmiguelmh


5

ตัวแปรนี้เป็นสิ่งที่ฉันโปรดปรานในชีวิตจริง มันจะแปลงใส่ถ้ามันถูกต้อง 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;
    }
}

1
ฉันเพิ่งเปิดตัวคำถามนี้ขึ้นอยู่กับคำตอบของคุณstackoverflow.com/questions/49669048/…คุณสามารถดูได้
ไหม

2

หากคุณมี QT และหากคุณขี้เกียจที่จะใช้ฟังก์ชั่นและสิ่งที่คุณสามารถใช้

std :: สตริง str; QString (STR) .toStdWString ()


เกือบแล้ว แต่คุณควรเริ่มด้วย a QStringเพราะตัวQStringสร้างไม่สามารถรับสตริงได้ด้วยเหตุผลบางอย่าง
bobsbeenjamin

1
คุณสามารถใช้doc.qt.io/qt-5/qstring.html#fromStdString
Kadir Erdem Demir

นี่เป็นสิ่งที่ดี นอกจากนี้คุณยังสามารถใช้. c_str ()เพื่อให้ QString ยอมรับสตริงของคุณใน Constructor
miep

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;
}

6
อะไรคือคำตอบทั้งหมดที่จัดสรรหน่วยความจำแบบไดนามิกในวิธีที่ไม่ปลอดภัยแล้วคัดลอกข้อมูลจากบัฟเฟอร์ไปยังสตริง ทำไมไม่มีใครกำจัดคนกลางที่ไม่ปลอดภัยออก?
Mooing Duck

ฮ่า ๆ ๆ ๆ คุณช่วยได้ด้วยสิ่งที่คล้ายกันสำหรับ ws2s?
คริสเตียน

1

จากการทดสอบของฉันเอง (บน 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 ดังนั้นสแต็กจะถูกปลดปล่อยจากการแปลงชั่วคราว


1

สตริงเป็น 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
Str2Wstr นี้มีปัญหากับการยกเลิก 0 ไม่สามารถต่อ wstrings ที่สร้างขึ้นอีกต่อไปผ่าน "+" (เช่นใน wstring s3 = s1 + s2) ฉันจะโพสต์คำตอบในไม่ช้าการแก้ปัญหานี้ ต้องทำการทดสอบการรั่วไหลของหน่วยความจำก่อน
thewhiteambit

-2

string s = "おはよう"; เป็นข้อผิดพลาด

คุณควรใช้ wstring โดยตรง:

wstring ws = L"おはよう";

1
นั่นจะไม่ทำงานเช่นกัน คุณจะต้องแปลงตัวละครที่ไม่ใช่ BMP เป็น C escape sequences
Dave Van den Eynde

3
@Dave: มันไม่ทำงานถ้าสนับสนุนคอมไพเลอร์ของคุณ Unicode ในแฟ้มแหล่งที่มาและคนทั้งหมดในทศวรรษที่ผ่านมาทำ (ภาพสตูดิโอ, GCC, ... )
โทมัส Bonini

สวัสดีไม่ว่าการเข้ารหัสระบบเริ่มต้น (ฉันอาจมีการเข้ารหัสภาษาอาหรับเป็นระบบเริ่มต้นของฉัน) การเข้ารหัสไฟล์รหัสต้นฉบับสำหรับ L "" はよう "ควรทำงานอย่างไร มันควรจะเป็น UTF-16 หรือฉันสามารถมี UTF-8 ได้โดยไม่ต้อง BOM สำหรับการเข้ารหัสไฟล์. cpp
Afriza N. Arief

2
@afriza: มันไม่สำคัญว่าตราบใดที่คอมไพล์ของคุณรองรับมัน
Thomas Bonini

2
มันไม่ใช่ข้อผิดพลาด อักขระส่วนขยายในสตริง "แคบ" ถูกกำหนดเพื่อแม็พกับลำดับหลายไบต์ คอมไพเลอร์ควรสนับสนุนตราบใดที่ระบบปฏิบัติการทำซึ่งเป็นอย่างน้อยคุณสามารถถาม
Potatoswatter

-2

ใช้รหัสนี้เพื่อแปลงสตริงของคุณเป็น 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;
}

3
โปรดทราบว่าคำถามไม่มีการกล่าวถึง Windows และคำตอบนี้เป็น Windows เท่านั้น
Johann Gerell

CP_ACPเป็นข้อโต้แย้งที่ผิดอย่างแน่นอนที่สุด ในทันทีสถานะสภาพแวดล้อมของเธรดที่กำลังเรียกใช้มีผลต่อพฤติกรรมของโค้ด ไม่แนะนำให้เลือก ระบุการเข้ารหัสอักขระคงที่ในการแปลงของคุณ (และพิจารณาการจัดการข้อผิดพลาด)
IInspectable
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.