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
мабуть, те, що ви шукаєте.
Це функція бібліотеки С і працює над буферами, але ось легка у користуванні ідіома, люб’язність 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
Тільки API 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]
. Нарешті переконайтеся, що останній нуль присутній після конверсії, виконуючи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());
Та сама процедура перетворення вставки в рядок (іноді вам потрібно буде вказати сторінку коду ):
#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 StD :: рядок показав в цій відповіді .
//
// 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 про програмне забезпечення: Абсолютний мінімум кожного розробника програмного забезпечення абсолютно, позитивно повинен знати про набори юнікоду та символів .
Ці макроси CA2W (Перетворити Ansi в широкий = unicode) є частиною макросів ATL і MFC String Conversion , включені зразки.
Іноді вам потрібно буде відключити попередження про безпеку № 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. Це корисно лише в тому випадку, якщо у вас є 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 байтовим значенням, тобто в a 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 має тенденцію зупинятися, коли він стикається з невідомим символом і вирізає рядок саме в цій точці. (Я випробував в'єтнамські символи на фінських вікнах).
Тому віддайте перевагу функції 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 - краще повернути якнайшвидше, тому стек буде звільнений від тимчасової конверсії.
Рядок на завивку
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;
}
прив’язання до рядка
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?