基於C語言的文件管理模擬系統


基於C語言的文件管理模擬系統

前言

這是某大學的一個C語言課程設計題目,之前幫別人寫過。程序寫的並不是很完善,當時忙於交差,實際上存在很多漏洞,比如開辟的空間沒有完全釋放等等。其余的一些遺留的bug以及漏洞等等請大家多多指正,謝謝!

題目要求

編寫程序,模擬命令行的常用文件系統管理命令,具體要求如下:
① 根路徑為ROOT。首次進入模擬器時,提示符為“ROOT>",“>”左側為當前路徑,可在“>”后輸入下述各命令。

② 切換到當前路徑下的某文件夾: cd文件夾。 如“cd music", 若當前路徑下存在music文件夾,則提示符變為“當前路徑\music>”,若不存在,則提示。

③ 切換到當前路徑的上級文件夾: cd ...

④ 在任意路徑下切換回根路徑ROOT: cd \。

⑤ 列出當前路徑下的全部文件夾和文件: dir。

⑥ 在當前路徑下新建文件夾: md文件夾 名稱。

⑦ 在當前路徑下新建文件: mf文件名稱。

⑧ 刪除當前路徑下的某文件或文件夾(及其下所有文件夾及文件): del文件或文件夾名稱。

注意:

① 以上各命令涉及到的文件夾和文件,僅在內存中用樹結構模擬,而非真正的文件系統。

② 樹中結點要包含必要的信息,如:文件或文件夾名稱、區分文件或文件夾的標識、文件創建日期等。

設計思路

要實現此系統,涉及到的算法及知識包括:樹的創建、遍歷、查找、插入、刪除。

以ROOT作為根節點,自上到下用多叉樹結構實現一個文件系統,每個節點代表一個文件或者文件夾(以標志位區分)。通過cd命令進入當前樹節點的子節點,cd ..返回上層目錄(文件節點中包含一個pNode指針位,表示當前節點的父節點,用以實現返回功能,這有點類似於樹的雙親表示法)。

具體的實現思路和方法我已經詳細注釋到代碼中。

具體實現

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

#define FILEMAXN 100
#define OPMAXN 100
#define NAMEMAXN 100
#define PATHMAXN 1000
typedef struct FileNode{
    char name[NAMEMAXN]; //文件名或者文件夾名
    char path[PATHMAXN]; //文件(夾)路徑
    int flag; //區分文件或者文件夾的標識->0: 文件夾,1: 文件
    char datetime[20]; //文件創建日期
    int filenumber; //文件夾包含的文件(夾)數量
    struct FileNode** files; //文件夾包含的文件(夾)列表
    struct FileNode* pNode; //上級目錄
}FileNode, *FileTree;

