OS課設:實現二級文件目錄系統

先從頭纔是撤,寫到現在真的感覺是令人肝疼的一份課設。2019年6月27日19:16:09

老師就不說了,在站內可以直接搜到,所以還是悄悄地抱怨,WOC XiaoZhao


廢話不多講了,開始這份分析報告把,希望能幫上我的讀者。

本人的底層實現來自於這位大哥的好心鏈接,給我了很多指導性的啓發,不過他也有致命的錯誤,也是我爲什麼這麼肝疼的原因了(設計實現一個文件系統,既然要以鏈表的形式實現連續式存儲文件系統,爲什麼不做存儲空間的回收)

附帶大哥鏈接:https://blog.csdn.net/huangqiang1363/article/details/50592633

本人在實現:1空間分配,2空間合併,3優先排序方面真的下了很大的功夫,畢竟單鏈表實現連續性,實現起來確實可能不如同學使用的索引節點好用。本人的拙見……


課設題目:操作系統之實現二級文件目錄系統

時間,,,烏拉烏拉

其實,剛拿到這個題目時,我真的沒有思路,隨後我就對着老師的課設指導書進行研究,對二級文件系統的演示這個課題的每個要求進行分析,總算是有了思路。下面給出我的分析。
文件系統演示
一、課程設計目的
使學生熟悉文件管理系統的設計方法;加深對所學各種文件操作的瞭解及其操作方法的特點。
//既然是基於控制檯的,我們可以更改顏色玩玩
二、課程設計內容
設計一個簡單的多用戶文件系統。即 //和後面一樣,用結構體數組實現
①在系統中用一個文件來模擬一個磁盤; //switch語句或者if-else語句實現,既然這裏說到了 用一個文件去模擬一個磁盤,換句話說,在你的課設裏,必須要有磁盤空間分配的思路在裏面,不然就不是模擬磁盤了。
②此係統至少有:Create、delete、open、close、read、write等和部分文件屬性的功能。
③實現這個文件系統。 //文件系統要實現
④能實際演示這個文件系統。//cmd演示即可
基本上是進入一個界面(此界面就是該文件系統的界面)後,可以實現設計的操作要求。

三、課程設計指導
1)設計一個10個用戶的文件系統,每次用戶可保存10個文件,一次運行用戶可以打開5個文件。 //三個數組的大小分別爲 10、10、5
//一次運行用戶最多可以打開5個文件如何實現? 在用戶文件裏面加變量判斷,用戶每打開一個就+1,
//每次用戶最多可保存10個文件如何實現? 很明顯,同時保存我們是無法做到的,無論是誰,都無法做到,也就是說還是一個個保存的,那麼同樣可以設置變量判斷。如果保存的較多,那麼只好請用戶單獨關閉某些指定的文件。

2)程序採用二級文件目錄(即設置主目錄MFD)和用戶文件目錄(UFD)。另外,爲打開文件設置了運行文件目錄(AFD)。 //存放各個用戶目錄的文件夾、用戶目錄
//是說運行的所有文件用一個目錄層次表示嗎
3)爲了便於實現,對文件的讀寫作了簡化,在執行讀寫命令時,只需改讀寫指針,並不進行實際的讀寫操作。 //整型的變量判斷是否讀寫完成了 下面的pointer
4)因系統小,文件目錄的檢索使用了簡單的線性搜索。 //鏈表的順序查找
5)文件保護簡單使用了三位保護碼:允許讀寫執行、對應位爲 1,對應位爲0,則表示不允許讀寫、執行。 //標記變量即可實現
6)程序中使用的主要設計結構如下:主文件目錄和用戶文件目錄(MFD、UFD),打開文件目錄(AFD)即運行文件目錄,如圖5.1所示。//主要的結構體設計

