Я не думаю, что stringsпринимает> 8-битные символы. Это уже закодировано в UTF-8?
Kennytm
3
Какая у вас системная кодировка, чтобы она "おはよう"создавала системную строку?
2010 года
Я полагаю, что MSVC примет это и создаст несколько многобайтовых кодировок, возможно, UTF-8.
Potatoswatter
1
@Potatoswatter: MSVC не использует UTF-8 по умолчанию для НИЧЕГО. Если вы вводите эти символы, он спрашивает, в какую кодировку конвертировать файл, и по умолчанию использует кодовую страницу 1252.
Mooing Duck
2
@Samir: что важнее, какова кодировка файла ? Можете ли вы переместить эту строку в начало файла и показать hexdump этой части? Мы можем, вероятно, определить это из этого.
Mooing Duck
Ответы:
239
Предполагая, что входная строка в вашем примере (お は よ う) имеет кодировку UTF-8 (что не выглядит, но давайте предположим, что это ради объяснения :-)) представление строки Unicode Если вы заинтересованы, то ваша проблема может быть полностью решена с помощью стандартной библиотеки (C ++ 11 и новее).
Как указано в комментариях и объяснено в https://stackoverflow.com/a/17106065/6345, существуют случаи, когда использование стандартной библиотеки для преобразования между UTF-8 и UTF-16 может привести к неожиданным различиям в результатах на разных платформах. , Для лучшего преобразования рассмотрите, std::codecvt_utf8как описано на http://en.cppreference.com/w/cpp/locale/codecvt_utf8
Это работает, только если все символы являются однобайтовыми, то есть ASCII или ISO-8859-1 . Любой многобайтовый код с треском провалится, включая UTF-8. Вопрос явно содержит многобайтовые символы.
Марк Рэнсом
28
Этот ответ явно недостаточен и делает только копирование узких символов, как есть, в широкие символы. Посмотрите другие ответы, в частности, ответ Иоганна Герелла, чтобы узнать, как правильно перейти от многобайтовой строки или строки в кодировке utf8 к строке wtf16.
DLRdave
10
этот ответ опасен и, вероятно, сломается в системе, отличной от ascii. то есть арабское имя файла будет искажено этим взломом.
Стивен
9
Этот ответ полезен, если вы игнорируете нюанс тела вопроса и сосредотачиваетесь на названии вопроса, что и привело меня сюда из Google. Как, название на вопрос является чрезвычайно вводящей в заблуждение и должны быть изменены , чтобы отразить истинный вопрос Спрашиваемо
Энн Quinn
3
Это работает только для 7-битных символов ASCII. Для latin1 это работает, только если char настроен как unsigned. Если тип char подписан (что чаще всего имеет место), символы> 127 будут давать неправильные результаты.
huyc
32
Ваш вопрос не указан. Строго говоря, этот пример является синтаксической ошибкой. Тем не мение,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.
@Samir: Вы должны убедиться, что кодировка во время выполнения совпадает с кодировкой во время компиляции. Вам может понадобиться setlocaleили настроить флаги компилятора. Я не знаю, потому что я не использую Windows, но именно поэтому это не обычная функция. Рассмотрим другой ответ, если это возможно.
@WaffleSouffle Это устарело. С 2011 года требуются смежные реализации, и реализации выходят из таких уловок задолго до этого.
Potatoswatter
1
а в некоторых средах, таких как mingw, до сих пор нет заголовка codecvt, поэтому некоторые из «лучших» решений ранее не работают, то есть эта проблема все еще не имеет хороших решений в mingw даже по состоянию на декабрь 2014 года
Брайан Джек
18
Только для Windows API, до C ++ 11, если кому-то это нужно:
Вы можете оптимизировать это. Нет необходимости делать двойную копию строки, используя vector. Просто Оставляем символы в строке, делая wstring strW(charsNeeded + 1);и затем использовать его в качестве буфера для преобразования: &strW[0]. Наконец, убедитесь, что последний нулевой присутствует после преобразования, выполнивstrW[charsNeeded] = 0;
c00000fd
1
@ c00000fd, насколько я знаю, внутренний буфер std :: basic_string должен быть непрерывным только начиная со стандарта C ++ 11. Мой код до C ++ 11, как отмечено в верхней части поста. Поэтому код & strW [0] не будет соответствовать стандарту и может законно завершиться сбоем во время выполнения.
Алекс Че
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());
// // 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);}
Иногда вам нужно отключить предупреждение безопасности # 4995 ', я не знаю другого обходного пути (для меня это случилось, когда я скомпилировал для WindowsXp в VS2012).
Извините, я не являюсь носителем английского языка. Пожалуйста, отредактируйте, как считаете нужным.
lmiguelmh
Что случилось с Downvoter? Что не так с ответом?
lmiguelmh
Вероятно, факт, что это продвигает непереносимый код.
Павел Минаев
Да, именно поэтому я заявил, что это работает только в Windows / Visual Studio. Но, по крайней мере, это решение верное, а не это:char* str = "hello worlddd"; wstring wstr (str, str+strlen(str));
lmiguelmh
Дополнительное примечание: CA2W находится под пространством имен ATL. (ATL :: CA2W)
Val
12
Вот способ объединения string, wstringи смешанные строковые константы к wstring. Используйте wstringstreamкласс.
Это НЕ работает для многобайтовых кодировок символов. Это просто глупый способ отбросить безопасность типов и расширить 7-битные символы из std :: string в младшие 7 бит каждого символа std: wstring. Это полезно только в том случае, если у вас есть 7-битные строки ASCII и вам нужно вызвать API, который требует широких строк.
Ответ кажется интересным. Не могли бы вы объяснить немного: будет ли это работать для многобайтовых кодировок и почему / как?
wh1t3cat1k
схемы кодирования ортогональны классу хранения. stringхранит 1-байтовые символы и wstringсохраняет 2-байтовые символы. что-то вроде utf8 хранит многобайтовые символы как последовательность значений из 1 байта, то есть в a string. классы строки не помогают с кодированием. Я не эксперт по кодированию классов в с ++.
Марк Лаката
2
Любая причина, почему этот не самый лучший ответ, учитывая, насколько он короток и прост? Какие-либо случаи, которые это не покрывает?
Рю,
@MarkLakata, я прочитал твой ответ на первый комментарий, но все еще не уверен. Будет ли это работать для многобайтовых символов? Другими словами, разве это не подвержено той же ловушке, что и этот ответ ?
23
@ Marc.2377 Это НЕ работает для многобайтовых кодировок символов. Это просто глупый способ отбросить безопасность типов и расширить 7-битные символы из std::stringнижних 7-бит каждого символа std:wstring. Это полезно только в том случае, если у вас есть 7-битные строки ASCII и вам нужно вызвать API, который требует широких строк. Посмотрите на stackoverflow.com/a/8969776/3258851, если вам нужно что-то более сложное.
Потому что это работает, только если кодировка Windows-1252, которая не может даже содержать буквы в вопросе.
Mooing Duck
3
это наименее подверженный ошибкам способ сделать это, когда вы знаете, что имеете дело с ASCII. Что является важным примером использования при портировании приложений на новые API.
Сид Сарасвати
Это не так. Если вы используете Visual Studio, вы должны использовать atlconv.h. Проверьте другие ответы.
Этот вариант мой любимый в реальной жизни. Он преобразует вход, если это действительно UTF-8, в соответствующий wstring. Если входной сигнал поврежден, он wstringсостоит из отдельных байтов. Это очень полезно, если вы не можете быть уверены в качестве входных данных.
Что со всеми этими ответами выделяет динамическую память небезопасным способом, а затем копирует данные из буфера в строку? Почему никто не избавляется от небезопасного посредника?
Mooing Duck
хахакубиле, можете ли вы помочь с чем-то похожим для ws2s?
Кристиан
1
Основываясь на моем собственном тестировании (на Windows 8, vs2010), mbstowcs может фактически повредить исходную строку, она работает только с кодовой страницей ANSI. Если MultiByteToWideChar / WideCharToMultiByte также может привести к повреждению строки - но они имеют тенденцию заменять символы, которые они не знают, на «?» вопросительные знаки, но mbstowcs имеет тенденцию останавливаться, когда встречает неизвестный символ и обрезает строку в этой самой точке. (Я проверил вьетнамские символы на финских окнах).
Так что предпочтите Multi * -Windows API-функции по сравнению с аналоговыми и C-функциями.
Кроме того, я заметил, что самый короткий способ кодирования строки из одной кодовой страницы в другую - это не вызовы функций API MultiByteToWideChar / WideCharToMultiByte, а их аналоговые макросы ATL: W2A / A2W.
Таким образом, аналоговая функция, как упомянуто выше, звучит так:
Но обратите внимание, что эти макросы используют большой стек - не используйте для циклов или рекурсивных циклов для одной и той же функции - после использования макроса W2A или A2W - лучше вернуть ASAP, поэтому стек будет освобожден от временного преобразования.
У этого Str2Wstr есть проблема с завершением 0. Больше невозможно объединить сгенерированные строки w через «+» (как в wstring s3 = s1 + s2). Я скоро выложу ответ, решающий эту проблему. Сначала нужно провести тестирование на утечки памяти.
Это тоже не сработает. Вам придется конвертировать эти не-BMP символы в C escape-последовательности.
Дейв Ван ден Эйнде
3
@Dave: он работает, если ваш компилятор поддерживает юникод в исходных файлах, и все те, что были в последнее десятилетие (Visual Studio, GCC, ...)
Томас Бонини
Привет, независимо от используемой по умолчанию системной кодировки (например, я могу использовать арабский в качестве системной кодировки по умолчанию), как должна работать кодировка файла исходного кода для L "お は よ う"? это должно быть в UTF-16, или я могу иметь UTF-8 без спецификации для кодировки файла .cpp?
Afriza N. Arief
2
@afriza: это не имеет значения, если ваш компилятор поддерживает это
Томас Бонини,
2
Это не ошибка; расширенные символы в «узкой» строке определяются для отображения на многобайтовые последовательности. Компилятор должен поддерживать его до тех пор, пока это делает ОС, что является наименьшим спросом.
Potatoswatter
-2
используйте этот код для преобразования вашей строки в wstring
Обратите внимание, что вопрос не упоминает о Windows, и этот ответ только для Windows.
Иоганн Герелл
CP_ACPэто, безусловно, неправильный аргумент. Внезапно состояние среды исполняющего потока влияет на поведение кода. Не рекомендуется Укажите фиксированную кодировку символов в конверсии. (И рассмотрим обработку ошибок.)
strings
принимает> 8-битные символы. Это уже закодировано в UTF-8?"おはよう"
создавала системную строку?Ответы:
Предполагая, что входная строка в вашем примере (お は よ う) имеет кодировку UTF-8 (что не выглядит, но давайте предположим, что это ради объяснения :-)) представление строки Unicode Если вы заинтересованы, то ваша проблема может быть полностью решена с помощью стандартной библиотеки (C ++ 11 и новее).
Версия TL; DR:
Более длинный онлайн компилируемый и запускаемый пример:
(Все они показывают один и тот же пример. Их просто много для избыточности ...)
Примечание (старое) :
Как указано в комментариях и объяснено в 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 говоряПоэтому в обозримом будущем
codecvt
решение в этом ответе является безопасным и портативным.источник
std::codecvt_utf8
<codecvt>
устарела с C ++ 17.источник
Ваш вопрос не указан. Строго говоря, этот пример является синтаксической ошибкой. Тем не мение,
std::mbstowcs
это, вероятно, то, что вы ищете.Это функция библиотеки C и она работает с буферами, но вот простая в использовании идиома, любезно предоставленная TBohne (ранее Mooing Duck):
источник
setlocale
или настроить флаги компилятора. Я не знаю, потому что я не использую Windows, но именно поэтому это не обычная функция. Рассмотрим другой ответ, если это возможно.std::string ws(s.size()); ws.resize(mbstowcs(&ws[0], s.c_str(), s.size());
RAII FTWТолько для Windows API, до C ++ 11, если кому-то это нужно:
источник
vector
. Просто Оставляем символы в строке, делаяwstring strW(charsNeeded + 1);
и затем использовать его в качестве буфера для преобразования:&strW[0]
. Наконец, убедитесь, что последний нулевой присутствует после преобразования, выполнивstrW[charsNeeded] = 0;
Если вы используете Windows / Visual Studio и вам нужно преобразовать строку в wstring, вы можете использовать:
Та же процедура для преобразования wstring в строку (иногда вам нужно будет указать кодовую страницу ):
Вы можете указать кодовую страницу и даже UTF8 (это очень хорошо при работе с JNI / Java ). В этом ответе показан стандартный способ преобразования std :: wstring в utf8 std :: string .
Если вы хотите узнать больше о кодовых страницах, то есть интересная статья о Джоэле о программном обеспечении: Абсолютный минимум, который должен знать каждый разработчик программного обеспечения. .
Эти макросы CA2W (Convert Ansi to Wide = unicode) являются частью макросов преобразования строк ATL и MFC , включая примеры.
Иногда вам нужно отключить предупреждение безопасности # 4995 ', я не знаю другого обходного пути (для меня это случилось, когда я скомпилировал для WindowsXp в VS2012).
Редактировать: Ну, в соответствии с этой статьей, статья Джоэля выглядит так: «Хотя это забавно, она довольно легка в реальных технических деталях». Статья: Что каждый программист абсолютно, положительно должен знать о кодировании и наборах символов для работы с текстом .
источник
char* str = "hello worlddd"; wstring wstr (str, str+strlen(str));
Вот способ объединения
string
,wstring
и смешанные строковые константы кwstring
. Используйтеwstringstream
класс.Это НЕ работает для многобайтовых кодировок символов. Это просто глупый способ отбросить безопасность типов и расширить 7-битные символы из std :: string в младшие 7 бит каждого символа std: wstring. Это полезно только в том случае, если у вас есть 7-битные строки ASCII и вам нужно вызвать API, который требует широких строк.
источник
string
хранит 1-байтовые символы иwstring
сохраняет 2-байтовые символы. что-то вроде utf8 хранит многобайтовые символы как последовательность значений из 1 байта, то есть в astring
. классы строки не помогают с кодированием. Я не эксперт по кодированию классов в с ++.std::string
нижних 7-бит каждого символаstd:wstring
. Это полезно только в том случае, если у вас есть 7-битные строки ASCII и вам нужно вызвать API, который требует широких строк. Посмотрите на stackoverflow.com/a/8969776/3258851, если вам нужно что-то более сложное.С
char*
поwstring
:С
string
поwstring
:Обратите внимание, что это работает только в том случае, если преобразуемая строка содержит только символы ASCII.
источник
atlconv.h
. Проверьте другие ответы.используя Boost.Locale:
источник
Этот вариант мой любимый в реальной жизни. Он преобразует вход, если это действительно UTF-8, в соответствующий
wstring
. Если входной сигнал поврежден, онwstring
состоит из отдельных байтов. Это очень полезно, если вы не можете быть уверены в качестве входных данных.источник
Если у вас есть QT и вам лень реализовывать функцию и прочее, вы можете использовать
std :: string str; QString (ул) .toStdWString ()
источник
QString
, потому чтоQString
конструктор по какой-то причине не может принять строку.Метод s2ws работает хорошо. Надежда помогает.
источник
Основываясь на моем собственном тестировании (на Windows 8, vs2010), mbstowcs может фактически повредить исходную строку, она работает только с кодовой страницей ANSI. Если MultiByteToWideChar / WideCharToMultiByte также может привести к повреждению строки - но они имеют тенденцию заменять символы, которые они не знают, на «?» вопросительные знаки, но mbstowcs имеет тенденцию останавливаться, когда встречает неизвестный символ и обрезает строку в этой самой точке. (Я проверил вьетнамские символы на финских окнах).
Так что предпочтите Multi * -Windows API-функции по сравнению с аналоговыми и C-функциями.
Кроме того, я заметил, что самый короткий способ кодирования строки из одной кодовой страницы в другую - это не вызовы функций API MultiByteToWideChar / WideCharToMultiByte, а их аналоговые макросы ATL: W2A / A2W.
Таким образом, аналоговая функция, как упомянуто выше, звучит так:
_acp объявлен в макросе USES_CONVERSION.
Или также функцию, которую я часто пропускаю при выполнении преобразования старых данных в новые:
Но обратите внимание, что эти макросы используют большой стек - не используйте для циклов или рекурсивных циклов для одной и той же функции - после использования макроса W2A или A2W - лучше вернуть ASAP, поэтому стек будет освобожден от временного преобразования.
источник
Строка в строку
wstring to String
источник
string s = "おはよう";
это ошибка.Вы должны использовать wstring напрямую:
источник
используйте этот код для преобразования вашей строки в wstring
источник
CP_ACP
это, безусловно, неправильный аргумент. Внезапно состояние среды исполняющего потока влияет на поведение кода. Не рекомендуется Укажите фиксированную кодировку символов в конверсии. (И рассмотрим обработку ошибок.)