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


Автор: EttoreMajorana 25.5.2017, 15:07
Доброго дня, уважаемые форумчане!
Пытаюсь использовать функции findfirstfile и findnextfile для поиска файла. Первым параметром оно хочет TCHAR, а у меня три переменные строковые с содержимым "C:", "ProgramData" и "settings.ini". Я их склеиваю, но как их преобразовать в TCHAR? И как потом этот TCHAR обратно в обычную строку преобразовать? Нахрена такие танцы с миллионом типов данных? Есть ли простые функции для работы с TCHAR? Та же конкатенация, к примеру? Что за бред? Чтоб начать просто пользоваться функцией, надо ещё применить десяток непонятных технологий!

Автор: feodorv 25.5.2017, 22:24
Цитата(EttoreMajorana @  25.5.2017,  15:07 Найти цитируемый пост)
Нахрена такие танцы с миллионом типов данных?

Вам не приходило в голову, что всё это https://habrahabr.ru/post/164193/?

Автор: EttoreMajorana 26.5.2017, 17:34
Да, спасибо! Именно на эту статью я набрёл самостоятельно. Но мне всё-равно непонятно, почему довольно-таки умный компилятор не переваривает конструкцию типа:
Код

HANDLE nh = FindFirstFile((TCHAR)strcat("C:\\", win.cFileName), &nw);


P.S.: Только вкатываюсь в С++ и немного шокирован происходящим. Как бы то ни было строки и в Африке строки, но только не в С++!!! Тут если ты работаешь с файловой системой, то строки у тебя TCHAR, если работаешь с сетью, то строки у тебя WCHAR, строки в старых учебниках и у студентов в лабах - это массивы символов, строки в новых учебниках - это классы, классы, классы... И всё это живёт своей жизнью! И меж собой никак не соотносится. Вообще никак! Пока очень сложно увидеть в этом хоть какую-нибудь систематику. Да и логика, если по честному, странная тут. Это вообще не похоже на язык высокого уровня. Это гипертрофированный ассемблер на стероидах!

P.P.S.: Теперь становится понятно, почему софт написанный на С++ настолько уязвим и потенциально изобилует ошибками. Этот инструмент реально позволяет "выстрелить себе в ногу"!

Автор: xvr 26.5.2017, 22:35
Для начала нужно уяснить, что в 'голом' С (и С++ тоже) строк нет вообще. Есть только массивы символов, причем фиксированной длинны. Поэтому ваш strcat("C:\\", win.cFileName) гарантированно работать не будет вообще. И никакой TCHAR вам не поможет.

Цитата(EttoreMajorana @  26.5.2017,  17:34 Найти цитируемый пост)
Тут если ты работаешь с файловой системой, то строки у тебя TCHAR, если работаешь с сетью, то строки у тебя WCHAR, строки в старых учебниках и у студентов в лабах - это массивы символов, строки в новых учебниках - это классы, классы, классы... 

Как все запущенно  smile char'ов в С/С++ всего 2 - это char и wchar_t, все остальное это рукоблудие MS и писателей библиотек (даже с учетом того, что библиотеки ныне внесены в стандарт)

Когда стало понятно, что со строками в языке совсем беда, в С++ были сделаны (в библиотеке) классы, которые позволили бы работать с нормальными строками - это std::string (ну и std::wstring). В С такой номер не прошел, так что там до сих пор воюют с ними руками.

TCHAR (с сотоварищами) появился тогда, когда до MS дошло, что в мире существует не только Английский язык, но еще много других. В том числе такие, что никак в char не умещались. Раньше MS это поняли в Unicode Consortium и был разработан char пошире, что бы туда уже все влезло. В компиляторах это появилось сильно позже, в виде типа wchar_t. Windows NT уже использовала для всех внутренних строк именно широкую Unicode кодировку.
Но тут стал вопрос - что делать с массой кода на С и С++ который был написан ДО того, и в который никто никакой Unicode не вставлял? И как он будет общаться с системными вызовами, которые теперь хотят Unicode? И что делать тем, кто хочет иметь возможность жить и по старому (с char) и по новому (c Unicode) одновременно?