//日期函數,用於記錄文件創建日期
//本函數可以不用看,下面的一些函數比較重要
char* getDateTime(){
    char cur_time[20];
    time_t t;
    struct tm * lt;
    time(&t);
    lt = localtime(&t); //轉為時間結構
    sprintf(cur_time, "%04d/%02d/%02d %02d:%02d:%02d",lt->tm_year+1900, lt->tm_mon, lt->tm_mday, lt->tm_hour, lt->tm_min, lt->tm_sec);
    return cur_time;
}
//初始化文件系統,即建立一個根目錄ROOT節點
FileTree init(){
    FileTree root;
    root = (FileNode *)malloc(sizeof(FileNode)); //分配空間
    strcpy(root->name, "ROOT"); //字符串拷貝函數
    strcpy(root->path, "ROOT");
    root->flag = 0; //ROOT為目錄節點,標識為0
    root->filenumber = 0; //初始時所含子文件(夾)數量為0
    root->files = NULL;
    root->pNode = NULL;
    return root;
}
//md:新建文件夾
void makeDirectory(FileNode *pNode, char dirname[]){
    if(pNode->files == NULL){ //首次使用要分配空間
        pNode->files = (FileNode**)malloc(FILEMAXN * sizeof(FileNode*));
    }
    pNode->files[pNode->filenumber] = (FileNode *)malloc(sizeof(FileNode));
    FileNode *dir = pNode->files[pNode->filenumber++];
    dir->flag = 0; //目錄節點,標識為0
    strcpy(dir->name, dirname);
    dir->filenumber = 0;
    dir->files = NULL;
    dir->pNode = pNode;
    //以下代碼生成當前路徑
    char tmp[PATHMAXN];
    strcpy(tmp, pNode->path);
    strcat(tmp, "\\");
    strcat(tmp, dirname);
    strcpy(dir->path, tmp);

}
//mf:新建文件
void makeFile(FileNode *pNode, char filename[]){
    if(pNode->files == NULL){
        pNode->files = (FileNode**)malloc(FILEMAXN * sizeof(FileNode*));
    }
    pNode->files[pNode->filenumber] = (FileNode *)malloc(sizeof(FileNode));
    FileNode *dir = pNode->files[pNode->filenumber++];
    dir->flag = 1; //文件節點,標識為1
    strcpy(dir->name, filename);
    dir->filenumber = 0;
    dir->files = NULL;
    dir->pNode = pNode;
}
//dir:列出當前目錄下全部文件(夾)
void showDir(FileNode *pNode){
    int i;
    //遍歷打印文件名
    for(i = 0; i < pNode->filenumber; i++){
        printf("%s ", pNode->files[i]->name);
    }
    printf("\n");
}
//cd:切換到當前路徑下的某個文件夾
FileNode* enterSubDir(FileNode *pNode, char dirname[]){
    FileNode* curNode = NULL;
    int i;
    for(i = 0; i < pNode->filenumber; i++){
        if(strcmp(pNode->files[i]->name, dirname) == 0
           && pNode->files[i]->flag == 0){
            //若有此文件夾,則將當前節點切換為此文件夾
            curNode = pNode->files[i];
        }
    }
    return curNode;
}
//del:刪除文件(夾)
int delFile(FileNode *pNode, char dirname[]){
   int i;
   for(i = 0; i < pNode->filenumber; i++){
        if(strcmp(pNode->files[i]->name, dirname) == 0){
            free(pNode->files[i]); //釋放空間
            int j = i;
            for(; j < pNode->filenumber - 1; j++){
                pNode->files[j] = pNode->files[j + 1]; //后面節點前移
            }
            pNode->filenumber --; //子文件(夾)數量減一
        }
    }
}
void showInfo()
{
	printf("  ******************************************************\n\n");
	printf("  *                歡迎使用文件模擬系統                 *\n \n");
	printf("  ******************************************************\n\n");
	printf("  該系統目前支持如下功能:\n");
	printf("  1.切換到當前路徑下的某文件夾: cd + 文件夾\n");
	printf("  2.切換到當前路徑的上級文件夾: cd ..\n");
	printf("  3.在任意路徑下切換回根路徑ROOT: cd \\ \n");
	printf("  4.列出當前路徑下的全部文件夾和文件: dir\n");
	printf("  5.在當前路徑下新建文件夾: md + 文件夾名\n");
	printf("  6.在當前路徑下新建文件: mf + 文件名\n");
	printf("  7.刪除當前路徑下的某文件(夾)名: del文件(夾)名\n");
	printf("  ******************************************************\n");
}
//主函數
int main()
{
    showInfo();
    FileTree rootDir = init(); //初始化文件系統,
    FileNode *curDir = rootDir; //切換當前節點為根節點
    char curPath[PATHMAXN] = "ROOT"; //切換當前路徑為根路徑
    printf("%s> ", curPath); //輸出 ROOT>
    char operation[OPMAXN];
    while(gets(operation)!= EOF){ //獲取輸入
        char *op = strtok(operation, " ");
        char *arg = strtok(NULL, " "); //以上分割出操作命令和參數,比如cd music,則命令為cd,參數為music
        if(strcmp(op, "md") == 0){ //md
            makeDirectory(curDir, arg);
        }else if(strcmp(op, "mf") == 0){ //mf
            makeFile(curDir, arg);
        }else if(strcmp(op, "del") == 0){ //del
            delFile(curDir, arg);
        }else if(strcmp(op, "dir") == 0){ //dir
            showDir(curDir);
        }else if(strcmp(op, "cd") == 0){ //cd
            if(strcmp(arg, "..") == 0){ //cd ..
                curDir = curDir->pNode;
            }else if(strcmp(arg, "\\") == 0){ //cd \ ---切換為根目錄
                curDir = rootDir;
            }else{ //cd music --進入子目錄
                FileNode *pNode = curDir;
                curDir = enterSubDir(curDir, arg);
                if(!curDir){ //出現未知目錄名,報錯
                    printf("ERROR:\"%s\"目錄下沒有\"%s\", 請重新輸入!\n",pNode->name, arg);
                    curDir = pNode;
                    printf("%s> ", curPath);
                    continue;
                }
            }
            strcpy(curPath, curDir->path);
        }else if(strcmp(op, "exit") == 0){ //exit 退出
            printf("已退出系統, 謝謝使用!\n", op);
            break;
        }else{ // 出現未知命令,報錯
            printf("ERROR:不支持\"%s\"命令, 請重新輸入!\n", op);
        }
        printf("%s> ", curPath);
    }
    return 0;
}
//測試用例如下,可直接復制執行
//當然自己構造也可以
/*
md music
md video
mf file1.txt
mf file1.txt
dir
del file1.txt
dir
cd music
mf a.mp3
mf b.mp3
dir
cd ..
cd video
mf c.mp4
mf d.mp4
dir
cd \
cd music
dir
del a.mp3
dir
exit
**/

結語

這個文件模擬系統基本實現了多叉樹的初始化以及節點的新建,刪除等常見操作,對於刪除操作我實現的不是很好,沒有實現遞歸刪除,這會導致很大的內存泄露。大家可以根據此代碼進行相應的修改。

希望此代碼能給大家帶來收獲,謝謝大家!

堅持不懈地努力才能成為大神!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM