Форум программистов, компьютерный форум, киберфорум
Наши страницы
С++ для начинающих
Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 57, средняя оценка - 4.98
GetHelp
60 / 61 / 11
Регистрация: 27.02.2013
Сообщений: 1,112
#1

Std::string and std::wstring convert - C++

02.10.2014, 11:47. Просмотров 10112. Ответов 20
Метки нет (Все метки)

случайно наткнулся на такую вот конвертацию std::string в std::wstring

C++
1
2
3
std::string text("text");
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
std::wstring wtext = converter.from_bytes(text);
а как можно сделать обратное преобразование? т.е. std::wstring в std::string? чтоб только вот как то по аналогии в пару строк можно было...

Добавлено через 2 минуты
а все отбой там же еще есть метод to_bytes тупанул

Добавлено через 15 часов 49 минут
погодите ка, написал вот так:
C++
1
2
3
4
5
6
7
8
9
10
11
std::wstring to_wstring(const std::string& text)
{
    std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
    return converter.from_bytes(text);
}
 
std::string to_string(const std::wstring& text)
{
    std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
    return converter.to_bytes(text);
}
но при попытке сконвертить русские символы падает с ошибкой "Необработанное исключение по адресу..."
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
02.10.2014, 11:47
Я подобрал для вас темы с готовыми решениями и ответами на вопрос Std::string and std::wstring convert (C++):

ошибка error: cannot convert 'std::string {aka std::basic_string<char>}' to 'std::string* {aka std::basic_stri
на вод поступают 2 строки типа string. определить количество вхождений строки 2...

Как правильно перевести std::wstring в std::string ?
Собственно как? :)

Как привести std::wstring к std::string?
Как привести std::wstring к std::string?

Конвертация из std::string в std::wstring
В std::string находятся прочитанные данные из файла, в котором содержатся...

std::string -> std::wstring
Как перевести данный код в код с использованием wstring ( посути использовать...

ошибка в программе (cannot convert 'std::string {aka std::basic_string<char>}' to 'const char*')
int main() { string fileName, currWord, currMax = &quot;&quot;; cin&gt;&gt;fileName;...

20
0x10
2554 / 1734 / 285
Регистрация: 24.11.2012
Сообщений: 4,361
02.10.2014, 11:49 #2
Какой был текст, в какой кодировке и какая конкретно функция упала?
0
GetHelp
60 / 61 / 11
Регистрация: 27.02.2013
Сообщений: 1,112
02.10.2014, 11:51  [ТС] #3
Цитата Сообщение от 0x10 Посмотреть сообщение
Какой был текст, в какой кодировке и какая конкретно функция упала?
текст был "текст", упала функция to_wstring
0
0x10
2554 / 1734 / 285
Регистрация: 24.11.2012
Сообщений: 4,361
02.10.2014, 12:21 #4
Проверь, что кодировка была действительно utf8. Мне бы пока компилятор найти, который поддерживает эти функции...
0
MrGluck
Модератор
Эксперт CЭксперт С++
8023 / 4866 / 1425
Регистрация: 29.11.2010
Сообщений: 13,251
02.10.2014, 12:34 #5
Цитата Сообщение от GetHelp Посмотреть сообщение
to_wstring
Её нельзя использовать для преобразования string в wstring.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
std::string ws2s(const std::wstring& wstr, const std::locale& loc)
{
    if (wstr.empty())
        return std::string();
 
    typedef std::wstring::traits_type::state_type state_type;
    typedef std::codecvt<wchar_t, char, state_type> convert;
    
    const convert& cvt = std::use_facet<convert>(loc);
    std::string str(cvt.max_length()*wstr.size(), '\0');
    state_type state = state_type();
 
    const wchar_t* from_beg = &wstr[0];
    const wchar_t* from_end = from_beg + wstr.size();
    const wchar_t* from_nxt;
    char* to_beg = &str[0];
    char* to_end = to_beg + str.size();
    char* to_nxt;
    
    std::string::size_type sz = 0;
    std::codecvt_base::result r;
    do
    {
        r = cvt.out(state, from_beg, from_end, from_nxt,
                           to_beg,   to_end,   to_nxt);
        switch (r)
        {
        case std::codecvt_base::error:
            throw std::runtime_error("error converting wstring to string");
 
        case std::codecvt_base::partial:
            sz += to_nxt - to_beg;
            str.resize(2*str.size());
            to_beg = &str[sz];
            to_end = &str[0] + str.size();
            break;
 
        case std::codecvt_base::noconv:
            str.resize(sz + (from_end-from_beg)*sizeof(wchar_t));
            std::memcpy(&str[sz], from_beg,(from_end-from_beg)*sizeof(wchar_t));
            r = std::codecvt_base::ok;
            break;
 
        case std::codecvt_base::ok:
            sz += to_nxt - to_beg;
            str.resize(sz);
            break;
        }
    } while (r != std::codecvt_base::ok);
 
    return str;
}
0
GetHelp
60 / 61 / 11
Регистрация: 27.02.2013
Сообщений: 1,112
02.10.2014, 12:36  [ТС] #6
MrGluck, что за???
0
0x10
02.10.2014, 12:52
  #7

Не по теме:

Не знаю насколько корректен/необходим код выше, но с кодировками каждый раз головняк. Посему вопрос: какая стоит исходная задача? Зачем нужно гонять string в wstring и обратно?

0
GetHelp
60 / 61 / 11
Регистрация: 27.02.2013
Сообщений: 1,112
02.10.2014, 13:13  [ТС] #8
Цитата Сообщение от 0x10 Посмотреть сообщение
Не знаю насколько корректен/необходим код выше, но с кодировками каждый раз головняк. Посему вопрос: какая стоит исходная задача? Зачем нужно гонять string в wstring и обратно?
а не все ли равно? просто нужна wstring строка, какая разница как она потом будет использоваться?
0
0x10
2554 / 1734 / 285
Регистрация: 24.11.2012
Сообщений: 4,361
02.10.2014, 13:17 #9
Цитата Сообщение от GetHelp Посмотреть сообщение
а не все ли равно? просто нужна wstring строка, какая разница как она потом будет использоваться?
Вот я и хочу понять: нужна ли она на самом деле и должна ли она до или после быть сконвертирована из/в std::string. И при чем тут кодировки.
0
GetHelp
60 / 61 / 11
Регистрация: 27.02.2013
Сообщений: 1,112
02.10.2014, 13:23  [ТС] #10
Цитата Сообщение от 0x10 Посмотреть сообщение
Вот я и хочу понять: нужна ли она на самом деле и должна ли она до или после быть сконвертирована из/в std::string. И при чем тут кодировки.
что за странный вопрос нужна ли? если я говорю что мне нужна, то значит нужна иначе зачем бы я спрашивал? а про кодировки я вообще ничего не говорил...

Добавлено через 1 минуту
короче пофиг у меня уже был старый вариант конвертации
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
std::wstring _stdcall AnsiStringToWide(std::string const &Str, UINT CodePage = CP_ACP)
{
    DWORD const BuffSize = MultiByteToWideChar(CodePage, 0, Str.c_str(), -1, NULL, 0);
    if (!BuffSize) return NULL;
    std::vector<wchar_t> Buffer;
    Buffer.resize(BuffSize);
    if (!MultiByteToWideChar(CodePage, 0, Str.c_str(), -1, &Buffer[0], BuffSize)) return NULL;
    return (&Buffer[0]);
}
 
std::string _stdcall WideStringToAnsi(std::wstring const &Str, UINT CodePage = CP_ACP)
{
    DWORD const BuffSize = WideCharToMultiByte(CodePage, 0, Str.c_str(), -1, NULL, 0, NULL, NULL);
    if (!BuffSize) return NULL;
    std::vector<char> Buffer;
    Buffer.resize(BuffSize);
    if (!WideCharToMultiByte(CodePage, 0, Str.c_str(), -1, &Buffer[0], BuffSize, NULL, NULL)) return NULL;
    return (&Buffer[0]);
}
просто этот был короче намного, вот я и подумал что будет норм... но раз в wstring так не сконвертишь то печалька придется юзать старый...
0
0x10
2554 / 1734 / 285
Регистрация: 24.11.2012
Сообщений: 4,361
02.10.2014, 13:28 #11
Цитата Сообщение от GetHelp Посмотреть сообщение
а про кодировки я вообще ничего не говорил...
Тем не менее в коде в первом посте использован std::codecvt_utf8_utf16:
std::codecvt_utf8_utf16 is a std::codecvt facet which encapsulates conversion between a UTF-8 encoded byte string and UTF-16 encoded character string.
Ладно, не важно.
0
Voivoid
708 / 280 / 15
Регистрация: 31.03.2013
Сообщений: 1,339
02.10.2014, 13:35 #12
Цитата Сообщение от MrGluck Посмотреть сообщение
Её нельзя использовать для преобразования string в wstring.
Воу-воу-воу, я конечно не знаток, но твой код на первый взгляд не сильно отличается от того, как реализован std::wstring_convert. Что там по-твоему не так-то?

Добавлено через 3 минуты
Цитата Сообщение от GetHelp Посмотреть сообщение
UINT CodePage = CP_ACP
Ты уж определись-то, utf-8 тебе надо или кодировку текущей локали винды
0
GetHelp
60 / 61 / 11
Регистрация: 27.02.2013
Сообщений: 1,112
02.10.2014, 13:37  [ТС] #13
Цитата Сообщение от Voivoid Посмотреть сообщение
Ты уж определись-то, utf-8 тебе надо или кодировку текущей локали винды
я без понятия, я просто содрал где то тот код... да и этот тоже мне важно сконвертить и мне фиолетово как это будет выглядеть внутри, точнее если покороче будет я только за
0
MrGluck
Модератор
Эксперт CЭксперт С++
8023 / 4866 / 1425
Регистрация: 29.11.2010
Сообщений: 13,251
02.10.2014, 15:25 #14
Цитата Сообщение от Voivoid Посмотреть сообщение
Воу-воу-воу, я конечно не знаток, но твой код на первый взгляд не сильно отличается от того, как реализован std::wstring_convert. Что там по-твоему не так-то?
Convert numerical value to string
http://www.cplusplus.com/reference/string/to_wstring/
Цитата Сообщение от GetHelp Посмотреть сообщение
мне важно сконвертить и мне фиолетово как это будет выглядеть внутри, точнее если покороче будет я только за
Надо всё-таки знать кодировку, в которую нужно сконвертировать данные. Иначе получается "иди туда, не знаю куда, принеси то, не знаю что"
0
Voivoid
708 / 280 / 15
Регистрация: 31.03.2013
Сообщений: 1,339
02.10.2014, 15:51 #15
Цитата Сообщение от MrGluck Посмотреть сообщение
Э-э-э, а это к чему вообще? Я может что-то не заметил, но речь-то вроде о std::wstring_convert? При чем тут std::to_wstring ?
0
MrGluck
Модератор
Эксперт CЭксперт С++
8023 / 4866 / 1425
Регистрация: 29.11.2010
Сообщений: 13,251
02.10.2014, 16:31 #16
Цитата Сообщение от Voivoid Посмотреть сообщение
речь-то вроде о std::wstring_convert? При чем тут std::to_wstring ?
Я как бы про другое писал.
Цитата Сообщение от MrGluck Посмотреть сообщение
to_wstring
Её нельзя использовать для преобразования string в wstring.
Цитата Сообщение от Voivoid Посмотреть сообщение
Её нельзя использовать для преобразования string в wstring.
Воу-воу-воу, я конечно не знаток, но твой код на первый взгляд не сильно отличается от того, как реализован std::wstring_convert. Что там по-твоему не так-то?
Решение зависит от того, из какой кодировки в какую нужно переводить. Если из ANSI в UTF8, то std::wstring_convert не пойдёт т.к.
std::wstring_convert assumes ownership of the conversion facet, and cannot use a facet managed by a locale
Я же предложил вариант перевода из ANSI (string) в UTF8 (wstring)
0
kzru_hunter
1106 / 775 / 99
Регистрация: 01.02.2011
Сообщений: 1,779
Записей в блоге: 1
17.11.2015, 23:48 #17
Да, в чистом visual c++ проблема с конвертированием (std::string(ANSI)<->std:wstring(ANSI)). В билдере просто тупо пишешь WideString wStr = str;

Вот мои заготовки для visual c++:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
std::wstring to_wstring(char *str)
{
    int max_len = strlen(str)+1;
    std::wstring wstr; wstr.resize(max_len);    
    MultiByteToWideChar(CP_ACP, 0, str, -1, (LPWSTR)wstr.c_str(), max_len);
    return wstr;
}
 
std::string to_string(wchar_t *wstr)
{
    int max_len = lstrlen(wstr);
    std::string str; str.resize(max_len);
    WideCharToMultiByte(CP_ACP, 0, wstr, -1, (LPSTR)str.c_str(), max_len, NULL, NULL);
    return str;
}
Единственно, нельзя использовать таким образом:
C++
1
2
char *str = "некоторая строка";
wchar_t *wstr = (wchar_t*)to_wstring(str).c_str(); // тут создаётся временный объект wstring и возвращается указатель на его данные, после этой строки объект уничтожится вместе с данными
Добавлено через 31 минуту
Хотя наверно лучше использовать auto_ptr, чтобы не попасться в ситуацию, описанную выше.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
std::auto_ptr<WCHAR> to_wchar_str(char *str)
{
    int max_len = strlen(str)+1;
    WCHAR *wstr = new WCHAR[max_len];
    MultiByteToWideChar(CP_ACP, 0, str, -1, wstr, max_len);
    return std::auto_ptr<WCHAR>(wstr);
}
 
std::auto_ptr<char> to_char_str(wchar_t *wstr)
{
    int max_len = lstrlen(wstr)+1;
    char *str = new char[max_len];  
    WideCharToMultiByte(CP_ACP, 0, wstr, -1, str, max_len, NULL, NULL);
    return std::auto_ptr<char>(str);
}
И использовать следующим образом:
char *path = "некоторая строка";
auto wpath = to_wchar_str(path); // auto будет работать, если есть поддержка C++11
0
DrOffset
7518 / 4514 / 1097
Регистрация: 30.01.2014
Сообщений: 7,362
18.11.2015, 08:27 #18
Цитата Сообщение от kzru_hunter Посмотреть сообщение
лучше использовать auto_ptr,
auto_ptr нельзя использовать для массивов.
0
kzru_hunter
1106 / 775 / 99
Регистрация: 01.02.2011
Сообщений: 1,779
Записей в блоге: 1
18.11.2015, 11:45 #19
С auto_ptr тоже гемор. Короче остановился на таком варианте.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
namespace convert
{
    // конвертирует std::string -> [ANSI] -> std::wstring
    int StrToWStr(std::wstring &dest, const std::string &source)
    {
        int source_len = source.length();
 
        dest.resize(source_len + 1);
        int dest_len = MultiByteToWideChar(CP_ACP, 0, source.c_str(), -1, (WCHAR*)dest.c_str(), source_len + 1);
 
        return dest_len;
    }
 
    // конвертирует std::wstring -> [ANSI] -> std::string
    int WStrToStr(std::string &dest, const std::wstring &source)
    {
        int source_len = source.length() + 1;
 
        dest.resize(source_len * 2 + 1);
        int dest_len = WideCharToMultiByte(CP_ACP, 0, source.c_str(), -1, (LPSTR)dest.c_str(), source_len * 2 + 1, NULL, NULL);
        dest.resize(dest_len); dest.shrink_to_fit(); // укорачивание памяти под dest
 
        return dest_len;
    }
 
    // конвертирует std::string -> [CodePage] -> std::string
    int StrTo(std::string& dest, const std::string& source, UINT ResultCodePage = CP_ACP, DWORD dwFlags = 0) // параметры см. в WideCharToMultiByte
    {
        int source_len = source.length();
 
        WCHAR *wstr = new WCHAR[source_len + 1];
        MultiByteToWideChar(CP_ACP, 0, source.c_str(), -1, wstr, source_len + 1);
 
        dest.resize(source_len * 2 + 1);
        int dest_len = WideCharToMultiByte(ResultCodePage, dwFlags, wstr, -1, (LPSTR)dest.c_str(), source_len * 2 + 1, NULL, NULL);
        dest.resize(dest_len); dest.shrink_to_fit(); // укорачивание памяти под dest
 
        delete[] wstr;
 
        return dest_len;
    }
 
    // конвертирует std::wstring -> [CodePage] -> std::string
    int WStrTo(std::string& dest, const std::wstring& source, UINT ResultCodePage = CP_ACP, DWORD dwFlags = 0) // параметры см. в WideCharToMultiByte
    {
        int source_len = source.length();
 
        dest.resize(source_len * 2 + 1);
        int dest_len = WideCharToMultiByte(ResultCodePage, dwFlags, source.c_str(), -1, (LPSTR)dest.c_str(), source_len * 2 + 1, NULL, NULL);
        dest.resize(dest_len); dest.shrink_to_fit(); // укорачивание памяти под dest
 
        return dest_len;
    }
}
0
Tulosba
:)
Эксперт С++
4746 / 3240 / 496
Регистрация: 19.02.2013
Сообщений: 9,046
18.11.2015, 17:45 #20
Цитата Сообщение от kzru_hunter Посмотреть сообщение
С auto_ptr тоже гемор.
К тому же он deprecated, тем более, что раз уж используется shrink_to_fit, то это C++11.
В StrTo можем получить утечки, если resize кинет исключение.
Поэтому, я бы как минимум, предложил заменить
C++
1
WCHAR *wstr = new WCHAR[source_len + 1];
на
C++
1
std::vector<WCHAR> wstr(source_len + 1);
P.S. И как мне кажется, можно вообще обойтись стандартными (c++11) средствами, без виндозных MultiByteToWideChar. Поправьте, если ошибаюсь.

Лучше даже не std::vector, т.к. всякие векторные операции не нужны, а
C++
1
std::unique_ptr<WCHAR[]> wstr(new WCHAR[source_len + 1]);
Для с++14:
C++
1
auto wstr = std::make_unique<WCHAR[]>(source_len + 1);
0
18.11.2015, 17:45
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
18.11.2015, 17:45
Привет! Вот еще темы с решениями:

На основе исходного std::vector<std::string> содержащего числа, создать std::vector<int> с этими же числами
подскажите есть вот такая задача. Есть список . Создать второй список, в...

Ошибка Cannot convert std::string to void*
Не могу сконвертировать строку в void*: std::string str; (void*)str; ...

cannot convert parameter 1 from 'int' to 'std::string &'
string kolvo(string &amp;S, int &amp;k) { unsigned int i; for(i=1; i&lt;S.length();...

Запрошено преобразование от ‘const std::string*’ к нескалярному типу ‘std::string’
private: std::string firstName; }; std::string...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru