您现在的位置: IT技术文档中心 >> 文档资源 >> 编程语言及开发环境 >> C/C++ >> 文档正文
C语言中deltree程序的实现
作者:未知 文章来源:互联网 点击数: 更新时间:2007-7-22 2:57:20

这里我也把源代码贴一下,方便大家浏览
/* deltree.h */
#ifndef __DELTREE_H
#define __DELTREE_H

// 调试宏
//#define __DEBUG

#define MAX_STACK_SIZE 1024

typedef enum { tpFile, tpDir } ATTRIB_T;
typedef enum { False = 0, True } BOOL_T;

typedef struct tagFileNode {
    
    ATTRIB_T oFSAttr;                        // 节点类型(tpFile = 文件, tpDir = 目录)
    char *pFName;                            // 文件名(当tpDir时,为目录名)

    struct tagFileNode *pParent;            // 父节点
    
    struct tagFileNode *pNext;                // 子节点链表
    struct tagFileNode *pPrev;
    
    struct tagFileNode *pDesecentHead;        // 下一层节点
    struct tagFileNode *pDesecentTail;

} ATTR_FS_TREE_NODE;

// 将物理路径(就是硬文件系统)映射到内存路径树(对应该软件的数据结构)
ATTR_FS_TREE_NODE *DrawPhy2LogTree( char *path ) {
    
    int done;
    int len;
    int top = (int)-1;
    struct ffblk ffblk;
    
    // 临时字符串,为了创建查找使用串而设立
    char *pTempStr;

    // 最大文件夹数
    ATTR_FS_TREE_NODE *pStack[MAX_STACK_SIZE];
    // 临时节点指针
    ATTR_FS_TREE_NODE *pTemp;
    ATTR_FS_TREE_NODE *p;

    // 路径根
    ATTR_FS_TREE_NODE *pRoot = (ATTR_FS_TREE_NODE *)malloc(sizeof(ATTR_FS_TREE_NODE));
    assert( pRoot );

    if( path == (char *)0 )
        return (ATTR_FS_TREE_NODE *)0;
    
    // 创建根
    pRoot->pFName = new char[strlen(path)+1];
    strcpy( pRoot->pFName, path );
    
    pRoot->oFSAttr = tpDir;

    // 初始化根节点
    pRoot->pDesecentHead = (ATTR_FS_TREE_NODE *)0;
    pRoot->pDesecentTail = (ATTR_FS_TREE_NODE *)0;
    pRoot->pNext = (ATTR_FS_TREE_NODE *)0;
    pRoot->pPrev = (ATTR_FS_TREE_NODE *)0;
    pRoot->pParent = (ATTR_FS_TREE_NODE *)0;

    // 压栈处理(这里为了效率不用递归遍历路径)
    pStack[++top] = pRoot;

    while( top >= (int)0 ) {
        // 取出需要处理的路径
        pTemp = pStack[top--];
        
        // 构造查找串,这里我们查找所有文件或目录,在结尾添加"\*.*"即可
        len = strlen(pTemp->pFName);
        pTempStr = new char[len + 5];
        strcpy( pTempStr, pTemp->pFName );
        strcat( pTempStr, "\\*.*" );

        // 进行文件夹与文件的搜索(包含隐藏文件、只读文件,但不包含系统文件)
        done = findfirst( pTempStr, &ffblk, FA_NORMAL | FA_DIREC | FA_RDONLY | FA_HIDDEN );
        while( !done ) {
            // 测试当前获取的路径或文件名是否有效
            // "." 或 ".."都不是我们需要的路径
            if( ffblk.ff_name[0] == '.' ) {
                done = findnext( &ffblk );
                continue;
            }
        
            // 保存文件夹到当前正在处理的节点
            // 当前节点没有子节点
            if( pTemp->pDesecentHead == (ATTR_FS_TREE_NODE *)0 ) {
                pTemp->pDesecentHead = (ATTR_FS_TREE_NODE *)malloc(sizeof(ATTR_FS_TREE_NODE));
                assert( pTemp->pDesecentHead );
                p = pTemp->pDesecentHead;

                // 填充节点内容
                p->pFName = (char *)malloc(sizeof(char) * (len + strlen(ffblk.ff_name) + 2));
                assert(p->pFName);
                strcpy( p->pFName, pTemp->pFName ); // len个字节
                strcat( p->pFName, "\\" );            // 1个字节
                strcat( p->pFName, ffblk.ff_name ); // strlen(ffblk.ff_name) + 1个字节
                
                // 判断是否为文件夹
                if( ffblk.ff_attrib != FA_DIREC )
                    p->oFSAttr = tpFile;
                else {
                    // 将新添加的目录压栈
                    pStack[++top] = p;
                    p->oFSAttr = tpDir;
                }

                p->pDesecentHead = (ATTR_FS_TREE_NODE *)0;
                p->pDesecentTail = (ATTR_FS_TREE_NODE *)0;
                p->pNext = (ATTR_FS_TREE_NODE *)0;
                p->pPrev = (ATTR_FS_TREE_NODE *)0;
                p->pParent = pTemp;
                
                pTemp->pDesecentTail = p;
            }
            // 当前节点有子节点
            else {
                pTemp->pDesecentTail->pNext = (ATTR_FS_TREE_NODE *)malloc(sizeof(ATTR_FS_TREE_NODE));
                p = pTemp->pDesecentTail->pNext;
                assert(p);

                p->pFName = (char *)malloc(sizeof(char) * (len + strlen(ffblk.ff_name) + 2));
                assert(p->pFName);
                strcpy( p->pFName, pTemp->pFName );
                strcat( p->pFName, "\\" );
                strcat( p->pFName, ffblk.ff_name );

                if( ffblk.ff_attrib != FA_DIREC )
                    p->oFSAttr = tpFile;
                else {
                    pStack[++top] = p;
                    p->oFSAttr = tpDir;
                }

                p->pDesecentHead = (ATTR_FS_TREE_NODE *)0;
                p->pDesecentTail = (ATTR_FS_TREE_NODE *)0;
                p->pNext = (ATTR_FS_TREE_NODE *)0;
                p->pPrev = pTemp->pDesecentTail;
                pTemp->pDesecentTail->pNext = p;
                p->pParent = pTemp;

                pTemp->pDesecentTail = p;
            }
            // 继续往下搜索
            done = findnext( &ffblk );
        }
        delete []pTempStr;
        pTempStr = (char *)0;    
    }
    // 完成后返回根路进
    return pRoot;
}