Вот тут и появился TCHAR и все остальные t*. В зависимости от режима компиляции (он выбирается в свойствах проекта) он становится или char или wchar_t. Все функции WIN32 API так же меняют принимаемые строки параметры в зависимости от типа компиляции - или строки в старых (8ми битных символах) или строки в Unicode. Таким образом, достаточно сменить настройку проекта и старое приложение волшебным образом меняется в новое - Unicode. 
К сожалению реальность подкачала, и при смене настройки обычно старое приложение превращается в свежий труп, который отказывается даже компилиться  smile 
А если учесть, что при создании проекта в VS этот самый Unicode режим по умолчанию включен, то возникает масса проблем. И пытаться решить их приведением char* в TCHAR* сродни попытке реанимации трупа.

Цитата(EttoreMajorana @  26.5.2017,  17:34 Найти цитируемый пост)
Это гипертрофированный ассемблер на стероидах!
Ну его так и создавали. Хотите чего нибудь более высокоуровнево - берите Java или C#



Автор: volatile 28.5.2017, 10:19
Да чел явно тролит. Очередной "критик С/С++", второй день как перешедший с какого-нибудь Java, и решивший что он имеет моральное право критиковать.

Автор: EttoreMajorana 28.5.2017, 13:46
xvr, спасибо за разъяснения! Потихоньку осваиваюсь с С++. И таки да! Я старый троль второй день как перешедший с какого-нибудь Java или ещё с чего-нибудь. Ну а собственно, почему бы и нет? Кто запрещает то? Критиковать и в мыслях не было, потому как я стараюсь не тратить своё и чужое время на это. Но, пардон муа, у любого второй день как перешедшего с какого-нибудь Java обязательно возникнет вопрос, почему по логике вещей конструкция типа:
Код

a="абв"
b="где"
c=a+b

нихрена не работает на С++. Более того, работа со строками в С++ довольно таки нетривиальная весчь!!! Что-бы убедиться в моих словах, достаточно загуглить запрос типа "конкатенация TCHAR".

Автор: volatile 28.5.2017, 14:27
Цитата(EttoreMajorana @  28.5.2017,  13:46 Найти цитируемый пост)
нихрена не работает на С++. 

если вы пишете в С++, то и пишите в С++
Код

std::string a = "абв";
std::string b = "где";
std::string c = a+b;

Автор: EttoreMajorana 28.5.2017, 15:08
Почти разобрался. Осталась одна непонятка!
Имеем:
Код

TCHAR* path; //полный путь
TCHAR* rpath; //правая часть (programdata etc)
TCHAR* lpath; //левая часть (\settings.ini)
TCHAR buff[1024]; //временный буфер

Далее по ходу программы имеем кусок:
Код

wcscpy(buff, lpath); //копируем C:\ProgramData во временный буфер
path = wcscat(buff, rpath); //добавляем к временному буферу \settings.ini

После отработки функций path содержит то что нужно и с работой FindNextFile проблем не возникает. Т. е. я добился чего хотел. Но есть одно но!!! После отработки функции wcscat указатели buff и path содержат один и тот же адрес!!! Как так? Ведь хочется временный буфер и далее пользовать как временный буфер!

Автор: xvr 28.5.2017, 18:45
Цитата(EttoreMajorana @  28.5.2017,  15:08 Найти цитируемый пост)
Ведь хочется временный буфер и далее пользовать как временный буфер! 

Если хочется временный буфер, то вам его придется сделать самому, увы. С и С++ не занимается за программиста вопросами распределения памяти, все руками  smile 
Или используйте стандартную библиотека - std::string & std::wstring. Ее для того и сделали  smile 

Автор: EttoreMajorana 31.5.2017, 08:55
Мне уже начинает нравиться этот язык! Он как ассемблер ZX Spectrum! Можно сделать всё, если только знаешь как! Вот только боюсь что на это "знаешь как" могут годы уйти! Извините за оффтоп.

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