還有MFD、UFD、AFD最好全部存到文件裏面去,不然每次都要輸入,十分麻煩,而且不能通過看文件 查看到自己的實驗現象,着實不便。
參考的數據結構設計如下
struct TYPE_UFD //用戶文件目錄
{
string File_Name; //文件名
bool Read; //讀保護碼,true爲可讀
bool Write; //寫保護碼,true爲可寫
bool Execute; //執行保護碼,true爲可執行
int Length_File; //文件長度
}; //用戶文件目錄和用戶打開的文件目錄是不是都各有自己的屬性
struct TYPE_MFD //主文件目錄
{
string User_Name; //用戶名
TYPE_UFD *Pointer; //用戶文件目錄指針
};
//很明顯,第三個結構體沒有指針域,但我們是需要指針域的,還有下面紅色部分可以合在一個整型變量裏面的
struct TYPE_AFD //打開文件目錄
{
int File_ID; //打開的文件號
boolRead;//讀保護碼,true爲可讀
boolWrite;//寫保護碼,true爲可寫
boolExecute;//執行保護碼,true爲可執行
int Pointer; //讀寫指針
};
7)文件系統結構如圖5.2所示
//很明顯,這裏要用到的數據結構是 鏈表
    
8)文件系統算法的流程圖如圖5.3所示。
                             
圖5.3文件系統算法的流程圖
//這裏告訴了你 main函數的主要調用的函數順序 
9)注意對於物理塊的訪問(包括訪問指針,空閒位)需要經過輸入輸出,相當於通過定位對文件進行讀寫。打開文件目錄(AFD)是在內存中,由打開文件時創建。
好了,分析完了,就要開始編寫代碼了,下面附上我小小的代碼,還有很多需要修改的地方,做的不好的地方,大神就請原諒,也希望多多指點我。
--------------------- 
作者:o0非誠勿擾0o 
來源:CSDN 
原文:https://blog.csdn.net/huangqiang1363/article/details/50592633 


代碼實現Code

下面是我實現整體結構的文件·

1 OSHead.h頭文件

#ifndef OSHEAD_H_INCLUDED
#define OSHEAD_H_INCLUDED

#include<cmath>
#include<ctime>
#include<string>
#include<conio.h>
#include<fstream>
#include<cstdlib>
#include<iostream>
#include<windows.h>
using namespace std;

typedef struct UFD
{
	string File_name;         //文件名
	int Start;                //文件在磁盤存儲空間的起始地址
	int Protect;              //文件的屬性
	int File_length;           //文件的長度
	int Max_File_length;         //文件的最大長度
	struct UFD *next;
	int i=0;
}UFD,*UFD_ptr;

typedef struct MFD
{
	string User_name;
	string User_passwd;
	UFD *Ufd_next;
	int End;
	struct MFD *next;
}MFD,*MFD_ptr;




typedef struct AFD
{
	string File_name;
	int File_length;
	int Start;
	int Protect;
	int Pointer;    //根據這個指針的值去完成用戶的要求  讀寫指針
	int Max_File_length;
	struct AFD *next;
}AFD,*AFD_ptr;

#endif // OSHEAD_H_INCLUDED

2.Main.cpp文件
 

#include"OSHead.h"

#define MaxDisk 512*1024   //一個扇區512字節,假設有1024個扇區,模擬磁盤的大小
int Max_User=10;
int Max_Open=5;
int Max_End=0;
UFD_ptr pufd=NULL;
MFD_ptr pmfd=NULL;
AFD_ptr pafd=NULL;
char User_name[30];   //存放當前用戶的用戶名
char flag='n';
char Disk_Size[MaxDisk];    //最後在打印輸出的時候,用RWX表示即可

int zone[10][2];
int x,y;

typedef struct Disk_Table
{
	int Max_length;      //最大長度
	int Start;          //開始位置
}Disk_Node;
Disk_Node Disk_Head;

void clean();
void sort();

void Init_Disk()
{
	Disk_Head.Max_length=MaxDisk;
	Disk_Head.Start=0;
}

bool Init_MFD()
{
	pmfd=(MFD *)new MFD;   //帶頭節點的單向鏈表
	MFD *p=pmfd;
	ifstream ifs("MFD.txt");  //文件的輸入流對象
	if(!ifs)
	{
		cerr<<"錯誤:無法打開文件"<<endl;
		p->next=NULL;
		p->Ufd_next=NULL;
		return false;
	}
	while(!ifs.eof())
	{
		p->next=(MFD *)new MFD;
		ifs>>p->next->User_name>>p->next->User_passwd>>p->next->End;
		if(p->next->End>Max_End)
			Max_End=p->next->End;
		p=p->next;
		p->Ufd_next=NULL;
		p->next=NULL;
	}
	ifs.close();
	return true;
}