// 删除指定目录树
void DelTree( ATTR_FS_TREE_NODE *pRoot ) {
    int top = (int)-1;
    ATTR_FS_TREE_NODE *pStack[MAX_STACK_SIZE];
    ATTR_FS_TREE_NODE *pTemp, *p;

    BOOL_T flag; // 鉴定指定层是否有下一级目录

    pStack[++top] = pRoot;
    while( top >= (int)0 ) {
        flag = False; // 假设该层没有下一级目录
        pTemp = pStack[top--];
        // 消除该层文件,并将该层的子目录进栈
        p = pTemp->pDesecentHead;
        while( p != (ATTR_FS_TREE_NODE *)0 ) {
            if( p->oFSAttr == tpDir ) { //若是目录则进栈
                if( flag != True ) {    // 该操作必须在子目录压栈前操作
                    flag = True;
                    pStack[++top] = pTemp; // 重新将带有子目录的根目录压栈为了以后的目录删除操作
                }
                pStack[++top] = p;
                p = p->pNext;
            }
            else { //若是文件删除
                // 调试状态下不进行删除操作,为了数据安全
#ifndef __DEBUG
                unlink(p->pFName);
#endif
                printf("%s has been deleted!\n", p->pFName);
                // 删除该节点
                if( p->pPrev != (ATTR_FS_TREE_NODE *)0 )
                    p->pPrev->pNext = p->pNext;
                if( p->pNext != (ATTR_FS_TREE_NODE *)0 )
                    p->pNext->pPrev = p->pPrev;
                if( p == pTemp->pDesecentHead )
                    pTemp->pDesecentHead = p->pNext;
                else if( p == pTemp->pDesecentTail ) {
                    if( p->pPrev != (ATTR_FS_TREE_NODE *)0 )
                        p->pPrev->pNext = (ATTR_FS_TREE_NODE *)0;
                    pTemp->pDesecentTail = p->pPrev;
                }
                // 暂时将p->pNext压栈进行删除操作
                pStack[++top] = p->pNext;
                // 删除名称项
                free(p->pFName);
                free(p);
                p = pStack[top--];    
            }
        }
        // 说明该目录没有下一层子目录,直接删除该目录
        if( flag == False ) {
#ifndef __DEBUG
            rmdir( pTemp->pFName );
#endif
            printf("[%s] has been removed!\n", pTemp->pFName);
            p = pTemp->pParent;
            
            if( pTemp->pPrev != (ATTR_FS_TREE_NODE *)0 )
                pTemp->pPrev->pNext = pTemp->pNext;
            if( pTemp->pNext != (ATTR_FS_TREE_NODE *)0 )
                pTemp->pNext->pPrev = pTemp->pPrev;
            
            if( p != (ATTR_FS_TREE_NODE *)0 ) {
                if( pTemp == p->pDesecentHead )
                    p->pDesecentHead = pTemp->pNext;
                else if( pTemp == p->pDesecentTail ) {
                    if( pTemp->pPrev != (ATTR_FS_TREE_NODE *)0 )
                        pTemp->pPrev->pNext = (ATTR_FS_TREE_NODE *)0;
                    p->pDesecentTail = pTemp->pPrev;
                }
            }
            free(pTemp->pFName);
            free(pTemp);
        }
    }
}

