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 и она работает с буферами, но вот простая в использовании идиома, любезно предоставленная 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]
. Наконец, убедитесь, что последний нулевой присутствует после преобразования, выполнив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 ). В этом ответе показан стандартный способ преобразования 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);
}
Если вы хотите узнать больше о кодовых страницах, то есть интересная статья о Джоэле о программном обеспечении: Абсолютный минимум, который должен знать каждый разработчик программного обеспечения. .
Эти макросы CA2W (Convert Ansi to Wide = unicode) являются частью макросов преобразования строк ATL и MFC , включая примеры.
Иногда вам нужно отключить предупреждение безопасности # 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
. классы строки не помогают с кодированием. Я не эксперт по кодированию классов в с ++.
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 (ул) .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-функции по сравнению с аналоговыми и C-функциями.
Кроме того, я заметил, что самый короткий способ кодирования строки из одной кодовой страницы в другую - это не вызовы функций API MultiByteToWideChar / WideCharToMultiByte, а их аналоговые макросы 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, поэтому стек будет освобожден от временного преобразования.
Строка в строку
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 to 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?