void Print_UFD()
{
	UFD *p=pufd->next;
	if(!p)
	{
		cout<<"抱歉,該用戶沒有創建任何文件,請先創建!!!"<<endl;
		return ;
	}
	cout<<"文件名\t\t最大文件長度\t文件權限\t起始位置\t文件長度"<<endl;
	while(p)
	{
		cout<<p->File_name<<"\t\t"<<p->Max_File_length;
		if(p->Protect==0)
			cout<<"\t\t"<<"---";
		else if(p->Protect==1)
			cout<<"\t\t"<<"r-x";
		else if(p->Protect==2)
			cout<<"\t\t"<<"rwx";
		cout<<"\t\t"<<p->Start;
		cout<<"\t\t"<<p->File_length<<endl;
		p=p->next;
	}
}

bool Init_UFD(char *name)
{
	ifstream ifs(name);
	pufd=(UFD *)new UFD;
	UFD *p=pufd;
	char temp[MaxDisk];
	bool Index=false;
	if(!ifs)
	{
		cerr<<"錯誤:無法打開文件或尚未創建文件"<<endl;
		p->next=NULL;
		return false;
	}
	while(!ifs.eof())
	{
		memset(temp,'\0',sizeof(temp));
		p->next=(UFD *)new UFD;
		if(!Index)
		{
			pmfd->Ufd_next=p->next;
			Index=true;
		}
		ifs>>p->next->File_name>>p->next->Max_File_length>>p->next->Protect>>p->next->Start>>p->next->File_length;
		ifs>>temp;
		if(temp[0]=='#')
			temp[0]='\0';
		for(int i=p->next->Start,j=1;j<=p->next->Max_File_length-1;i++,j++)
		{
			Disk_Size[i]=temp[j-1];
			if(!Disk_Size[i])
				break;
		}
		Disk_Head.Max_length-=p->next->Max_File_length;
	//	Disk_Head.Start+=p->next->Max_File_length;
		p=p->next;
		p->next=NULL;
	}
	ifs.close();
	return true;
}

void Rename_File()
{
	string File_name;
	UFD *temp=pufd;
	char Index;
SD:
	cout<<"請輸入文件的名字:"<<endl;
	cin>>File_name;
	while(temp)
	{
		if(temp->File_name==File_name)
		{
			cout<<"請輸入新的文件名:"<<endl;
			cin>>File_name;
			temp->File_name=File_name;
			break;
		}
		temp=temp->next;
	}
	if(!temp)
	{
		cout<<"抱歉,輸入的文件不存在,無法完成重命名文件操作,是否繼續操作<y/n>?"<<endl;
		cin>>Index;
		if(Index=='y')
			goto SD;
		else
			return ;
	}
	else
		cout<<"修改成功!!!"<<endl;
}
bool User_Check()
{
	string User_passwd;
	int Count=0;
	while(1)
	{
		cout<<"請輸入用戶名:";
		cin>>User_name;
INIT:
		cout<<"請輸入密碼:";
		cin>>User_passwd;
		MFD *p=pmfd->next;
		char temp[30];
		memset(temp,'\0',sizeof(temp));
		strcpy(temp,User_name);
		Count++;
		while(p)
		{
			if(User_name==p->User_name)
			{
				if(User_passwd==p->User_passwd)
					cout<<"登入成功."<<endl;
				else
				{
					cout<<"抱歉,密碼錯誤,登陸失敗,請重新輸入!!!"<<endl;
					if(Count==3)
					{
						cout<<"密碼錯誤次數過多,系統運行結束!!!"<<endl;
						return false;
					}
					goto INIT;
				}
				strcat(temp,".txt");
				Init_UFD(temp);
	//			Print_UFD();
				Disk_Head.Start=Max_End;
				return true;
			}
			p=p->next;
		}
		cout<<"用戶名不存在,請重新輸入!!!"<<endl;
	}
//	return false;
}
void Init_AFD()
{
	pafd=(AFD *)new AFD;
	pafd->next=NULL;
}