#ifdef __DEBUG
// 先序遍历文件树
void DisplayTree( ATTR_FS_TREE_NODE *pRoot ) {
    ATTR_FS_TREE_NODE *p;
    ATTR_FS_TREE_NODE *pStack[MAX_STACK_SIZE];
    
    int top = (int)-1;
    pStack[++top] = pRoot;

    while( top >= (int)0 ) {
        p = pStack[top--];
        printf("[%s]\n",p->pFName);

        p = p->pDesecentHead;
        while( p != (ATTR_FS_TREE_NODE *)0 ) {
            if( p->oFSAttr == tpDir )
                //DisplayTree( p );
                pStack[++top] = p;
            else
                printf("%s\n", p->pFName);
            p = p->pNext;
        }
    }
}
#endif

#endif

/* deltree.cpp */
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dos.h>
#include <dir.h>
#include <conio.h>

#include "deltree.h"

int main(int argc, char *argv[]) {
    ATTR_FS_TREE_NODE *pRoot;
    
    int i, j;
    int len, done;
    struct ffblk ffblk;

    char c;

    if( argc != (int)2 ) {
        printf("Deltree simple version\n");
        printf("Usage: %s <directory>\n\n", argv[0]);
        printf("eg. %s d:\\testdir\n", argv[0]);
        printf("[NOTICE] Delete any logical driver root is forbidden!\n");
    }
    else {
        // 判断是否为逻辑盘根
        if( strlen(argv[1]) == (int)2 && argv[1][1] == ':' ) {
            printf("Delete any logical driver root is forbidden!\n");
        }
        else {
            // 收集路径
            len = i = strlen(argv[1]) - 1;
            while( argv[1][i--] != '\\' && i >= 0 );
            // 若路径长度大于8则自动缩进
            if( (j = (len - i - 1)) > 8 ) {
                argv[1][ (j =  (i + 1 + (j - 8) + 6)) ] = '~';
                argv[1][++j] = '1';
                argv[1][++j] = '\0';
            }
            // 确认是否要删除,为了安全考虑
            do {
                printf("Do you really want to REMOVE [%s] and its sub-directories within all files? (Y/N) ", argv[1]);
                c = getchar();
            } while( c != 'Y' && c != 'y' && c != 'N' && c != 'n' );

            if( c == 'N' || c == 'n' )
                return (int)0;

            // 查看指定路径是否存在
            done = findfirst( argv[1], &ffblk, FA_DIREC );
            if(!done) { //指定路径存在
                pRoot = DrawPhy2LogTree( argv[1] );
                DelTree( pRoot );
                pRoot = (ATTR_FS_TREE_NODE *)0;
                printf("\nAll done!\n");
            }
            else
                printf("Path not found!\n");
        }
    }
    return 0;
}

上一页  [1] [2] [3] 下一页

网友评论:(只显示最新10条。评论内容只代表网友观点,与本站立场无关!)
| 设为首页 | 加入收藏 | 联系站长 | 版权申明 | 雁过留声 | 会员中心 |