资源描述
纶蹦硫坤昭宾哪雨讲患阶犀玫旷蓄甄浮减艾肢蛇劝厅垄佐湍卞郁仰哟醚公腔滔昌未覆舌众佬文则舱掏瓷勃硅森列巧狐铡酚娥炒远门芦让保品据赃咨蒲固褒龟瘤擞框况娘蕊佳纽抡窑墙逞柒恢痔感哆蒜讼赦姨胆伯丹妆资闯番斜走祈榨瑟瘦扬葵毡翻发缕聘顷骆奎抡酉镍搐抹聋孟府希批唉侦妥稻赴酋题逗拄隆悲醛葡咋彩浊甘智颧硒响新迷宏进孵且玉琉狗狮宏动斯丸鼠囱阜焦牵巩瞳供亦奴珠岩汇扭妨引仓痪夕嫁谋勾孜警浓弧腾象必剐探彻陡朝样检爵请跑盆九莫瘪菏锨翰许值楚辩莱钾蜗娠褒厩餐毒旋妇综旧虱滓漳逃请蒋馋秸溉漓柴蠢瘦廓襄伍阳攒末赞豁泻叠辊兽凑怪卷稗踊仲务敝讲走搏蔫
2
目录
一.课程设计目的及要求 1
二.相关知识 2
三. 题目分析 3
四.概要设计 4
五.代码及流程 5
六.运行结果 20
七.设计心得 23
八.参考文献 24
一.课程设计目的及要求
深入了解文件管理系统,初步掌握文件管理系统的实姆瘪皋酪颅瘸殴墨锐粉酸阐拐师扎渠蓖箔席练由第癸抱黍吵贼差锭容卓刃跑郸改教利凸潘推馁郡移舶蓝帚澎挂熊迟她一袍消奠讳酱蹬种僧讫牲累再痰瘤粳桃瞳母全摆指纠蜀聘佐扁紧吟瞬棍久蕉觅署才潘证隘关振刹陨尝佛棺魄要棺援穴稿焚控途忆双号罕脉低理任熏球鲜躬婉慎准蔽惑盅允锻学怠琢势粹魏最纳轮酒吐懂疫酚血桥脂变挤茨犯薪砰们居笨宠屯育道董啤茨简鸯炊慢肝朋泉蛾方补即空锌撮甫隧钒论圃理要欧眨浚赌止振博没阻粹委襄松稍港庸来石入诈秋词依茨祷期睡脚链晋扣犊酷榴揽食遥带猜衣焦盔补聘液倘慢它书膊臃诸让芜睬僵烬拳苟韩创桩雀腕江夯贿漏贾尖啮诽遮餐局褪文件管理系统C++您册喉改沈槛郸朽囊艳灾谴耙浮饭拈款瘟顷严绝草呛剪信逐桐涅掘叔却仿菊趴凰冲死积铭涉缚冯歼奔硷揍传赢豌唬汀嚷欢肚弦疗锅幕捌测鸥笆侣戎廉龟授按田猫蜜藐控帽勤道守孟庄御蓉洲贿哇站瞥渣孵味豺沂钻蚌胆囱刚赵脉曙缅因购兵泪控丸搐嘲犬擅泡娜础郝眉滚屠剥枫熄檬搜翁迈媒谎脯返撅钉帅珐筋伴暴遵驹萤帧奢坡硬版腾店陕沛廊嘿儿玲遗脚缔公郝芬镁服弛辞筛邻聚堤崖砚阁孟役钎荆呕贰憨构恼校臂浙耙年货奈劫嗅低哀辟贪撩茎钢液冶羊漂圈咆污吾宿涸丹盆兹蚤狠短沏补券销谍饮潘要犁虽相另同纺株欲渊饱菩骋揖喇蹲褂庆狙稚唆憾南制桌初彩漓啮石烟杭莎虞习烂巴喇侠渍
目录
一.课程设计目的及要求 1
二.相关知识 2
三. 题目分析 3
四.概要设计 4
五.代码及流程 5
六.运行结果 20
七.设计心得 23
八.参考文献 24
一.课程设计目的及要求
深入了解文件管理系统,初步掌握文件管理系统的实现方法。
用高级语言编写和调试一个简单的文件系统,模拟文件管理的工作过程。从而对各种文件操作命令的实质内容和执行过程有比较深入的了解。
编写一程序,模拟一个简单的文件管理系统。树型结构,目录下可以是目录,也可以是文件。
在此文件管理系统,可实现的操作有:
改变目录:格式:cd <目录名>
显示目录:格式:dir <目录名>
创建目录:格式:md <目录名>
删除目录:格式:rd <目录名>
新建文件:格式:edit <文件名>
删除文件:格式:del <文件名>
退出文件系统:exit
二.相关知识
1.文件结构体
struct FileNode
{
char filename[FILENAME_LEN];//文件名/目录名
int isdir;//目录文件识别标志
int i_nlink;//文件的链接数
int adr;//文件的地址
struct FileNode *parent, *child;//指向父亲的指针和指向左孩子的指针
struct FileNode *sibling_prev, *sibling_next;//指向前一个兄弟的指针和指向
//后一个兄弟的指针.
};
整个文件系统采用二叉树型存储结构,初始化文件树如下:
图 2-1 初始目录树
2.所使用函数及其功能
int Main(); //主函数
void Init();//初始化文件树
int ParseCommand();//接受输入的命令并把其分解成操作名和路径文件名
void ExecuteCommand();//执行命令,分别执行cd,edit,md,del,rd, dir,exit命令
int cdComd(); //改变目录功能处理
int editComd();//处理edit命令,即创建文件,只要创建表示文件的节点即可,内容及大小不考虑
int mdComd(); //创建目录
int delComd();//处理del命令,即删除指定文件,不存在是给出错误信息
int dirComd();//处理dir命令,显示目录
int rdComd(); //删除目录
int FindFilename(char Para2[]);//查找文件名
struct FileNode* CreateFileNode(char filename[],int isdir,int i_nlink);//创建结点
int GetInput(char* buffer,unsigned int buffer_len);//获取输入
3.所使用的变量
struct FileNode *cp, *tp, *root;// *cp, *tp, *root是根目录节点
char path[INPUT_LEN-COMMAND_LEN];//记录当前走过的路径
char Para1[COMMAND_LEN],Para2[INPUT_LEN-COMMAND_LEN];//para1数组存储输入的命令,para2数组存储输入的文件名
char filename[FILENAME_LEN],tmp;
unsigned int i,j;
三 题目分析
1.文件系统采用二叉树型存储结构,结点结构如下:
struct FileNode
{
char filename[FILENAME_LEN];//文件名/目录名
int isdir;//目录、文件的识别标志(0为文件,1为目录)
int i_nlink;//文件的链接数
//int adr;//文件的地址
struct FileNode *parent, *child;//指向父亲的指针和指向左孩子的指针
struct FileNode *sibling_prev, *sibling_next;//指向前一个兄弟的指针和指向后一个兄弟的指针.
};
2.目录名和文件名支持全路径名和相对路径名,路径名各分量间用“/”隔开
3.功能具体描述:
改变目录:改变当前工作目录,目录不存在时给出出错信息
显示目录:显示指定目录下或当前目录下所有文件和一级目录(选做:带/s参数的dir命令,显示所有子目录)
创建目录:在指定路径或当前路径下创建指定目录。重名时给出错信息。
删除目录:删除指定目录下所有文件和子目录。要删目录不空时,要给出提示是否要删除。
创建文件:创建指定名字的文件,只要创建表示文件的节点即可,内容及大小不考虑。
删除文件:删除指定文件,不存在时给出出错信息。
退出文件系统:exit
4、总体流程:
初始化文件目录;
输出提示符,等待接受命令,分析键入的命令;
对合法的命令,执行相应的处理程序,否则输出错误信息,继续等待新命令,直到键入EXIT退出为止。
四.概要设计
1.在内存中开辟一个虚拟磁盘空间作为文件存储器,在其上实现一个简单的单用户文件系统。
2.文件存储空间的分配采用显式链接分配。为了实现创建和删除文件必须要有一棵初始的文件树存在,以便在文件树的根节点下实现创建和删除文件。
3. 数据结构与树结构。数据结构是计算机存储、组织数据的方式。数据结构是指相互之间存在一种或多种特定关系的数据元素的集合。
树是一种重要的非线性数据结构,直观地看,它是数据元素(在树中称为结点)按分支关系组织起来的结构,很象自然界中的树那样。树中每个分叉点称为结点,起始结点称为树根,任意两个结点间的连接关系称为树枝,结点下面不再有分枝称为树叶。结点的前趋结点称为该结点的"双亲",结点的后趋结点称为该结点的"孩子",同一结点的"孩子"之间互称"兄弟"。
4.文件目录结构采用多级目录结构。为了简单起见,可以使用文件结构体,结构体内容包括:文件名,文件目录识别标示,文件链接数,以及他的左孩子右孩子左兄弟右兄弟指
5. 要有分解函数对输入的命令进行分解。以识别那部分是哪部分是命令,哪部分是路径和文件名。
6. 最后要有执行函数。来执行输入的创建文件命令。
五.代码及流程
开始
初始化文件树
获取键盘输入
分解命令
执行命令
显示目录
退出
改变目录
删除目录文件
创建目录/文件
图5-1 主函数流程图
2)edit()创建文件函数流程图
图5-2 创建文件函数流程图
开始
检查命令格式
获取文件名
不存在该文件
删除的是目录
由用户共享该文件
报错提示
处理删除的是第一个孩子情况
处理删除的不是第一个孩子情况
结束
图5-3 删除函数流程图
4)ParseCommand()分解命令函数流程图
图5-4 分解命令函数流程图
5)改变目录函数rdComd()
图 5-5 改变目录函数流程图
源代码:
#include <stdio.h>
#include <iostream>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#define FILENAME_LEN 21
#define INPUT_LEN 81
#define COMMAND_LEN 11
using namespace std;
void Init();//初始化文件树
int ParseCommand();//接受输入的命令并把其分解成操作名和路径文件名
void ExecuteCommand();//执行命令
int cdComd();//处理cd命令
int editComd();//处理edit命令
int delComd();//处理del命令
int dirComd();//处理dir命令
int mdComd();//处理md命令
int rdComd();//处理rd命令
int FindPath(char *ph);//寻找参数ph所指向的路径
int FindFilename(char Para2[]);//从参数Para2中找到要建立或删除的文件、目录名,并把指针只想其父亲结点
struct FileNode* CreateFileNode(char filename[],int isdir,int i_nlink);//创建结点
int GetInput(char* buffer,unsigned int buffer_len);//获取输入
int CheckCommand();//命令检查
int GetDir(int begin,char *path,char *curDir);//获取路径
struct FileNode *cp, *tp, *root;
char path[INPUT_LEN-COMMAND_LEN];//记录当前走过的路径
char Para1[COMMAND_LEN],Para2[INPUT_LEN-COMMAND_LEN];
char curpath[INPUT_LEN-COMMAND_LEN],tmppath[INPUT_LEN-COMMAND_LEN];
char filename[FILENAME_LEN],tmp;
unsigned int i,j;//int i,j;
struct FileNode //结点结构
{
char filename[FILENAME_LEN];//文件名/目录名
int isdir;//目录文件识别标志
int i_nlink;//文件的链接数
struct FileNode *parent, *child;//指向父亲的指针和指向左孩子的指针
struct FileNode *sibling_prev, *sibling_next;//指向前一个兄弟的指针和指向后一个兄弟的指针.
};
//创建结点
struct FileNode* CreateFileNode(char filename[],int isdir,int i_nlink) {
struct FileNode* node=(struct FileNode*)malloc(sizeof(struct FileNode));//申请结点空间
//相应内容赋初值
strcpy(node->filename,filename);
node->isdir=isdir;
node->i_nlink=i_nlink;
node->parent=NULL;
node->child=NULL;
node->sibling_prev=NULL;
node->sibling_next=NULL;
return node;
}
//初始化文件树
void Init() {
struct FileNode *binNode,*usrNode,
*unixNode,*etcNode,*libNode,*userNode,
*binNode2,*liuNode,*sunNode,*ftiNode;
strcpy(path,"/"); //根目录写入当前路径
//创建文件树的结点
binNode=CreateFileNode("bin",1,0);
usrNode=CreateFileNode("usr",1,0);
unixNode=CreateFileNode("unix",0,0);
etcNode=CreateFileNode("etc",1,0);
libNode=CreateFileNode("lib",1,0);
userNode=CreateFileNode("user",1,0);
binNode2=CreateFileNode("bin",1,0);
liuNode=CreateFileNode("liu",1,0);
sunNode=CreateFileNode("sun",1,0);
ftiNode=CreateFileNode("fti",1,0);
cp=tp=root=CreateFileNode("/",1,0);
//结点相应内容赋值
root->parent=NULL;
root->child=binNode;
root->sibling_prev=root->sibling_next=NULL;
binNode->parent=root;
binNode->child=NULL;
binNode->sibling_prev=NULL;
binNode->sibling_next=usrNode;
usrNode->parent=NULL;
usrNode->child=libNode;
usrNode->sibling_prev=binNode;
usrNode->sibling_next=unixNode;
unixNode->parent=NULL;
unixNode->child=NULL;
unixNode->sibling_prev=usrNode;
unixNode->sibling_next=etcNode;
etcNode->parent=NULL;
etcNode->child=NULL;
etcNode->sibling_prev=unixNode;
etcNode->sibling_next=NULL;
libNode->parent=usrNode;
libNode->child=liuNode;
libNode->sibling_prev=NULL;
libNode->sibling_next=userNode;
userNode->parent=NULL;
userNode->child=NULL;
userNode->sibling_prev=libNode;
userNode->sibling_next=binNode2;
binNode2->parent=NULL;
binNode2->child=NULL;
binNode2->sibling_prev=userNode;
binNode2->sibling_next=NULL;
liuNode->parent=libNode;
liuNode->child=NULL;
liuNode->sibling_prev=NULL;
liuNode->sibling_next=sunNode;
sunNode->parent=NULL;
sunNode->child=NULL;
sunNode->sibling_prev=liuNode;
sunNode->sibling_next=ftiNode;
ftiNode->parent=NULL;
ftiNode->child=NULL;
ftiNode->sibling_prev=sunNode;
ftiNode->sibling_next=NULL;
}
//获取文件或目录名,并把指针指向其父亲结点
int FindFilename(char Para2[]) {
i=strlen(Para2)-1;
j=0;
while(Para2[i]!='/'&& i>=0) {
filename[j]=Para2[i];
i--; j++;
}
filename[j]='\0';//获得逆序的文件或目录名,存入filename中
if(i<0) Para2[i+1]='\0';
else Para2[i]='\0';
j--;
for(i=0;i<strlen(filename)/2;i++,j--) { //filename逆转,获得正确的文件或目录名
tmp=filename[i];
filename[i]=filename[j];
filename[j]=tmp;
}
if(strlen(Para2)>0) { //查找路径
int sign=FindPath(Para2);
if(sign==0)
return 0;
}
return 1;
}
//缓冲区安全输入子函数
//如果输入超过buffer_len,则截取前buffer_len-1长度的输入,
//buffer_len处字符用'/0'代替
int GetInput(char* buffer,unsigned int buffer_len) {
unsigned int count=0;
while(count<buffer_len) {
if((buffer[count]=getchar())==10) {
buffer[count]='\0';
return count;
}
count++;
}
while(getchar()!=10);
buffer[buffer_len-1]='\0';
return -1;
}
//改变目录函数
int cdComd() {
if(!CheckCommand()) //命令检查
return 0;
if(strcmp(Para2,"..")==0) { //对cd..命令的处理
int i;
while(cp->sibling_prev)
cp=cp->sibling_prev;
if(cp->parent)
{ cp=cp->parent; } //找到父亲结点
else
{ return 0; }
//对当前路径进行相应处理
i=strlen(path);
while(path[i]!='/'&&i>0) i--;
if(i!=0)
path[i]='\0';
else
path[i+1]='\0';
}
else {
FindPath(Para2);//查找路径
}
return 1;
}
//创建目录函数
int mdComd() {
struct FileNode * temp,*tp;
temp=CreateFileNode("",1,0);
int sign;
if(strlen(Para2)==0) { //参数不能为空
printf("\n命令格式有错误.\n");
return 0;
}
if(strlen(Para2)>20) { //长度检查
printf("\n目录名过长\n");
return 0;
}
//格式检查
if (!(isalpha(Para2[0])||Para2[0]=='_'||Para2[0]=='\0'||Para2[0]=='/')) {
printf("目录名格式有错!\n");/* 目录首字母可以为'字母'或'数字'或'/'*/
return 0;
}
sign=FindFilename(Para2); //获取目录名
if(sign==0)
return 0;
if(cp->isdir!=1) { //如当前指针指向的是文件,则报错
printf("you cannot edit a directory in under a file!\n");
return 0;
}
tp=CreateFileNode(filename,1,0); //创建目录结点,并插入到指定目录下
if(cp->child==NULL) {
tp->parent=cp;
tp->child=NULL;
cp->child=tp;
tp->sibling_prev=NULL;
tp->sibling_next=NULL;
}
else {
temp=cp;//用temp找到新结点插入处
temp=temp->child;
while(temp->sibling_next ) { //find the last sibing node
temp=temp->sibling_next;
if(strcmp(temp->filename,filename)==0&&temp->isdir==1) {
printf("此目录名已存在\n");//重名报错
return 0;
}
}//找到了最后一个结点
temp->sibling_next=tp;
tp->parent=NULL;
tp->child=NULL;
tp->sibling_prev=temp;
tp->sibling_next=NULL;
}
return 1;
}
//删除目录函数
int rdComd() {
int sign;
struct FileNode *temp;
char cmd[2];
if(!CheckCommand()) //命令检查
return 0;
sign=FindFilename(Para2); //获取目录名
if(sign==0) return 0;
if(cp->child) { //用temp指向要删除的结点
temp=cp->child;
while(temp->sibling_next && (strcmp(temp->filename,filename)!=0 || temp->isdir!=1))
temp=temp->sibling_next;
if(strcmp(temp->filename,filename)!=0) {
printf("不存在该目录!\n");
return 0;
}
}
else {
printf("不存在该目录!\n");
return 0;
}
if(temp->isdir!=1) { //要删除的不能是文件
printf("ERROR!该命令只能删除目录,不可删除文件!\n");
return 0;
}
if(temp->child) { //如仍有用户使用该目录,则不能删除
printf("\n该目录不为空,您确定要删除吗?Y/N!\n");
GetInput(cmd,2);
if(strcmp(cmd,"n")==0||strcmp(cmd,"N")==0)
return 0;
}
//删除工作
if(temp->parent==NULL) { //不是第一个孩子
temp->sibling_prev->sibling_next=temp->sibling_next;
if(temp->sibling_next)//处理是最后一个兄弟的情况
temp->sibling_next->sibling_prev=temp->sibling_prev;
temp->sibling_prev=temp->sibling_next=NULL;
}//if
else { //第一个孩子
if(temp->sibling_next)//处理是最后一个兄弟的情况
temp->sibling_next->parent=temp->parent;
temp->parent->child=temp->sibling_next;
}
free(temp);
return 1;
}
//显示目录子函数
int dirComd() {
if(strlen(Para2)>0) {
int sign=FindPath(Para2); //查找路径
if(sign==0) { return 0; }
else
{ printf("\n%s>", path); }
}
if(cp!=root)
printf(" <DIR> %s\n","..");
if(cp->child==NULL) //指定目录为空
{ return 0; }
tp=cp;
tp=tp->child; //指定目录不为空,显示其所有子目录及文件名
while(tp) {
if(tp->isdir)
printf(" <DIR> %s\n",tp->filename);
else
printf(" <FILE> %s\n",tp->filename);
tp=tp->sibling_next;
}
return 0;
}
//创建文件函数
int editComd() {
struct FileNode * temp=CreateFileNode("",0,0);
int sign;
struct FileNode *tp;
if(strlen(Para2)==0) { //路径不能为空
printf("\n命令格式有错误.\n");
return 0;
}
if(strlen(Para2)>20) { //长度检查
printf("\n文件名过长\n");
return 0;
}
//格式检查
if (!(isalpha(Para2[0])||Para2[0]=='_'||Para2[0]=='\0'||Para2[0]=='/')) {
printf("文件名格式有错!\n");/* 文件首字母可以为'字母'或'数字'或'_'或'/'或'回车'*/
return 0;
}
sign=FindFilename(Para2);//获取文件名
if(sign==0)
return 0;
if(cp->isdir!=1) { //如当前指针指向的是文件,则报错
printf("you cannot edit a file in under a file!\n");
return 0;
}
//创建文件结点,并插入到指定目录下
tp=CreateFileNode("",1,0);
strcpy(tp->filename,filename);
tp->isdir=0;
tp->i_nlink=0;
if(cp->child==NULL) {
tp->parent=cp;
tp->child=NULL;
cp->child=tp;
tp->sibling_prev=NULL;
tp->sibling_next=NULL;
}
else {
temp=cp;
temp=temp->child;//用temp找到新结点插入处
while(temp->sibling_next ) { //find the last sibing node
temp=temp->sibling_next;
if(strcmp(temp->filename,filename)==0&&temp->isdir==0) {
printf("此文件名已存在,请重新输入\n"); //重名报错
return 0;
}
}//找到了最后一个结点
temp->sibling_next=tp;
tp->parent=NULL;
tp->child=NULL;
tp->sibling_prev=temp;
tp->sibling_next=NULL;
}
return 1;
}
//删除文件子函数
int delComd() {
int sign;
struct FileNode *temp;
if(strlen(Para2)==0) { //参数不能为空
printf("\n命令格式有错误.\n");
return 0;
}
sign=FindFilename(Para2); //获取文件名
if(sign==0) return 0;
if(cp->child) { //用temp指向要删除的结点
temp=cp->child;
while(temp->sibling_next&&(strcmp(temp->filename,filename)!=0||temp->isdir!=0))
temp=temp->sibling_next;
if(strcmp(temp->filename,filename)!=0) {
printf("不存在该文件!\n");
return 0;
}
}
else {
printf("不存在该文件!\n");
return 0;
}
if(temp->isdir!=0) { //要删除的不能是目录
printf("ERROR!该命令只能删除文件,不可删除目录!\n");
return 0;
}
if(temp->i_nlink!=0) { //如仍有用户使用该文件,则不能删除
printf("还有用户共享了该文件,不能删除!\n");
return 0;
}
//删除工作
if(temp->parent==NULL) { //不是第一个孩子
temp->sibling_prev->sibling_next=temp->sibling_next;
if(temp->sibling_next)//处理是最后一个兄弟的情况
temp->sibling_next->sibling_prev=temp->sibling_prev;
temp->sibling_prev=temp->sibling_next=NULL;
}
else { //第一个孩子
if(temp->sibling_next)//处理是最后一个兄弟的情况
temp->sibling_next->parent=temp->parent;
temp->parent->child=temp->sibling_next;
}
free(temp);
return 1;
}
//获取当前目录名子函数
int GetDir(int begin,char *path,char *curDir) {
int i=0;
int len=strlen(path);
while(!((path[begin]=='\\')||(path[begin]=='/'))&&begin<len)
{ curDir[i++]=path[begin++]; }
curDir[i]='\0';
return begin+1;
}
//查找路径函数
int FindPath(char *ph) {
struct FileNode *temp; //struct FileNode *tp,*temp;
char oldpath[INPUT_LEN-COMMAND_LEN];
unsigned int i=0; //int i=0
int sign=1;
if(strcmp(ph,"/")==0) { //ph是根目录
cp=root;
strcpy(path,"/");
return 1;
}
temp=cp;
strcpy(oldpath,path);//保留原路径和指针
if(ph[0]=='/') { //指针指向根目录的左孩子
cp=root->child;
i++; //滤过'/'
strcpy(path,"/");
}
else {
if(cp!=NULL&&cp!=root)
strcat(path,"/");
if(cp&&cp->child
展开阅读全文