Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > поведение wcstombs


Автор: mrgloom 26.11.2013, 12:59
Код

bool func( const TCHAR* fileName)
{
    #ifdef _UNICODE
        char path[MAX_PATH];
        wcstombs(path, fileName, ARRAYSIZE(path));
    #else
        const char* path = strFileName;
    #endif


почему то wcstombs обрезает путь, то ли из-за того что русские буквы в названии папок то ли из-за того что пробелы, в чём причина?

Автор: Static 26.11.2013, 13:51
Первый раз вижу макрос ARRAYSIZE, быстрое гугление показало, что он возвращает количество элементов в массиве. А функция wcstombs третьим параметром принимает количество байт

Автор: mrgloom 26.11.2013, 14:14
замена на sizeof(path) не дала результата, тем более что вроде как размер char это и есть 1 байт.

похоже отрезает путь именно до папки с русским названием.

Добавлено через 3 минуты и 13 секунд
например D:\Новая папка\file.dat
превращается в D:\

а например D:\test folder\file.dat  работает

Автор: mrgloom 26.11.2013, 16:03
по всей видимости
Цитата


If wcstombs encounters a wide character it cannot convert to a multibyte character, it returns –1 cast to type size_t and sets errno to EILSEQ.


как раз возвращает -1.


только непонятно почему не может сконвертировать русские буквы?

Автор: Static 26.11.2013, 16:04
mrgloom, а что функция возвращает при этом? -1?

опередил smile Вот тут не знаю. Может, надо текущую локаль установить?

Автор: mrgloom 26.11.2013, 16:57
http://habrahabr.ru/post/164193/
боль


вообще функция определена как
Код

bool func( const TCHAR* fileName)

а вызывается
Код

func(dlg.GetPathName())

т.е. передается CString вроде как, может он там автоматом конвертируется?
т.е. даже не надо писать 
Код

func((LPCTSTR)dlg.GetPathName())


и да у меня юникод проект, если это важно.

Автор: mrgloom 26.11.2013, 17:41
вообщем так вроде работает
Код

CT2CA path(fileName);

Автор: smalcom 28.11.2013, 17:36
а wcslen заюзать, не?

Автор: mrgloom 28.11.2013, 18:20
дело то не в этом, там от длины не зависит, именно обрубает начиная от вхождения первой русской папки.

хоть вместо
Код

char path[MAX_PATH];
wcstombs(path, fileName, ARRAYSIZE(path));


напиши
Код

wcstombs(path, fileName,MAX_PATH);

Автор: vinter 28.11.2013, 18:36
Ну что же не читаем документацию на функции?
Цитата(MSDN)

wcstombs  uses the current locale for any locale-dependent behavior; _wcstombs_l is identical except that it uses the locale passed in instead

Цитата(cplusplus.com)

The behavior of this function depends on the LC_CTYPE category of the selected C locale.

Автор: mrgloom 29.11.2013, 09:37
ну да можно и через изменение локали, но я решил с этим не разбираться, потому что непонятно какую ставить и она как я понял меняется глобально, т.е. потом её надо менять обратно?

Автор: vinter 29.11.2013, 09:46
да, менять придётся на всё приложение. Вообще, нужно использовать юникод везде и не переводить в ANSI+codepage. 

Автор: mrgloom 29.11.2013, 12:24
дело в том, что в функцию передаётся TCHAR* , а внутри используется библиотечная функция которая хочет char* .

Автор: xvr 2.12.2013, 12:38
TCHAR у вас Unicode, а char - ANSI. Перевод из Unicode в ANSI вещь неоднозначная, и сама по себе зависит от локали, в которой вы хотите этот  самый ANSI получить. Так что для любой функции перевода Unicode -> ANSI нужно так или иначе задавать локаль (или кодовую страницу). Для wcstombs это делается настройкой локали в CRT, для http://msdn.microsoft.com/en-us/library/windows/desktop/dd374130%28v=vs.85%29.aspx кодовая страница задается при вызове


Автор: akizelokro 14.12.2013, 13:50
TCHAR это TCHAR, в случае если определен _UNICODE это wchar_t (из башки вылетело как wide string символ обозначается, wchar_t или wchar), в ином случае это char (multibyte string character). Это подставляется на стадии компиляции.

В случае, если идут проблемы с конвертацией национальных симоволов (кириллицы в том числе) в символьный массив char[] порядок действий следующий:
1. Проверяется locale на соответствие национальной кодировке
2. Если и это не срабатывает, проверяется на размер массива-приёмника (на каком символе обрезается, на первом национальном или в другом месте). судя по тому, что размер массива установлен в MAX_PATH, в данном случае проблемка с установкой национальной кодовой страницы.

В данном случае можно переписать
Код

        char path[MAX_PATH];
        wcstombs(path, fileName, ARRAYSIZE(path));

на
Код

        char path[MAX_PATH];
        wcstombs(path, fileName, MAX_PATH);


В случае с CString уже на стадии копиляции происходит преобразование TCHAR в wchar_t или char, а дальше подыскивается способ преобразования CStringA или CStringW к TCHAR* (используемый по умолчанию при компиляции тип CString тоже зависит от наличия либо отстутсвия _UNICODE)

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)