天天看點

作業系統:實驗五 目錄管理(選做)

實驗五 目錄管理

一. 實驗目的:

通過編寫一個簡單的目錄管理程式,實作主要的目錄操作指令,加深作業系統對于檔案目錄管理方式的了解。

二 . 實驗指導:

仿照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;
}      

繼續閱讀