實驗五 目錄管理
一. 實驗目的:
通過編寫一個簡單的目錄管理程式,實作主要的目錄操作指令,加深作業系統對于檔案目錄管理方式的了解。
二 . 實驗指導:
仿照DOS作業系統的目錄管理,實作簡單的目錄管理指令,要求建立多級目錄結構,可以将原作業系統的指令簡化,各指令說明如下。
(1)DIR指令
格式:DIR
功能:顯示目前目錄下的所有一級目錄和檔案
(2)CD指令
格式:CD 目錄名
功能:進入目前目錄下的某個子目錄,并将其設為目前目錄。
(3)MD指令
格式:MD 目錄名
功能:在目前目錄下建立一個子目錄
(4)RD指令
格式:RD 目錄名
功能:删除目前目錄下的一個空子目錄,對于非空目錄應給出提示不能删除。
三、提示
1、操作界面可以參考windows作業系統的cmd應用程式
2、目錄的存儲結構可以參閱教材203頁圖6-18,也可以考慮更好的結構。
資料結構就是一個二叉樹沒什麼高深的東西
實作不是很完美,沒有異常處理,沒有不合法輸入的提示,而且學到了C++STL中string的小用法:結構體中用string,申請記憶體時,不可以用malloc,因為malloc不會調用string的構造函數,會造成系統不知申請多大記憶體報錯的情況,要使new申請
#include<bits/stdc++.h>
using namespace std;
string curpath="";
string path="";
string parameter1,parameter2;
//目錄結構體
typedef struct ContentNode
{
string contentname;//目錄名
int is_dir;//目錄檔案識别标志
struct ContentNode *parent,*child;//指向父親的指針和指向左孩子的指針
struct ContentNode *prev,*next;//指向前一個兄弟的指針和指向後一個兄弟的指針
} CN;
struct ContentNode *cp, *tp, *root;//根目錄節點
//建立節點
CN* CreateContentNode(string contentname,int is_dir)
{
CN* node = new CN;
node->contentname=contentname;
node->is_dir=is_dir;
node->child=NULL;
node->next=NULL;
node->parent=NULL;
node->prev=NULL;
return node;
}
void init()
{
CN *binNode,*usrNode,*unixNode,*etcNode,*libNode,*userNode,*binNode2,*liuNode,*sunNode,*ftiNode;
path+="/";
//建立檔案樹節點
binNode=CreateContentNode("bin",1);
usrNode=CreateContentNode("usr",1);
unixNode=CreateContentNode("unix",0);
etcNode=CreateContentNode("etc",1);
libNode=CreateContentNode("lib",1);
userNode=CreateContentNode("user",1);
binNode2=CreateContentNode("bin",1);
liuNode=CreateContentNode("liu",1);
sunNode=CreateContentNode("sun",1);
ftiNode=CreateContentNode("fti",1);
cp=tp=root=CreateContentNode("/",1);
// 結點相應内容指派
root->parent=NULL;
root->child=binNode;
root->prev=root->next=NULL;
binNode->parent=root;
binNode->child=NULL;
binNode->prev=NULL;
binNode->next=usrNode;
usrNode->parent=NULL;
usrNode->child=libNode;
usrNode->prev=binNode;
usrNode->next=unixNode;
unixNode->parent=NULL;
unixNode->child=NULL;
unixNode->prev=usrNode;
unixNode->next=etcNode;
etcNode->parent=NULL;
etcNode->child=NULL;
etcNode->prev=unixNode;
etcNode->next=NULL;
libNode->parent=usrNode;
libNode->child=liuNode;
libNode->prev=NULL;
libNode->next=userNode;
userNode->parent=NULL;
userNode->child=NULL;
userNode->prev=libNode;
userNode->next=binNode2;
binNode2->parent=NULL;
binNode2->child=NULL;
binNode2->prev=userNode;
binNode2->next=NULL;
liuNode->parent=libNode;
liuNode->child=NULL;
liuNode->prev=NULL;
liuNode->next=sunNode;
sunNode->parent=NULL;
sunNode->child=NULL;
sunNode->prev=liuNode;
sunNode->next=ftiNode;
ftiNode->parent=NULL;
ftiNode->child=NULL;
ftiNode->prev=sunNode;
ftiNode->next=NULL;
}
int deal()
{
cout<<path<<">";
cin>>parameter1;
if(parameter1.size()==3)
{
transform(parameter1.begin(), parameter1.end(), parameter1.begin(), ::tolower);
return 1;
}
else
{
getchar();//吞空格
cin>>parameter2;
// cout<<parameter1<<" "<<parameter2<<endl;
return 1;
}
}
//查找路徑函數
int FindPath(string ph)
{
curpath="";//目前路徑
CN *temp;
string oldpath;
if(ph=="/") //ph 是根目錄
{
cp=root;
path="/";
return 0;
}
if(ph[0]=='/') // 指針指向根目錄的左孩子
{
cp=root->child;
path="/";
}
else
{
if(cp!=NULL&&cp!=root)
path+="/";
if(cp&&cp->child)
{
if(cp->is_dir)
cp=cp->child;// 指針指向目前目錄的左孩子
}
}
//儲存目前路徑
if(ph[0]=='/')//略過/
{
for(int k=1; k<ph.size(); k++)
{
curpath+=ph[k];
}
}
else
{
curpath=ph;
}
while((cp->contentname!=curpath||(cp->is_dir!=1))&&cp->next!=NULL)
{
cp=cp->next;
}
if(cp->contentname==curpath)
{
path+=cp->contentname;
return 0;
}
}
//改變目錄函數
int cdComd()
{
if(parameter2=="..") //對 cd.. 指令的處理
{
while(cp->prev)
cp=cp->prev;
if(cp->parent)
{
cp=cp->parent; // 找到父親結點
}
//記錄上一級path
int cnt=0;
for(int i=0; i<path.size(); i++)
{
if(path[i]=='/')
cnt++;
}
if(cnt==1)
path="/";
else
{
string l="";
int index=-1;
for(int i=path.size()-1; i>=0; i--)//記錄倒叙第一個/的位置
{
if(path[i]=='/')
{
index=i;
break;
}
}
for(int i=0; i<index; i++)
l+=path[i];
path=l;//更新路徑
}
}
else
{
FindPath(parameter2);// 查找路徑
}
return 1;
}
//顯示目錄子函數
int dirComd()
{
//cp目前目錄
if(cp!=root)
cout<<" <DIR> .."<<endl;
if(cp->child==NULL) // 指定目錄為空
{
return 0;
}
else
{
tp=cp;
tp=tp->child; // 指定目錄不為空,顯示其所有子目錄及檔案名
while(tp)
{
if(tp->is_dir)
cout<<" <DIR> "<<tp->contentname<<endl;
else
cout<<" <FILE> "<<tp->contentname<<endl;
tp=tp->next;
}
return 0;
}
}
//建立目錄函數
int mdComd()
{
CN *temp,*tp;
string content_name;//擷取目錄名
content_name=parameter2;
tp=CreateContentNode(content_name,1); //建立目錄結點
if(cp->child==NULL)
{
tp->parent=cp;
tp->child=NULL;
cp->child=tp;
tp->prev=NULL;
tp->next=NULL;
}
else
{
temp=cp;// 用 temp 找到新結點插入處
temp=temp->child;
while(temp->next)//找到目前目錄子目錄的最後一個兄弟節點
{
temp=temp->next;
}
temp->next=tp;
tp->parent=NULL;
tp->child=NULL;
tp->prev=temp;
tp->next=NULL;
}
return 1;
}
//删除目錄函數
int rdComd()
{
CN *temp;
// char cmd[2];
string content_name;//擷取目錄名
content_name=parameter2;
if(cp->child) //用 temp 指向要删除的結點
{
temp=cp->child;
while(temp->next!=NULL && (temp->contentname!=content_name || temp->is_dir!=1))
temp=temp->next;
}
else
{
printf(" 不存在該目錄 !\n");
return 0;
}
if(temp->child) // 如仍有使用者使用該目錄,則不能删除
{
printf("\n 該目錄不為空,您不能删除\n");
return 0;
}
//删除工作
if(temp->parent==NULL) //不是第一個孩子
{
temp->prev->next=temp->next;
if(temp->next!=NULL)// 如果不是最後一個兄弟
temp->next->prev=temp->prev;
temp->prev=temp->next=NULL;//删除的節點斷開
}
else // 第一個孩子
{
if(temp->next!=NULL)// 如果不是最後一個兄弟
temp->next->parent=temp->parent;//指針指向parent
temp->parent->child=temp->next;//如果是最後一個兄弟則parent=NULL,因為temp->next為空(最後一個兄弟)
}
free(temp);
return 1;
}
void start()
{
int sign;
if(parameter1=="dir")
sign=dirComd();
else if(parameter1=="cd")
{
sign=cdComd();
}
else if(parameter1=="md")
{
sign=mdComd();
}
else if(parameter1=="rd")
{
sign=rdComd();
}
}
int main()
{
init();
while(1)
{
if(deal())
start();
}
return 0;
}