biketrials.ru

biketrials.ru (http://biketrials.ru/live/index.php)
-   Забор (http://biketrials.ru/live/forumdisplay.php?f=13)
-   -   вопрос по с++ (http://biketrials.ru/live/showthread.php?t=16175)

TEMA4 02.07.2007 18:37

вопрос по с++
 
мне нужно чтоб программа открывала текстовые файлы, например с расширением log, причём она должна начать с заданной пользователем папки и далее искать во всех вложенных. как это вообще можно сделать? а то я могу открыть тока заданный файл.. можно было сделать конечно на bash с регулярными выражениями но нужно именно под винду(((
ну или где про это почитать можно? я у страуструпа чего-то не нашёл....
заранее спасибо)

t.w.o. 02.07.2007 19:08

может DC++, или нет, знач я такой не знаю

mil_alex 02.07.2007 19:22

для си/си++ есть функция findfirst() которая получает шаблон, например строку "*.*" и проводит поиск первого совпадающего с шаблоном элемента каталога (файла или подкаталога). Затем вызывают findnext() и продолжают ее вызывать пока она возвращает положительный результат. При этом функции заполняют информацией структуру, в которой оказывается имя, длина, атрибуты, время создания файла и т.п.

надо, в общем случае, проверять является ли очередной найденный элемент каталога файлом или каталогом и, в этом случае, рекурсивно вызывать эту же подпрограмму для найденного подкаталога.

если не пользоваться ф-циями стандартной библиотеки си/си++, тогда на WinAPI32 это выглядит как FindFirstFile() и FindNextFile + FindClose, которые работают точно так же как и рантайм библиотеки си/си++

mil_alex 02.07.2007 19:30

во кусок оч старого кода)
Код:

static int ProcessFolder3(int level)
{
  HANDLE hFind;
  WIN32_FIND_DATA fnd;
  bool flag;

  int found=0; // have found something in this folder?

  hFind = FindFirstFile( "*.*", &fnd );
  flag=TRUE;

  if (hFind != INVALID_HANDLE_VALUE )
  while (flag)
  {
      if ( fnd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
      {
        if ( *((short *) &fnd.cFileName[0] ) == 0x002E ) goto b; // skip "."
        if ( (*((uint *) &fnd.cFileName[0] ) & 0x00FFFFFF) == 0x002E2E ) goto b; // skip ".."

        found++;

        if (SetCurrentDirectory(fnd.cFileName))
        {
            int old_path_len = strlen(my_path);
            strcat(my_path, fnd.cFileName); // append this folder name
            strcat(my_path, "\\");
            int f=ProcessFolder3(level+1);
            if (! SetCurrentDirectory(".."))
            {
              printf("error: can't cd ..\n");
              break;
            }
            my_path[old_path_len] = 0; // trim this folder name
            if (!f)
            {
              if (level) RemoveDirectory(fnd.cFileName);
            }
        }
        else
        {
            printf("error: can't cd '%s'\n", fnd.cFileName);
            break;
        }

        goto b;
      }

      strcpy(this_file, fnd.cFileName ); // local
      wsprintf( target_file, "%s%s%s", target_path, my_path, fnd.cFileName );
      found++;

      b:
      flag=FindNextFile( hFind, &fnd );
  }
  else
      found = 1; // for safety, do not assume failed directories empty
     
  FindClose(hFind);
  return found;
}

не надо его запускать) он если я верно помню стирает пустые вложенные каталоги. Просто как примерчеГ

TEMA4 02.07.2007 19:38

круто) спасибо большое, ща буду разбираться!

mil_alex 02.07.2007 19:48

вдогонку, открыть файл для чтения это
FILE *f = fopen(name, "r");

далее
while (fgets(буфер, его размер, f))
{
// тут делаем со строкой в буфере чо нада
}
и в конце fclose(f);

в хелпе эти слова должны быть)

а на винапи32
HANDLE h = CreateFile(непомню));
ReadFile(буфер, размер, скока было прочитано, h); // примерно так
CloseHandle(h); // в конце

TEMA4 03.07.2007 14:48

такой ещё вопрос созрел:

мне нужно искать файлы *.log в каталоге который передан как параметр через командную строку.
передаю вот так int main(int argc, char* argv[]) - то есть имя каталога у меня будет в argv[1].
файлы ищу с помощью findfirst()
findfirst("*.log", &ffblk,0); так я найду все файлы в текущем каталоге.. а как туда приделать ещё каталог переданный через командную строку? а то тут у меня постоянно всякие несоответствия...
findfirst(argv[1] + "*.log", &ffblk,0); - так не работает

mil_alex 03.07.2007 15:33

мелкое замечаньице: прежде чем в проге использовать argv[] с любым ненулевым индексом, надо проверить argc и убедиться, что оно больше единицы, т.е. када прога без параметров запускается, то argc=1 и argv[0] содержит путь к её файлу exe, а во всех остальных случаях надо проверить например что argc действительно ==2 и после этого пользоваться строкой из argv[1], иначе потенциальный баг будет.

соединить строки можно strcat(a, b) (вместо перегруженного оператора + ) и вроде в хелпе пишут что вот так
findfirst("c:\\dos\\test\\*.log", бла-бла
вроде можно и будет работать)

вообще я делал иначе, не уверен что так будет лучше - но оно работало))

берем каталог из командной строки и делаем туда cd то есть change dir. Он станет текущим, после чего там findfirst("*.log", бла-бла
Когда от findnext() выяснится что больше подходящих файлов нема, можно сделать cd обратно в каталог, откуда программа была запущена.

это см. про getcurdir() chdir() и их аналоги.


и еще, для пущей безопасности, лучше не использовать место в памяти, выделенное операционкой под массив параметров командной строки, в своих целях. То есть, не копировать "в" argv[] ничего и не присоединять к его имеющимся строкам другие строки.

т.е. вот как-то так:

char tmp[512];
strcpy(tmp, argv[1] ); // неплохо бы проверить длину строки и убедиться, что она влезет в 512 байт минус 1
strcat(tmp, "*.log"); // здесь то же самое, плюс надо проверить что последний символ в tmp это слэш (косая черта), и если юзер в командной строке указал путь без слэша в конце, добавить в tmp еще и слэш.

undirecthands 04.07.2007 01:28

Код:

goto b;
Сорри за оффтоп, уписался когда увидел эту конструкцию :D

mil_alex 04.07.2007 01:46

ааа я не религиозен. полстраны оттрахали моск Паскалем и люди со школьной скамьи конструируют невообразимой красоты лестницы (в смысле ступеньки) из вложенных if-ов, do...until-ов и прочих эндов с бегинами, вместо простых, читаемых и эффективных исходников))

тут кстати есть над чем в другом месте посмеяться - я вот думаю что будучи скомпилирован для моторола, код работать перестанет ввиду другого порядка байт в машинном слове. а у меня проверка является ли найденная строка (имя файла или каталога) "." или ".." выполнена одной командой сравнения двух целых чисел, вместо вызова ф-ции strcmp()

TEMA4 04.07.2007 05:04

спасибо огромное) ты мозг!
параметры я проверял, но не подумал что в си можно использовать cd - хотя очень полезно) опять правда всякие проблемы начались(( завтра может разберусь..

mil_alex 04.07.2007 09:53

незачто)
имелось в виду что можно и выполнить команду cd (посредством exec/system т.е. фактически вызвать command.com гыгы) и вызвать ф-цию смены каталога (не трогая командный процессор). Второе мне кажется надежнее)


Часовой пояс GMT +4, время: 14:19.

Powered by vBulletin® Version 3.8.4
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd. Перевод: zCarot