bool Create_MFD()//創建文件命令
{
	string User_name;
	char User_passwd[30];
	MFD *p = pmfd;
	cout<<"請輸入要創建的用戶名: ";
	cin>>User_name;
	cout<<"請輸入"<<User_name<<"用戶的密碼:(默認爲:admin)";
	getchar();
	cin.getline(User_passwd,30);
	if(User_passwd[0]=='\0')
		strcpy(User_passwd,"admin");
	while(p)
	{
		if(User_name==p->User_name)
		{
			cout<<"此用戶名已存在!!!"<<endl;
			return false;
		}
		if(!p->next)
			break;
		p= p->next;
	}
	p->next = (MFD *)new MFD;  //尾插法
	p=p->next;
	p->User_name=User_name;
	p->User_passwd=User_passwd;
	p->End=0;
	p->next = NULL;
	p->Ufd_next = NULL;
	Max_User--;
	return true;
}  //應該是 不同的用戶下的UFD文件名是不一樣的啊,怎麼出問題了

bool Create_UFD()//創建文件命令
{
	string File_name;
	UFD *p = pufd;
	unsigned int Protect;
	int Max_File_length;
//	AFD *pa = pafd;
	cout<<"請輸入要創建的文件名: ";
	cin>>File_name;
	cout<<"請輸入要創建的文件保護類型:";
	cin>>Protect;
	cout<<"請輸入文件的最大容量:"<<endl;
	cin>>Max_File_length;
	while(p)
	{
		if(File_name==p->File_name)
		{
			cout<<"此文件名已存在!!!"<<endl;
			return false;
		}
		if(!p->next)
			break;
		p= p->next;
	}
    for(int i=0;i<10;i++){
        if(zone[i][1] >= Max_File_length){
            cout<<zone[i][0]<<" "<<zone[i][1]<<endl;
            p->next = (UFD *)new UFD;  //尾插法
            p=p->next;
            p->File_name=File_name;
            p->Max_File_length=Max_File_length;
            p->Start=zone[i][0];
            p->Protect = Protect;
            p->File_length = 0;     //剛創建文件時,文件是空的
            p->next = NULL;      //我覺得這部分代碼有問題;用戶創建了一個文件並不代表該文件就被打開了
            zone[i][0]+=Max_File_length;
            zone[i][1]-=Max_File_length;
            clean();
            sort();
            return true;
        }
    }
    for(int i=0;i<10;i++){
        cout<<zone[i][0]<<" "<<zone[i][1]<<endl;
    }
	p->next = (UFD *)new UFD;  //尾插法
	p=p->next;
	p->File_name=File_name;
	p->Max_File_length=Max_File_length;
	p->Start=Disk_Head.Start;
	p->Protect = Protect;
//	p->Time_info=      //暫定
	p->File_length = 0;     //剛創建文件時,文件是空的
	Disk_Head.Start+=Max_File_length;
	p->next = NULL;      //我覺得這部分代碼有問題;用戶創建了一個文件並不代表該文件就被打開了
	return true;
}

bool Delete_UFD()  //關於主目錄的用戶文件夾的文件刪除-->先這樣寫,好吧    //如果文件已經打開了,是不能刪除的
{
	string File_name;
	cout<<"請輸入要刪除的文件名:";
	cin>>File_name;
	UFD *p=pufd,*temp;
	AFD *pa=pafd;
	while(pa->next)
	{
		if(File_name==pa->next->File_name)
		{
			cout<<"抱歉,該文件已被打開,請先關閉,再進行刪除操作!!!"<<endl;
			return false;
		}
	}
	while(p->next)
	{
		if(File_name==p->next->File_name)
		{
		    if(p->next->next == NULL){
                temp=p->next;
                Disk_Head.Start-=p->next->Max_File_length;
                p->next=p->next->next;  //如果說要回收模擬的磁盤空間的話,應該是回收最大長度
                //	Disk_Head.Max_length+=temp->Max_File_length;    //鏈表中刪除了,其他的文件內容的起始位置不變即可,又沒事,還是照樣可以訪問數據的嘛
                delete temp;
                cout<<"文件刪除成功!!!"<<endl;
			return true;
		    }else{
		    x=p->next->Start;
		    y=p->next->Max_File_length;
            for(int i=0;i<10;i++){
                if(zone[i][1]==0){
                    zone[i][0]=0;
                }
                if((zone[i][0]==0) && (zone[i][1]==0)){
                 zone[i][0]=x;
                 zone[i][1]=y;
                 break;
                }
            }
            for(int i=0;i<10;i++){
                cout<<zone[i][0]<<" "<<zone[i][1]<<endl;
            }
            clean();
            sort();
			temp=p->next;
			p->next=p->next->next;  //如果說要回收模擬的磁盤空間的話,應該是回收最大長度
		//	Disk_Head.Max_length+=temp->Max_File_length;    //鏈表中刪除了,其他的文件內容的起始位置不變即可,又沒事,還是照樣可以訪問數據的嘛
			delete temp;
			cout<<"文件刪除成功!!!"<<endl;
			return true;
		    }
		}
		p=p->next;
	}
	cout<<"抱歉,要刪除的文件不存在!!!"<<endl;
	return false;
}

