实现一个简单的文件系统,支持一些基本操作,目前的版本非常简陋以及鲁棒性比较差~( ̄0 ̄)/
结构
将文件系统组织成一个目录树,每个节点为目录,节点的属性包括{目录名,当前路径,父节点,子目录们,该目录下的文件}
因此,我们可以定义我们的节点属性:
struct node {
string name;
string pwd;
node *fa;
//save dirs
set<node*> sons;
//save files
set<string> files;
}
在OS中,文件是通过文件名索引的, 我们在查找目录的时候,我们是通过目录名称索引目录的,因此,还需要创建一个目录名称到目录节点的索引:
map<string, node*> basic;
操作
ls(列出该目录下的所有目录和文件)
首先,每个文件目录下,都包含“.”和“..”,分别代表当前目录和上一个目录,然后,我们只需要遍历它的子节点(目录们),该目录下的文件即可。从我们之前对目录结构的定义,可以方便的通过遍历set来遍历目录和文件
void ls() {
cout << "Directories: " << endl;
cout << "." << "\t" << ".." << "\t";
for (auto t : sons) {
if (t != fa && t != this) {
cout << t->name << "\t";
}
}
cout << endl;
cout << "Files: " << endl;
for (auto t : files) {
cout << t << "\t";
}
cout << endl;
}
cd(跳转的相应目录)
目前版本只支持相对路径的跳转,并且只能单步跳转
首先,“.”和“..”特判一下,然后,我们再去索引相应的目录。这时候,我们在结构体里面设计的basic就有用了。首先,通过basic从目录名称映射到我们的节点,然后,把当前节点的指针cur指向basic映射到的节点即可
if (cmd.substr(0, 2) == "cd") {
string t = cmd.substr(3, cmd.size() - 3);
if (t == ".") {
continue;
}
if (t == "..") {
if (cur == root) continue;
cur = cur->fa;
continue;
}
if (cur->basic.find(t) == cur->basic.end()) {
cout << "No such folder" << endl;
} else {
node *next = cur->basic[t];
cur = next;
}
continue;
}
mkdir(在当前目录下新建一个目录)
新建一个节点,并且将当前节点cur的子节点中加入该新节点,创建新的索引,并且更新路径
if (cmd.substr(0, 5) == "mkdir") {
string t = cmd.substr(6, cmd.size() - 6);
node* tmp = new node(cur, t);
cur->basic[t] = tmp;
cur->sons.insert(tmp);
continue;
}
rmdir(在当前目录下删除一个目录)
首先,我们在basic里面去查找该目录下有没有我们要删除的目录,如果找到了,我们只需要把它从sons的set里面删掉,并且把索引也删掉即可
if (cmd.substr(0, 5) == "rmdir") {
string t = cmd.substr(6, cmd.size() - 6);
bool flag = false;
for (auto it = cur->basic.begin(); it != cur->basic.end(); it++) {
if (it->first == t) flag = true;
}
if (!flag) {
cout << "No such folder" << endl;
continue;
}
//del map from basic;
for (auto it = cur->basic.begin(); it != cur->basic.end(); it++) {
if (it->first == t) {
cur->basic.erase(it);
break;
}
}
//del node from sons;
for (auto it = cur->sons.begin(); it != cur->sons.end(); it++) {
node *tnode = *it;
if (tnode->name == t) {
cur->sons.erase(it);
break;
}
}
continue;
}
touch(新建一个文件)
只需要在当前节点的files的set里面插入该文件名即可
if (cmd.substr(0, 5) == "touch") {
string t = cmd.substr(6, cmd.size() - 6);
if (cur->files.find(t) != cur->files.end()) {
cout << "File already exist" << endl;
continue;
}
cur->files.insert(t);
continue;
}
rm(删除一个文件)
通过在files的集合里面查找文件,判断文件是否存在,如果存在,从set里面删除它即可
if (cmd.substr(0, 2) == "rm") {
string t = cmd.substr(3, cmd.size() - 3);
if (cur->files.find(t) == cur->files.end()) {
cout << "No such file" << endl;
continue;
}
for (auto it = cur->files.begin(); it != cur->files.end(); it++) {
if (*it == t) {
cur->files.erase(it);
break;
}
}
continue;
}
pwd(获取当前路径)
在每次新建一个子节点的时候,更新子节点的路径
pwd = pa->pwd + s + "/";
代码
最后,我们完整的代码如下:
#include <bits/stdc++.h>
using namespace std;
struct node {
string name;
string pwd;
node *fa;
//save dirs
set<node*> sons;
//save files
set<string> files;
map<string, node*> basic;
node(string s) {
name = s;
fa = NULL;
files.clear();
}
node(node *pa, string s) {
name = s;
pwd = pa->pwd + s + "/";
fa = pa;
files.clear();
}
void ls() {
cout << "Directories: " << endl;
cout << "." << "\t" << ".." << "\t";
for (auto t : sons) {
if (t != fa && t != this) {
cout << t->name << "\t";
}
}
cout << endl;
cout << "Files: " << endl;
for (auto t : files) {
cout << t << "\t";
}
cout << endl;
}
};
node* cur;
node* root;
void init() {
root = new node("/");
root->name = "root";
root->pwd = "/";
root->basic["."] = root;
root->basic[".."] = root;
}
int main() {
init();
cur = root;
while (1) {
cout << "lz console: ";
string cmd;
getline(cin, cmd);
if (cmd == "quit") break;
//call cd
if (cmd.substr(0, 2) == "cd") {
string t = cmd.substr(3, cmd.size() - 3);
if (t == ".") {
continue;
}
if (t == "..") {
if (cur == root) continue;
cur = cur->fa;
continue;
}
if (cur->basic.find(t) == cur->basic.end()) {
cout << "No such folder" << endl;
} else {
node *next = cur->basic[t];
cur = next;
}
continue;
}
//call pwd
if (cmd == "pwd") {
cout << cur->pwd << endl;
continue;
}
//call ls
if (cmd.substr(0, 2) == "ls") {
cout << "Directories: " << endl;
cout << "." << "\t" << ".." << "\t";
for (auto t : cur->sons) {
if (t == cur->fa || t == cur) continue;
cout << t->name << "\t";
}
cout << endl;
cout << "Files: " << endl;
for (auto t : cur->files) {
cout << t << "\t";
}
cout << endl;
continue;
}
//call mkdir
if (cmd.substr(0, 5) == "mkdir") {
string t = cmd.substr(6, cmd.size() - 6);
node* tmp = new node(cur, t);
cur->basic[t] = tmp;
cur->sons.insert(tmp);
continue;
}
//rmdir
if (cmd.substr(0, 5) == "rmdir") {
string t = cmd.substr(6, cmd.size() - 6);
cout<< t << endl;
bool flag = false;
for (auto it = cur->basic.begin(); it != cur->basic.end(); it++) {
if (it->first == t) flag = true;
}
if (!flag) {
cout << "No such folder" << endl;
continue;
}
//del map from basic;
for (auto it = cur->basic.begin(); it != cur->basic.end(); it++) {
if (it->first == t) {
cur->basic.erase(it);
break;
}
}
//del node from sons;
for (auto it = cur->sons.begin(); it != cur->sons.end(); it++) {
node *tnode = *it;
if (tnode->name == t) {
cur->sons.erase(it);
break;
}
}
continue;
}
//touch file
if (cmd.substr(0, 5) == "touch") {
string t = cmd.substr(6, cmd.size() - 6);
if (cur->files.find(t) != cur->files.end()) {
cout << "File already exist" << endl;
continue;
}
cur->files.insert(t);
continue;
}
//rm file
if (cmd.substr(0, 2) == "rm") {
string t = cmd.substr(3, cmd.size() - 3);
if (cur->files.find(t) == cur->files.end()) {
cout << "No such file" << endl;
continue;
}
for (auto it = cur->files.begin(); it != cur->files.end(); it++) {
if (*it == t) {
cur->files.erase(it);
break;
}
}
continue;
}
}
return 0;
}