Поиск
файлов
В качестве примера
использования рекурсии рассмотрим задачу поиска файлов. Пусть нужно получить
список всех файлов, например, с расширением bmp, которые находятся в указанном
пользователем каталоге и во всех подкаталогах этого каталога.
Словесно алгоритм обработки
каталога может быть представлен так:
1. Вывести список всех
файлов удовлетворяющих критерию запроса.
2. Если в каталоге
есть подкаталоги, то обработать каждый из этих каталогов.
Приведенный алгоритм
(его блок-схема представлена на рис. 12.4) является рекурсивным: для того чтобы
обработать подкаталог, процедура обработки текущего каталога должна вызвать
сама себя.
Рис. 12.4. Рекурсивный
алгоритм поиска файлов
Вид диалогового окна
программы приведен на рис. 12.5, текст — в листинге 12.3.
Поле Файл (Edit1)
используется для ввода имени искомого файла или маски (для поиска файлов одного
типа). Имя каталога, в котором нужно выполнить поиск, можно ввести непосредственно
в поле Папка или выбрать из стандартного диалогового окна Обзор папок,
которое появляется в результате щелчка на кнопке Папка. Окно Обзор
папок (рис. 12.6) выводит на экран стандартная функция Seiectoirectory.
Следует обратить внимание, что имя каталога, который используется в диалоговом
окне Обзор папок в качестве корневого, должно передаваться функции SeiectDirectory
как Строка WhideChar. Для Преобразования обычной строки в строку WideChar использована
функция StringToWhideChar.
Рис. 12.5. Окно
программы Поиск файлов
Рис. 12.6. Диалоговое
окно Обзор папок появляется в результате щелчка на кнопке Папка
Основную работу выполняет
рекурсивная функция Find. У функции Find один-единственный параметр — структура
searchRec, которая используется функциями FindFirst и FindNext для поиска соответственнопервого
и следующего файла, удовлетворяющего критерию поиска. Следует обратить внимание
на то, как осуществляется перебор каталогов в текущем каталоге. Если текущий
каталог не корневой, то помимо обычных, то есть имеющих имя, в каталоге есть
еще два каталога: .. и ., которые обозначают каталог предыдущего уровня. Эти
два каталога не обрабатываются, так как при входе в эти каталоги фактически
выполняется выход (переход) в родительский каталог. Если этого не учесть, то
программа зациклится.
Листинг 12.3.
Программа поиск файлов
// поиск файла в указанном каталоге и его подкаталогах
// используется рекурсивная процедура Find
unit FindFile_;
interface
uses
Windows, Messages, SysUtils, Variants,
Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, FileCtr;
type
TForm1
= class(TForm)
Editl:
TEdit; // что искать
Edit2:
TEdit; // где искать
Memo1:
TMemo; // результат поиска
Button1:
TButton; // кнопка Поиск
Button2:
TButton; // кнопка Папка
Label1:
TLabel;
Label2:
TLabel;
Label3:
TLabel;
Label4:
TLabel;
procedure
Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{
Private declarations }
public
{ Public declarations }
end;
var
Form1:
TForm1;
implementation
{$R
*.dfm}
var
FileName:
string; // имя или маска искомого файла
cDir:
string;
n:
integer; // кол-во файлов, удовлетворяющих запросу
//
поиск файла в текущем каталоге
procedure
Find;
var
SearchRec:
TSearchRec; // информация о файле или каталоге
begin
GetDir(0,cDir); // получить имя текущего каталога
if
cDir [length (cDir) ] <> 'V then cDir := cDir+'\';
if FindFirst(FileName, faArchive,SearchRec) = 0
then
repeat
if (SearchRec.Attr and faAnyFile) = SearchRec.Attr
then
begin
Form1.Memo1.Lines.Add(cDir + SearchRec.Name);
n
:= n + 1; end; until FindNext(SearchRec) <> 0;
// обработка подкаталогов текущего каталога
if
FindFirst('*', faDirectory, SearchRec) = 0 then repeat
if
(SearchRec.Attr and faDirectory) = SearchRec.Attr then begin
// каталоги .. и . тоже каталоги,
// но в них входить не надо .'.'.'
if
SearchRec.Name[1] <> '.' then begin
ChDir(SearchRec.Name);// войти в каталог
Find; // выполнить поиск в подкаталоге
ChDir('..');// выйти из каталога
end;
end;
until FindNext(SearchRec) <> 0;
end;
/ возвращает каталог, выбранный пользователем
function GetPath(mes: string):string;
var
Root: string; // корневой каталог
pwRoot : PWideChar; Dir: string;
begin
Root
:= '';
GetMem(pwRoot, (Length(Root)+1) * 2);
pwRoot := StringToWideChar(Root, pwRoot, MAX_PATH*2);
if
SelectDirectory(mes, pwRoot, Dir) then
if length(Dir) =2 // пользователь выбрал корневой каталог
then
GetPath := Dir+'\' else GetPath := Dir else
GetPath := '';
end;
щелчок
на кнопке Поиск
procedure TForml.ButtonlClick(Sender: TObject);
begin
Memo1.Clear;
// очистить поле Memol
Label4.Caption
:= '';
FileName
:= Edit1.Text; // что искать.
cDir
:= Edit2.Text; // где искать
n:=0;
// кол-во найденных файлов
ChDir(cDir);
// войти в каталог начала поиска
Find;
// начать поиск
if
n = 0 then
ShowMessage('Файлов, удовлетворяющих критерию поиска нет.')
else Label4.Caption := 'Найдено файлов:' + IntToStr(n);
end;
//
щелчок на кнопке Папка
procedure
TForml.Button2Click (Sender: TObject);
var
Path:
string; begin
Path
:= GetPath('Выберите папку');
if
Path <> ''
then Edit2.Text := Path;
end;
end.
Релятивисты и позитивисты утверждают, что "мысленный эксперимент" весьма полезный интрумент для проверки теорий (также возникающих в нашем уме) на непротиворечивость. В этом они обманывают людей, так как любая проверка может осуществляться только независимым от объекта проверки источником. Сам заявитель гипотезы не может быть проверкой своего же заявления, так как причина самого этого заявления есть отсутствие видимых для заявителя противоречий в заявлении.
Это мы видим на примере СТО и ОТО, превратившихся в своеобразный вид религии, управляющей наукой и общественным мнением. Никакое количество фактов, противоречащих им, не может преодолеть формулу Эйнштейна: "Если факт не соответствует теории - измените факт" (В другом варианте " - Факт не соответствует теории? - Тем хуже для факта").
Максимально, на что может претендовать "мысленный эксперимент" - это только на внутреннюю непротиворечивость гипотезы в рамках собственной, часто отнюдь не истинной логики заявителя. Соответсвие практике это не проверяет. Настоящая проверка может состояться только в действительном физическом эксперименте.
Эксперимент на то и эксперимент, что он есть не изощрение мысли, а проверка мысли. Непротиворечивая внутри себя мысль не может сама себя проверить. Это доказано Куртом Гёделем.
Понятие "мысленный эксперимент" придумано специально спекулянтами - релятивистами для шулерской подмены реальной проверки мысли на практике (эксперимента) своим "честным словом". Подробнее читайте в FAQ по эфирной физике.