bool Open()
{
    string File_name;
	unsigned int Protect;
	cout<<"請輸入要打開的文件名:";
    cin>>File_name;
    UFD *p=pufd->next;
	AFD *pa=pafd->next;
	while(pa)
	{
		if(File_name==pa->File_name)
		{
			cout<<"文件"<<File_name<<"已經打開!!!"<<endl;
			return true;
		}
		if(!pa->next)
			break;
		pa=pa->next;
	}
	if(!pa)     //如果找不到,或者打開的文件目錄鏈表爲空表
		pa=pafd;
	while(p)
	{
        if(File_name==p->File_name)
		{
			if(!Max_Open)
			{
				cout<<"抱歉,最多隻能打開5個文件,請先關閉其他打開的文件再操作!!!"<<endl;
				return false;
			}
			if(p->Protect==0)
			{
				cout<<"抱歉,此文件不可執行任何操作!!!"<<endl;
				return false;
			}
			cout<<"請選擇以什麼樣的方式打開文件<1-只讀,2-可讀可寫>:";
			cin>>Protect;
			pa->next=(AFD *)new AFD;
			pa=pa->next;
			pa->File_name=p->File_name;
			pa->Start=p->Start;
			pa->File_length=p->File_length;
			pa->Max_File_length=p->Max_File_length;
			pa->Protect=Protect;
			if(Protect==1)
				pa->Pointer=0;   //Poniter取0表示此時用戶無法寫數據(沒有空間的含義)
			else
				pa->Pointer=p->File_length;
			pa->next=NULL;
			Max_Open--;
			cout<<"文件"<<File_name<<"已經打開!!!"<<endl;
			return true;
		}
		p=p->next;
	}
	cout<<"抱歉,要打開的文件不存在!!!"<<endl;
	return false;
}
void Close()
{
	string file_name;
	UFD *pu=pufd->next;
	cout<<"請輸入要關閉的文件名:";
	cin>>file_name;
	AFD *p=pafd,*temp;
	while(p&&p->next)
	{
		if(file_name==p->next->File_name)
		{
			temp=p->next;
			p->next=p->next->next;
			if(temp->Protect==2)      //可寫的文件纔有權把新寫入的數據也保存起來嘛
			{
				while(pu)
				{
					if(temp->File_name==pu->File_name)
					{
						pu->File_length=temp->Pointer;
						break;
					}
					pu=pu->next;
				}
			}
			delete temp;
			cout<<"文件"<<file_name<<"關閉成功!!!"<<endl;
			return ;
		}
		p=p->next;
	}
	cout<<"抱歉,要關閉的文件沒有被打開!!!"<<endl;
}
bool Read_File()  //因爲讀寫都是通過修改運行文件目錄的Pointer去模擬的嘛
{
	string File_name;       //你要讀文件的話,你這文件肯定得在運行/打開文件目錄裏面,是吧
	unsigned int length;
	AFD *p=pafd->next;
	cout<<"請輸入要讀的文件名:";
	cin>>File_name;
	cout<<"請輸入要讀取的長度:";  //讀取的話,實際中文件的長度並不會改變
	cin>>length;          //即讀取的長度並不能保存回去,爲了方便(如果用戶是讀數據的話,pointer始終不變)
	while(p)
	{
		if(File_name==p->File_name)
		{
			for(int i=p->Start,j=1;j<=length;i++,j++)
				cout<<Disk_Size[i];
			cout<<endl;
			cout<<"文件"<<File_name<<"讀取成功!!!"<<endl;
			return true;
		}
		p=p->next;
	}
	cout<<"讀取失敗,文件沒有打開過!!!"<<endl;
	return false;
}
bool Write_File()  //寫的話,自然是運行文件目錄
{
	string File_name;
	unsigned int length;
	AFD *p=pafd->next;
	char temp[MaxDisk]={'\0'};
	cout<<"請輸入要寫的文件名:";
	cin>>File_name;
	while(p)
	{
		if(File_name==p->File_name)
		{
			if(p->Protect!=2)
			{
				cout<<"文件"<<File_name<<"不可寫"<<endl;
				return false;
			}
			cout<<"請輸入要寫入的長度:"<<endl;
			cin>>length;
			if(p->Pointer+length<=p->Max_File_length)
			{
				cout<<"請寫入指定長度的內容:<以回車作爲結束符>"<<endl;
				getchar();
				gets(temp);
				for(int i=p->Start+p->File_length,j=1;j<=strlen(temp);i++,j++)
					Disk_Size[i]=temp[j-1];
				p->Pointer += length;
				cout<<"文件"<<File_name<<"寫入成功!!!"<<endl;
			}
			else
			{
				cout<<"欲寫入的數據大小發生溢出,已超過文件的分配容量,寫入失敗!!!"<<endl;
				return false;
			}
			return true;
		}
		p=p->next;
	}
	cout<<"寫入失敗,文件沒有打開過!!!"<<endl;
	return false;
}
void Destroy_Space()
{
	MFD *pm=pmfd;
	while(pm)
	{
		pmfd=pmfd->next;
		delete pm;
		pm=pmfd;
	}
	AFD *pa=pafd;
	while(pa)
	{
		pafd=pafd->next;
		delete pa;
		pa=pafd;
	}
	UFD *pu=pufd;
	while(pu)
	{
		pufd=pufd->next;
		delete pu;
		pu=pufd;
	}
}

void Save_MFD()
{
	ofstream ofs;        //文件的輸出流對象
	ofs.open("MFD.txt");
	if(!ofs.is_open())
	{
		cout<<"The MFD can't open!!!"<<endl;
		if(flag=='y')
			cout<<"正在保存主目錄用戶名信息..."<<endl;
		else
			ofs.close();  //該語句待定
	}
	MFD *p=pmfd->next;
	while(p)
	{
		if(p->User_name==User_name)
			p->End=Disk_Head.Start;
		ofs<<p->User_name<<" "<<p->User_passwd<<" "<<p->End;
		if(p->next)
			ofs<<"\n";
		p=p->next;
	}
	ofs.close();
}

void Save_UFD(char *name)
{
	ofstream ofs;        //文件的輸出流對象
	char temp[MaxDisk]={'\0'};
	ofs.open(name);
	if(!ofs.is_open())
	{
		cout<<"The "<<name<<"文件 can't open!!!"<<endl;
		ofs.close();  //該語句待定,這語句真的用的很妙,因爲我並沒有馬上退出這次函數調用了
	}
	UFD *p=pufd->next;
	while(p)
	{
		memset(temp,'\0',sizeof(temp));
		for(int i=p->Start,j=1;j<=p->Max_File_length;i++,j++)
		{
			if(Disk_Size[i])
				temp[j-1]=Disk_Size[i];
			else
				break;
		}
		if(!temp[0])        //如果文件沒有數據的話,就用空格表示此文件沒有任何內容
			temp[0]='#';
		ofs<<p->File_name<<" "<<p->Max_File_length<<" "<<p->Protect<<" "<<p->Start<<" "<<p->File_length<<" "<<temp;
		if(p->next)
			ofs<<"\n";
		p=p->next;
	}
	ofs.close();
}

void Quit_System()
{
	AFD *pa=pafd->next;
	UFD *pu=pufd->next;
	while(pa)
	{
		if(pa->Protect==2)  //2表示可寫   //1表示只讀  //0表示不可操作
		{
			while(pu)
			{
				if(pa->File_name==pu->File_name)
				{
					pu->File_length=pa->Pointer;
					break;
				}
				pu=pu->next;
			}
		}
		pa=pa->next;
	}
	char temp[30];
	strcpy(temp,User_name);
	strcat(temp,".txt");
	Save_MFD();
	Save_UFD(temp);
	Print_UFD();
	Destroy_Space();
}

