
![]() |
Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
|
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[216.73.216.3] |
![]() |
|
Сообщ.
#1
,
|
|
|
Преобразование std::string в std::wstring туда и обратно, как делается? (Юникод <-> Анси)
|
Сообщ.
#2
,
|
|
|
![]() ![]() std::string str = "12345"; std::wstring wstr1(str.begin(), str.end()); std::wstring wstr2(str.length(), ' '); std::copy(str.begin(), str.end(), wstr2.begin()); std::string str1(wstr1.begin(), wstr1.end()); std::string str2(wstr2.length(), L' '); std::copy(wstr2.begin(), wstr2.end(), str2.begin()); |
Сообщ.
#3
,
|
|
|
а если юникодная строка (std::wstring) содержит иероглифы? Как ее переводить в std::string? Или это бред?
Вообще мне надо конвертить строки для сокетных функций, типа такого плана: ![]() ![]() #if defined(UNICODE) || defined(_UNICODE) typedef std::wstring tstring; #else typedef std::string tstring; #endif /*_UNICODE*/ ![]() ![]() BOOL CXSocket::bConnect(const std::tstring &csIp, USHORT usPort) { INT iRes = etError; #if defined(UNICODE) || defined(_UNICODE) //конвертим в АНСИ //csIp -> std::wstring #else //это АНСИ-строка, ничего с ней не делаем #endif /*_UNICODE*/ struct sockaddr_in saSockAddr = {0}; saSockAddr.sin_family = AF_INET; saSockAddr.sin_addr.s_addr = inet_addr(csIp.c_str()); saSockAddr.sin_port = ::htons(usPort); iRes = ::connect(_m_puiSocket, (struct sockaddr *)&saSockAddr, sizeof(struct sockaddr_in)); /*DEBUG*/XASSERT_RET(0 == iRes, FALSE); return TRUE; } |
Сообщ.
#4
,
|
|
|
Цитата Alca @ а если юникодная строка (std::wstring) содержит иероглифы? Как ее переводить в std::string? Или это бред? выдели размер равный юникодовой строке и копируй, как выше показал Добавлено Или тебе важно соблюсти кодировку ? |
Сообщ.
#5
,
|
|
|
Вот в этом проекте: http://www.sources.ru/wiki/doku.php?id=projects:ufo есть соответствующие специализации lexical_cast
|
Сообщ.
#6
,
|
|
|
Цитата Или тебе важно соблюсти кодировку ? Скорее всего, чтоб независимо от входной строки (Юникод или Анси) в сокетную функцию заходила Ансишная строка. |
Сообщ.
#7
,
|
|
|
Цитата Вот в этом проекте: http://www.sources.ru/wiki/doku.php?id=projects:ufo есть соответствующие специализации lexical_cast в упор не вижу |
Сообщ.
#8
,
|
|
|
Может Флекс там и переделал чего. Было в GOAL/include/lexical_cast.h
|
Сообщ.
#9
,
|
|
|
Там кроме бинарников я ничего нет
Добавлено Это типа http://firstcontact.svn.sourceforge.net/viewvc/firstcontact/firstcontact/trunk/GOAL/include/lexical_cast.h?revision=116 ??? |
Сообщ.
#10
,
|
|
|
наверное.
|
Сообщ.
#11
,
|
|
|
Цитата Alca @ Преобразование std::string в std::wstring туда и обратно, как делается? Стандартными средствами C++ примерно так можно: ![]() ![]() #include <iostream> #include <locale> #include <string> #include <vector> std::wstring wide_string(std::string const &s, std::locale const &loc) { if (s.empty()) return std::wstring(); std::ctype<wchar_t> const &facet = std::use_facet<std::ctype<wchar_t> >(loc); char const *first = s.c_str(); char const *last = first + s.size(); std::vector<wchar_t> result(s.size()); facet.widen(first, last, &result[0]); return std::wstring(result.begin(), result.end()); } std::string narrow_string(std::wstring const &s, std::locale const &loc, char default_char = '?') { if (s.empty()) return std::string(); std::ctype<wchar_t> const &facet = std::use_facet<std::ctype<wchar_t> >(loc); wchar_t const *first = s.c_str(); wchar_t const *last = first + s.size(); std::vector<char> result(s.size()); facet.narrow(first, last, default_char, &result[0]); return std::string(result.begin(), result.end()); } char const *russian_locale_designator = "rus"; // обозначение локали зависит от реализации, // "rus" подходит для VC++ int main() { std::locale loc(russian_locale_designator); std::wstring const s = L"русский текст"; std::string const sa = ::narrow_string(s, loc); std::wstring const sw = ::wide_string(sa, loc); std::locale::global(loc); std::wcout << "original wide: " << s << std::endl; std::cout << "wide -> narrow: " << sa << std::endl; std::wcout << "narrow -> wide: " << sw << std::endl; } |
Сообщ.
#12
,
|
|
|
Цитата Alca @ чтоб независимо от входной строки (Юникод или Анси) в сокетную функцию заходила Ансишная строка. Цитата Alca @ Надо определиться с кодировкой, в которой происходит обмен. Тогда и станет понятно, какие нужны преобразования. а если юникодная строка (std::wstring) содержит иероглифы? |
Сообщ.
#13
,
|
|
|
![]() ![]() std::wstring CUSCError::char2wchar( const std::string & p_in, const std::locale & p_loc ) const { try{ std::wstring out( p_in.length(), 0 ); std::string::const_iterator i = p_in.begin(), ie = p_in.end(); std::wstring::iterator j = out.begin(); for( ; i!=ie; ++i, ++j ) *j = std::use_facet< std::ctype< wchar_t > > ( p_loc ).widen( *i ); return out; }catch(...) { return std::wstring(); } }; std::string CUSCError::wchar2char( const std::wstring & p_in, const std::locale & p_loc ) const { typedef std::wstring::traits_type::state_type TsType; typedef std::codecvt<wchar_t, char, TsType> Tcvt; try{ std::string l_out( p_in.length(), char() ); const Tcvt & l_cvt = std::use_facet<Tcvt>(p_loc); const wchar_t* l_from_nxt; char* l_to_nxt; TsType l_state = TsType(); l_cvt.out(l_state, &p_in[0], &p_in[0] + p_in.size(), l_from_nxt, &l_out[0], &l_out[0] + l_out.size(), l_to_nxt); return l_out; }catch(...) { return std::string(); } }; Не знаю на сколько это правильно но делаю так. |
![]() |
Сообщ.
#14
,
|
|
Ну и мои 5 копеек:
![]() ![]() std::wstring char2wchar(const std::string& p_in, const std::locale& p_loc) { try { const std::ctype<wchar_t>& ctypeFacet = std::use_facet<std::ctype<wchar_t> >(p_loc); std::wstring out(p_in.length(), L'\0'); std::transform(p_in.begin(), p_in.end(), out.begin(), boost::bind(boost::mem_fn( static_cast<wchar_t (std::ctype<wchar_t>::*)(char) const>(&std::ctype<wchar_t>::widen) ), &ctypeFacet, _1)); return out; } catch(...) { return std::wstring(); } }; std::string wchar2char(const std::wstring& p_in, const std::locale& p_loc, char def='?') { try { const std::ctype<wchar_t>& ctypeFacet = std::use_facet<std::ctype<wchar_t> >(p_loc); std::string out(p_in.length(), '\0'); std::transform(p_in.begin(), p_in.end(), out.begin(), boost::bind(boost::mem_fn( static_cast<char (std::ctype<wchar_t>::*)(wchar_t, char) const>(&std::ctype<wchar_t>::narrow) ), &ctypeFacet, _1, def)); return out; } catch(...) { return std::string(); } }; |
Сообщ.
#15
,
|
|
|
Цитата Masterkent @ Цитата Alca @ Преобразование std::string в std::wstring туда и обратно, как делается? Стандартными средствами C++ примерно так можно: ![]() ![]() #include <iostream> #include <locale> #include <string> #include <vector> std::wstring wide_string(std::string const &s, std::locale const &loc) { if (s.empty()) return std::wstring(); std::ctype<wchar_t> const &facet = std::use_facet<std::ctype<wchar_t> >(loc); char const *first = s.c_str(); char const *last = first + s.size(); std::vector<wchar_t> result(s.size()); facet.widen(first, last, &result[0]); return std::wstring(result.begin(), result.end()); } std::string narrow_string(std::wstring const &s, std::locale const &loc, char default_char = '?') { if (s.empty()) return std::string(); std::ctype<wchar_t> const &facet = std::use_facet<std::ctype<wchar_t> >(loc); wchar_t const *first = s.c_str(); wchar_t const *last = first + s.size(); std::vector<char> result(s.size()); facet.narrow(first, last, default_char, &result[0]); return std::string(result.begin(), result.end()); } char const *russian_locale_designator = "rus"; // обозначение локали зависит от реализации, // "rus" подходит для VC++ int main() { std::locale loc(russian_locale_designator); std::wstring const s = L"русский текст"; std::string const sa = ::narrow_string(s, loc); std::wstring const sw = ::wide_string(sa, loc); std::locale::global(loc); std::wcout << "original wide: " << s << std::endl; std::cout << "wide -> narrow: " << sa << std::endl; std::wcout << "narrow -> wide: " << sw << std::endl; } Возникла необходимость преобразования wstring в string. Из упомянутых здесь способов этот больше всего приглянулся. Но подскажите пожалуйста почему при первом преобразовании он из строки "ddd" делает строку "?ddd"? Причем если делать два преобразования подряд, то во второй раз символ спереди не добавляется. Я в крайнем случае могу его просто отбрасывать, но во-первых интересно знать причину, во-вторых это наводит на мысль - а не ждут ли меня еще какие сюрпризы? (способ Киллера кстати тоже прибавляет символ спереди) В этих строках у меня железно только цифры и латинские буквы, так что никакие проблемы с кодировками меня сейчас не интересуют, нужно просто самое элементарное преобразование. |
Сообщ.
#16
,
|
|
|
Ataru, вот еще вариант на винапи
![]() ![]() void utf16to8( const std::wstring& utf16, std::string& utf8 ) { char mUtf8[ MAX_PATH ] = { 0 }; int len = WideCharToMultiByte(CP_UTF8, 0, utf16.c_str(), -1, NULL, 0, 0, 0); if (len >= 1 && len < MAX_PATH ) { WideCharToMultiByte(CP_UTF8, 0, utf16.c_str(), -1, mUtf8, len, 0, 0); } utf8 = mUtf8; } void utf8to16(const std::string& utf8, std::wstring& utf16) { wchar_t mUtf16[ MAX_PATH ] = { 0 }; int len = MultiByteToWideChar(CP_UTF8, 0, utf8.c_str(), -1, NULL, 0); if ( len >= 1 && len < MAX_PATH ) { MultiByteToWideChar(CP_UTF8, 0, utf8.c_str(), -1, mUtf16, len ); } utf16 = mUtf16; } |
Сообщ.
#17
,
|
|
|
Этот способ тоже добавляет в начало символы и тоже только при первом преобразовании. Из "text" делает "text"
И почему названия функций и переменных такие странные? utf8 это и есть юникод. Корректнее было бы назвать Utf8ToASCII(), мне во всяком случае нужно именно такое преобразование Добавлено Все, сорри, вопрос снимается. Этот первый символ оказывается раньше появляется, т.е. проблема в другом месте. Просто в отладчике его не видно, если смотреть значение wstring, но он есть в буфере, из которого эта wstring создается. |
Сообщ.
#18
,
|
|
|
Добавляемые символы - это BOM (Byte Order Mark). Показывают порядок байт в широких символах. Добавляются скорее всего текстовым редактором (виндовый Notepad так делает), хотя в файле с кодировкой UTF-8 их ставить не обязательно. По стандарту их наоборот не должно быть.
WideChar и MultyByte это исторические названия, пришли из времён, когда названий UNICODE и UTF-8 ещё не придумали. |
Сообщ.
#19
,
|
|
|
Цитата Ataru @ И почему названия функций и переменных такие странные? utf8 это и есть юникод. Корректнее было бы назвать Utf8ToASCII(), мне во всяком случае нужно именно такое преобразование конвертация зависит от флагов у APIшной функции MultiByteToWideChar, в моем случае это CP_UTF8 а вам надо CP_ACP Цитата Ataru @ Корректнее было бы назвать Utf8ToASCII() С флагом CP_ACP, соглашусь, было бы корректнее. но у меня именно UTf8 <-> UTF16 |