C ++ Преобразование строки (или char *) в wstring (или wchar_t *) - PullRequest
147 голосов
/ 04 апреля 2010
string s = "おはよう";
wstring ws = FUNCTION(s, ws);

Как бы я назначил содержимое s для ws?

Поиск в Google и использование некоторых методов, но они не могут назначить точное содержание. Содержание искажено.

Ответы [ 15 ]

205 голосов
/ 03 сентября 2013

Предполагая, что входная строка в вашем примере (お は よ う) имеет кодировку 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 /apers / 2017 / p0618r0.html , в котором говорится

этот библиотечный компонент следует перенести в Приложение D вдоль стороны, пока не будет стандартизирована подходящая замена.

Так что в обозримом будущем решение codecvt в этом ответе является безопасным и переносимым.

45 голосов
/ 23 января 2012
int StringToWString(std::wstring &ws, const std::string &s)
{
    std::wstring wsTmp(s.begin(), s.end());

    ws = wsTmp;

    return 0;
}
28 голосов
/ 04 апреля 2010

Ваш вопрос не указан. Строго говоря, этот пример является синтаксической ошибкой. Тем не менее, 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.
17 голосов
/ 13 ноября 2014

Только для 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);
}
12 голосов
/ 22 августа 2014

Если вы используете 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 ).

CA2W ca2w(str, CP_UTF8);

Если вы хотите узнать больше о кодовых страницах , есть интересная статья о Джоэле о программном обеспечении: Абсолютный минимум для каждого разработчика программного обеспечения Абсолютно, положительно должен знать о Unicode и наборах символов

Эти макросы 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)

Edit: Что ж, в соответствии с этой статьей статья Джоэля выглядит так: «хотя она и интересна, она довольно легка в реальных технических деталях». Статья: Что абсолютно необходимо каждому программисту знать о кодировке и наборах символов для работы с текстом .

10 голосов
/ 01 июня 2015

Вот способ объединения string, wstring и смешанных строковых констант в wstring. Используйте wstringstream класс.

#include <sstream>

std::string narrow = "narrow";
std::wstring wide = "wide";

std::wstringstream cls;
cls << " abc " << narrow.c_str() << L" def " << wide.c_str();
std::wstring total= cls.str();
10 голосов
/ 05 марта 2013

От 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.

6 голосов
/ 21 сентября 2015

с использованием Boost.Locale:

ws = boost::locale::conv::utf_to_utf<wchar_t>(s);
3 голосов
/ 18 августа 2016

Этот вариант мой любимый в реальной жизни. Он преобразует входной сигнал , если он действителен 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 голос
/ 20 марта 2019

Строка в строку

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