void Print_Help()
{
	//system("color 0b");
	cout<<"************************二級文件系統演示*************************"<<endl;
	cout<<"*\t\t命令			  說明			*"<<endl;
	cout<<"*\t\tlogin			登錄系統		*"<<endl;
	cout<<"*\t\tcreate			創建文件		*"<<endl;
	cout<<"*\t\tdelete			刪除文件		*"<<endl;
	cout<<"*\t\topen			打開文件		*"<<endl;
	cout<<"*\t\tclose			關閉文件		*"<<endl;
	cout<<"*\t\tread			讀取文件		*"<<endl;
	cout<<"*\t\twrite			寫入文件		*"<<endl;
	cout<<"*\t\tls		        顯示目錄		*"<<endl;
	cout<<"*\t\trename			重命文件		*"<<endl;
	cout<<"*\t\thelp			幫助菜單		*"<<endl;
	cout<<"*\t\tcls 			清除屏幕		*"<<endl;
	cout<<"*\t\tlogout 			切換用戶		*"<<endl;
	cout<<"*\t\tquit			退出系統		*"<<endl;
	cout<<"*****************************************************************"<<endl;
}
void System_Init()
{
Start:
	Print_Help();
	Init_Disk();
	if(!Init_MFD())
	{
		int num;
		cout<<"主目錄還未創建,是否創建<y/n>!!!"<<endl;
		cin>>flag;
		cout<<"請輸入欲創建的用戶文件夾的個數(1-10):"<<endl;
		cin>>num;
		if(flag=='y')
		{
			while(num--)
			{
				Create_MFD();
				if(!Max_User)
				{
					cout<<"本系統,最多支持10個用戶,創建多餘用戶失敗,請刪除其他用戶,再做嘗試!!!"<<endl;
					return ;
				}
			}
			Save_MFD();
			cout<<"主目錄已經創建完成,用戶各自目錄已得到保存,是否繼續<y/n>!!!"<<endl;
			cin>>flag;
			if(flag=='y')
				goto Start;
		}
	}
	return ;
}


void File_System()
{
	while(1)
	{
		string Command;
		cout<<"請輸入命令:";
		cin>>Command;
		if(Command=="create")
			Create_UFD();
		else if(Command=="delete")
			Delete_UFD();
		else if(Command=="open")
			Open();
		else if(Command=="close")
			Close();
		else if(Command=="read")
			Read_File();
		else if(Command=="write")
			Write_File();
		else if(Command=="quit")
		{
			Quit_System();
			break;
		}
		else if(Command=="ls")
			Print_UFD();
		else if(Command=="cls")
			system("cls");
		else if(Command=="login")
		{
			if(!User_Check())
				break;
			Init_AFD();
		}
		else if(Command=="rename")
			Rename_File();
		else if(Command=="logout")
		{
			cout<<"用戶登出成功!!!"<<endl;
			Quit_System();
			System_Init();
			File_System();
		}
		else
			Print_Help();
	}
}

void clean(){
    int k,l;
    int temp;
    for(k=0;k<10;k++){
        temp=zone[k][0]+zone[k][1];
        //if(temp == Disk_Head.Start){
        //    zone[k][0]=0;
        //    zone[k][1]=0;
        //}
        for(l=0;l<10;l++){
            if(temp == zone[l][0]){
                zone[k][1]=zone[k][1]+zone[l][1];
                zone[l][0]=0;
                zone[l][1]=0;
                temp=zone[k][0]+zone[k][1]; //IIIIIIIIIIII
            }
        }
    }
}
void sort(){
    int k,l;
    int temp,temp2;
    for(k=0;k<10;k++){
        for(l=k+1;l<10;l++){
            if(zone[l][0] < zone[k][0]){

             temp=zone[k][0];
             zone[k][0]=zone[l][0];
             zone[l][0]=temp;

             temp=zone[k][1];
             zone[k][1]=zone[l][1];
             zone[l][1]=temp;
            }
        }
    }
}


int main()   //我保存,我不能連我的指針域也保存啊,這是不對的吧
{
	System_Init();
	File_System();
	return 0;
}

後面的分析等我,喫點飯,回宿舍,用自己的筆記本繼續更。

三、算法分析

本文件系統實現所用的最主要的是單鏈表,單鏈表結構簡單,也沒實現多麼複雜的算法,主要是對程序幾個重要的程序進行解釋。

採用單鏈表實現的文件存儲結構爲連續式存儲方案。2019年6月28日23:04:09

1.Create函數

用來創建一個新文件,實現過程如下,當用戶輸入Create命令後,程序會優先尋找之前刪除的文件的空間大小是否能夠滿足新文件的大小要求,如果能滿足要求,那就優先分配該空間,假如,刪除文件帶來的空閒空間不足,則採用尾插法在鏈表末端新建一個新節點,存儲該文件的屬性信息。

