//从任意节点开始遍历目录树,Copyright (C) Y.B.Chen //已经在 Borland C++ 3.1 for DOS 和 Borland C++ Builder 6.0 下编译通过 #include <stdio.h> #include <conio.h> #include <dir.h> #include <dos.h> #include <string.h> int lines = 0; //保存已经显示出几行了,如果到了一屏需要暂停 int bQuit = 0; //是否按了Esc键,如果按了Esc键,此数为非零,程序退出 void clines(void) //计算已经输出的行数,如果满一屏就暂停 { unsigned int k; if(lines&&(!(lines%23))) { printf("Press any key, or Esc to quit..."); if((k=getch())==0) //函数等待用户按键,如果=0表示功能键 k=getch()<<8; //需要再次重新调用getch判断具体是哪个键 //例如如果你按了向上移动光标的光标键,getch()返回值是0 //但是再次调用getch()时无条件返回0x48,即大写'H'的ASCII //如果不这样编,程序就误认为是按了两次按键,一次是'\0', //一次是'H',为了避免混淆'H'和以光标键,把移光标键移动到 //变量'k'的高8位,即k=0x4800 //最后结论: k==0x0048是大写'H',k==0x4800是移光标键 if(k==27) //Esc键的ASCII是27 bQuit = 1; printf("\r\n"); } lines++; } void dirall(const char *path) //递归函数,从path节点遍历目录树 { struct ffblk blk; int done; char np[MAXPATH]; strcpy(np,path); strcat(np,"\\*.*"); printf("==========================================\r\n"); clines(); printf("%s\r\n", path); clines(); printf("------------------------------------------\r\n"); clines(); //遍历本级目录(参数path的目录) done = findfirst(np, &blk, FA_RDONLY|FA_HIDDEN|FA_SYSTEM|FA_ARCH|FA_DIREC); while(!done && !bQuit) { if(blk.ff_attrib&FA_DIREC) //得到的文件名是目录(文件夹) { //分解文件的各个信息(日期、时间、长度等),显示出来 printf("%-12s <dir> %04d-%02d-%02d %02d:%02d:%02d\r\n", blk.ff_name, (blk.ff_fdate>>9)+1980, (blk.ff_fdate>>5)&0x0f, blk.ff_fdate&0x1f, blk.ff_ftime>>11, (blk.ff_ftime>>5)&0x3f, (blk.ff_ftime<<1)&0x3f); } else //得到的文件名是文件 { //分解文件的各个信息(日期、时间、长度等),显示出来 printf("%-12s %9ld %04d-%02d-%02d %02d:%02d:%02d\r\n", blk.ff_name, blk.ff_fsize, (blk.ff_fdate>>9)+1980, (blk.ff_fdate>>5)&0x0f, blk.ff_fdate&0x1f, blk.ff_ftime>>11, (blk.ff_ftime>>5)&0x3f, (blk.ff_ftime<<1)&0x3f); } clines(); //计算是否满一屏,如果是,暂停 done = findnext(&blk); //下一个文件 } #ifdef __WIN32__ findclose(&blk); //Windows 32比特版本的编译器要求关闭ffblk //实际是"长文件名"系统要求必须这样做 //Windows 95 以后的版本或者NT4.0以后的版本 //如果使用了长文件名系统,在控制台模式运行 //的32位程序和控制台下调用了LFN中断的16位程序 #endif //遍历下一级目录(参数path的下一级) done = findfirst(np, &blk, FA_DIREC); while(!done && !bQuit) { //文件名为"."和".."分别表示当前目录和上级目录,不在遍历范围,如果遍历则造成死循环 if((blk.ff_attrib&FA_DIREC) && (strcmp(blk.ff_name,".") && strcmp(blk.ff_name,".."))) { strcpy(np,path); //需要遍历的目录名(np) = path + blk.ff_name strcat(np,"\\"); strcat(np,blk.ff_name); dirall(np); //遍历下一级目录(np),(递归调用) } done = findnext(&blk); //下一个目录 } #ifdef __WIN32__ findclose(&blk); //Windows 版本的编译器要求关闭ffblk #endif } int main(void) { dirall("C:"); //从"C:"节点开始遍历 getch(); return 0; }

评论