Средствами локали и стримов можно сконвертить ansi -> unicode через std::wstringstream << char const*. Обратный вывод (std::stringstream << wchar_t const*) выводит в стрим значение указателя. std::wstring сливаться в char-поток не хочет. Можно ли как-то сконвертить unicode -> ansi средствами STL?
Мда, и после этого у нас не любят индусов Код (Text): wstring ws; string s; s.resize(ws.size()); std::transform(ws.begin(), ws.end(), s.begin(), wctob);
GoldFinch А чо уж сразу не std::wstring w=L"111"; std::string s = (std::string&)w; ? J0E wctob() не подходит - он не умеет работать с локалью, а мне нужно уметь.
Что бы уметь, учись... читать стандарт: 7.11.1.1/2 The setlocale function selects the appropriate portion of the program’s locale as specified by the category and locale arguments. The setlocale function may be used to change or query the program’s entire current locale or portions thereof. The value LC_ALL for category names the program’s entire locale; the other values for category name only a portion of the program’s locale. LC_COLLATE affects the behavior of the strcoll and strxfrm functions. LC_CTYPE affects the behavior of the character handling functions and the multibyte and wide character functions. LC_MONETARY affects the monetary formatting information returned by the localeconv function. LC_NUMERIC affects the decimal-point character for the formatted input/output functions and the string conversion functions, as well as the nonmonetary formatting information returned by the localeconv function. LC_TIME affects the behavior of the strftime and wcsftime functions. Или гуглить: http://www.google.com/search?q=LC_CTYPE+wctob Или смотреть сорцы: Код (Text): extern "C" int __cdecl wctob( wint_t wchar ) { if (wchar == WEOF) { return (EOF); } else { /* check for one-byte translation */ int retValue = -1; char buf[MB_LEN_MAX]; errno_t e; e = _wcrtomb_s_l(&retValue, buf, MB_LEN_MAX, wchar, NULL, NULL); if (e == 0 && retValue == 1) { return buf[0]; } return EOF; } } /*** *errno_t _wcrtomb_s_l() - Helper function to convert wide character to multibyte character. * *Purpose: * Convert a wide character into the equivalent multi-byte character, * according to the specified LC_CTYPE category, or the current locale. * [ANSI]. * * NOTE: Currently, the C libraries support the "C" locale only. * Non-C locale support now available under _INTL switch. *Entry: * int *pRetValue = the number of chars written (-1 in error case) * char *dst = pointer to multibyte character * size_t sizeInBytes = size of the destinarion buffer * wchar_t wchar = source wide character * mbstate_t *pst = pointer to state (not used) * _locale_t plocinfo = locale info * *Exit: * Returns: * Value of errno if errors, 0 otherwise. *pRetValue is set to -1 in error case. * *Exceptions: * *******************************************************************************/ static errno_t __cdecl _wcrtomb_s_l ( int *pRetValue, char *dst, size_t sizeInBytes, wchar_t wchar, mbstate_t *pst, _locale_t plocinfo ) { _ASSERTE (dst != NULL && sizeInBytes > 0); _LocaleUpdate _loc_update(plocinfo); _ASSERTE (_loc_update.GetLocaleT()->locinfo->mb_cur_max == 1 || _loc_update.GetLocaleT()->locinfo->mb_cur_max == 2); if(pst!=NULL) { *pst=0; } if ( _loc_update.GetLocaleT()->locinfo->lc_handle[LC_CTYPE] == _CLOCALEHANDLE ) { if ( wchar > 255 ) /* validate high byte */ { errno = EILSEQ; if (pRetValue != NULL) { *pRetValue = -1; } return errno; } *dst = (char) wchar; if (pRetValue != NULL) { *pRetValue = 1; } return 0; } else { int size; BOOL defused = 0; if ( ((size = WideCharToMultiByte(_loc_update.GetLocaleT()->locinfo->lc_codepage, 0, &wchar, 1, dst, (int)sizeInBytes, NULL, &defused)) == 0) || (defused) ) { errno = EILSEQ; if (pRetValue != NULL) { *pRetValue = -1; } return errno; } if (pRetValue != NULL) { *pRetValue = size; } return 0; } } А то нашел идола MSDN. Там про btowc тоже интересно "The output of this function is affected by the current LC_TYPE locale". Верь ему больше. P.S. В новой STL будет wstring_convert P.P.S. Не бангалорьте operator=() когда есть конструктор :\
Катит: Код (Text): std::string to_ansi(std::wstring const& wstr, std::locale const& loc) { std::string str; str.resize(wstr.length()); std::wstringstream stream; stream.imbue(loc); std::transform(wstr.begin(), wstr.end(), str.begin(), boost::bind(&std::wstringstream::narrow, &stream, _1, 0)); return str; }
Вот что мне нравится, _DEN_ сначала спросит а потом сам все и сделает )) Тока в таком виде bind тож не катит, кросплатформенность ;-( http://www.gotw.ca/gotw/064.htm И много поточность не кросплатформенна пока что. Хотя МС позаботились: Код (Text): class _LocaleUpdate { _locale_tstruct localeinfo; _ptiddata ptd; bool updated; public: _LocaleUpdate(_locale_t plocinfo) : updated(false) { if (plocinfo == NULL) { ptd = _getptd(); localeinfo.locinfo = ptd->ptlocinfo; localeinfo.mbcinfo = ptd->ptmbcinfo; __UPDATE_LOCALE(ptd, localeinfo.locinfo); __UPDATE_MBCP(ptd, localeinfo.mbcinfo); if (!(ptd->_ownlocale & _PER_THREAD_LOCALE_BIT)) { ptd->_ownlocale |= _PER_THREAD_LOCALE_BIT; updated = true; } } else { localeinfo=*plocinfo; } } ~_LocaleUpdate() { if (updated) ptd->_ownlocale = ptd->_ownlocale & ~_PER_THREAD_LOCALE_BIT; } _locale_t GetLocaleT() { return &localeinfo; } }; А MSDN при том что откуда бы ты еще взял "не умеет работать с локалью", в остальных дока про это есть а там нет )
J0E Ну во-первых, в моем примере и нет конкурирующих точек (общих данных), чтобы возникали проблемы с многопоточностью. А во-вторых, не понял - в чем проблема с boost::bind?
Проблемы с многопоточностью в том, что средствами С++ нельзя создать тред кросплатформенным способом )) Про проблемы с байндом написано у Саттера, непонятен англ. что ли? Стандарт не запрещает реализации std::wstringstream иметь несколько функций narrow с разными сигнатурами. Хотя я сам не редко кладу на это болт ))
J0E Я позволяю себе считать, что boost::thread - кроссплатформенный способ. Насчет Саттера - с первого прочтения не понял в чем именно проблемы. Ну значит std::transform простро заменяется на цикл и все щясливы.