既然這麼分配措施,那麼就很有必要實現,分配和回收

1.空間分配 :將模擬的磁盤空間分配給文件

2.空間整理:因爲採用連續式存儲方案,所以刪除文件,被刪除文件後面的文件位置是不會移動的,那就導致了,刪除文件後,就留下了一段空閒空間,按照連續式存儲方案,所以假設又要新建文件的話,該空間大小如果合適,就有優先分配該空間。

還有就是,當這個文件刪除後,假設,後面連續的文件也被刪除了,所以,就需要將這兩塊空間合併爲一塊。

再者就是,假設被刪除的文件是鏈表最後一個文件,他的指針不指向任何文件,(p->next == NULL),所以該文件相當於指向還沒有用過的空間,所以刪除最後一個文件,空間的處理方案和其他的也不同,我們需要釋放這塊空間,讓這塊空間和後面的未使用過的空間重新合併。

(這裏是昨天,在驗收的時候發現的BUG,昨天下午,自己在機房自閉想出來的問題,和解決方案)

3.優先分配

優先分配,出現在這樣的情況下,假設連續刪除了好幾個不連續的文件,所以產生了好幾個,不連續的空閒空間塊,那麼按照怎樣的順序分配這些空間給符合大小的新文件呢?

答案就是從前往後,優先分配首地址小的空間。

針對上面三個需求就要,設置合適的算法實現該功能。

我寫了 INT ZONE[10][2],這個數組用來記住空閒空間,刪除文件時,被刪除文件的首地址和文件長度,二維數組的第一項用來存儲空閒空間首地址,第二項用來存儲空間長度,10和2是可以改的,我只是假設記錄10個空閒空間。

同時寫了Clean()空間整理函數,Sort()排序函數。

這兩個函數每次都是在空閒空間改變的時候調用,Clean函數用來整理和合並空閒空間,假設二維數組的某一項首地址+空間長度 = 某一項的首地址,所以就把這兩塊空閒空間合併,首地址爲小的那個地址,空間長度擴充爲第一個空間的空間長度+第二個空間的空間長度,因爲第二個空間和第一個空間合併了,所以就把第二塊空間初始化(首地址設爲0,空間長度設爲0)。

Sort函數,對這個二維數組進行按照首地址大小排序,首地址小的在前面,首地址大的在後面。

所以這樣就實現了空間整理,優先分配。

Create函數在創建新文件的時候,從前往後順序便利這個二維數組,假設有合適空間大小的空閒空間塊就優先分配這塊。假設空閒塊中沒有合適的空間塊,那麼就採用尾插法,在鏈表最後新建一個新節點,存儲新文件信息。

Delete函數

感覺前面說了這麼多,感覺Delete函數沒有什麼好說的了,用戶輸入所需要刪除的文件名字,找到後,假設這個文件是首地址最大的文件(想到課設裏面有一個問題,剛想到的一個小BUG,我是判定鏈表最後一個文件,鏈表最後一個文件不一定是首地址最大的文件,一定是最新新建的文件,所以我的課設判定條件是錯誤的),接着說,判定文件的時候,要判斷這個文件是不是首地址最大的文件,

假設是就直接刪除這個文件,

假設不是,就先將這個文件的首地址和文件長度存入Zone[][]數組中,並進行Clean() ,Sort()函數,整理和排序。

好吧感覺寫的差不多了。

其他函數

感覺其他函數沒有什麼好說的,主要是一些字符串操作和文件操作,文件要和源文件放在同一文件夾下。否則要給出路徑。

好吧這次課設,因爲Zhai老師的認真負責還是學到了很多東西,不過課設安排的有些浪費時間,少了好多複習時間,考試還要努力啊,

以上就是本人這次代碼的拙見,各位大佬,若是發現什麼問題或者什麼錯誤,或者要一起探討一下代碼,歡迎評論。


而且,19週考試要考4門,週一概率論,周N操作系統,我的天,就剩下兩天的複習時間,一個垃圾課設居然這麼拖拖拉拉,肝疼。呵呵,老師在平臺上就不大聲說話了,明天去驗收,我真想WTM,

收穫和感悟記得要更!!!!!!!!!!!!!!!!!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章