ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

基于C语言的文件管理模拟系统

2021-02-02 22:33:03  阅读:271  来源: 互联网

标签:基于 C语言 pNode 文件夹 dir 模拟系统 printf cd FileNode


基于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
**/

结语

这个文件模拟系统基本实现了多叉树的初始化以及节点的新建,删除等常见操作,对于删除操作我实现的不是很好,没有实现递归删除,这会导致很大的内存泄露。大家可以根据此代码进行相应的修改。

希望此代码能给大家带来收获,谢谢大家!

坚持不懈地努力才能成为大神!

标签:基于,C语言,pNode,文件夹,dir,模拟系统,printf,cd,FileNode
来源: https://www.cnblogs.com/yimeixiaobai1314/p/14364546.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有