目录树的遍历及其应用
一、目录树的遍历 在用微机编写程序的过程中,往往需要对整个磁盘上的所有目录及下面的文件依一定的 条件进行某项特殊操作。如在整个磁盘上查找某一类型文件是否存在,有时还需要对找 到的目录进行改名、删除等特殊操作。这都要求能访问磁盘上所有的目录。大家知道, DOS操作系统采用的是树型目录结构,如附图所示: 要访问磁盘上所有的子目录,这在数据结构中称之为树的遍历,即依次访问磁盘上所有 的子目录,并且每个子目录只能被访问一次。而树的遍历有很多算法,其中递归法是较 为普遍的一种。所谓递归,就是指一个直接调用自己或通过一系列的过程调用语句间接 地调用自己的过程。针对上述树型目录结构而言,就是要设计这样的一个过程,用来搜 索当前目录下的所有文件和子目录,进行某项特殊操作如显示、删除、拷贝等后,若有 子目录就依次进入各个下级子目录,然后再调用这个过程。这样当一级子目录全部进入 后,整个磁盘上的所有目录就被访问且只被访问了一次。对上述目录结构而言,先对根 目录搜索,发现有A目录和B目录,就进入A目录再搜索,发现子目录A1、A2、A3子目 录,就再进入A1子目录,再搜索。若没有子目录了。就进入A2子目录搜索,完后进入A3 子目录搜索,然后进入B子目录搜索下面的子目录。这样当B子目录完成后,这样一个目 录结构就被全部遍历了。 二、遍历目录树的应用 在用C语言编程过程中,有时需要对磁盘上的目录或文件进行扫描以确定某类文件是否存 在,这时就可以采用目录树的遍历。依据在访问每一个目录时所进行的不同操作,就可 编程完成某些特定的功能。下面是作者编写的几个应用程序,可以弥补DOS操作命令的不 足。 1.删除磁盘上所有特定类型的文件 在使用微机的过程中,许多软件要在磁盘上产生某些文件。如Windows产生的临时文件 (.tmp)。这些文件在硬盘上将占用大量的磁盘空间。若手工删除,十分麻烦。为此,笔 者用C语言编制了一个程序DELP.C,经编译、链接成DELP.EXE。其原理就是在访问每一 个目录的过程中,查找是否有满足要求的文件,若有就删除。如果删除硬盘上所有 CHKLIST.MS,只需执行DELP CHKLIST.MS即可。 DELP.C #include ″stdio.h" #include ″stdlib.h″ #include ″dos.h″ #include ″dir.h″ #include ″string.h″ struct ffblk f,ff; int i,node,done; char dir[100][MAXDIR],file[50]; char mid[MAXDIR],curr[MAXDIR]; repeat(); delpro(); int main(int argc,char argv[]) { if(argc!=2) { printf(″/n Usage:delp filename /n″); exit(0); } strcpy(file,argv[1]); strupr(file); getcwd(curr,MAXDIR); i=1; system(″cd//″); getcwd(dir[i],MAXDIR); printf(″/n/t/tFILE %s in directory will be deleted.″,file); printf(″/n/t/t==============″); repeat(); } /目录树遍历函数/ repeat() { getcwd(mid,MAXDIR); delpro(); /调用删除函数/ done=findfirst (″.″,& ff,FA_DIREC|FA_SYSTEM|FA_HIDDEN|FA_ARCH|FA_RDONLY); while(!done) { if(((ff.ff_attrib&0xf0)==16)&&strcmp(ff.ff_name,″.″)&&strcmp (ff.ff_name,″..″)) { i=i+1; if(strlen(mid)==3) { strcpy(dir[i],mid); strcat(dir[i],ff.ff_name); } else { strcpy(dir[i],mid); strcat(dir[i],″//″); strcat(dir[i],ff.ff_name); } } done=findnext(&ff); } if(i==1) { chdir(curr); exit(0); } chdir(dir[i]); i--; repeat(); /递归调用自己/ } /删除符合条件的文件/ delpro() { node=findfirst(file,&f,FA_RDONLY|FA_HIDDEN|FA_SYSTEM|FA_ARCH); while(!node) { unlink(f.ff_name); printf(″/n/t/t%14s %s″,f.ff_name,mid); node=findnext(&f); } } 2.快速切换子目录 树型目录结构主要是为了DOS能够较好地进行目录和文件管理。但对用户的使用而言,并 不是很方便的事。如我校微机房中学生经常要用到的五笔字型练习软件“五笔高手速 成”(WT),在F:/CAI/PC/WUBI/WT这样一个四级子目录下,运行该软件,十分麻烦,怎 样不键入完整路径,就能一步进入所需的目录呢? 笔者同样利用目录树的遍历,设计了一个工具Q.EXE,使用时只需键入目录名或者是目录 名中的一部分,就能一步进入与之匹配的目录中,大大简化了操作,用起来十分方便。 其原理是当执行Q[盘符:]时。将搜索指定盘上的所有目录结构我保存于硬盘根目录下 DIR.DAT文件中。以后要进入某一子目录时,只需执行Q目录名或目录名的一部分。这时 就在DIR.DAT中查找与给定目录名最相匹配的路径。然后转至路径相应的目录。如上述要 进入WT目录中,只要先执行Q F:,将F:盘中所有的目录信息保存于C:盘下。以后要进 入WT目录时,执行Q WT即可。要进入该盘其它目录,如UCDOS也只需执行Q UCDOS。 3.磁(光)盘数据检查 在购买光盘软件的过程中,经常需要对光盘软件的好坏进行检查。而光盘数据多达几百 兆,怎样检查呢?一般方法是判断光盘数据是否能读出。利用拷贝到虚拟设备NUL的方法 可以检查数据的好坏,也能节约大量的磁盘空间。但光盘目录有很多个,若逐个进入检 查,就很麻烦了。利用上述的目录树的遍历,就能很方便地解决这个问题。其原理是在 访问每一个目录时,执行一次拷贝到虚拟设备上操作COPY . NUL。若能通过则是好 的,否则就表明光盘数据有损坏。遍历完整个目录树后,就检查完了所有文件。也可只 检查指定目录及其所有子目录,只需遍历该目录就可。?