Mr.K 018 发布于四月 10, 2020 分享 发布于四月 10, 2020 (已修改) · 只看该作者 第二期来啦!!!!!!!! 本来打算放一道BIT校赛的题,搬运完后感觉有点难,于是留给周末两天做吧。 今天就换成了一道模拟题。模拟题不难,依题意模拟即可。 前排提示:这个题不是个操作系统题,原题是给大一同学(非ACM)做的寒假集训题 嘛 召唤阵忘掉了,这次就算了( 第2期 Linux目录系统 众所周知,在没有图形用户界面的年代,想要做事情都得输入命令才行。时至今日在Linux中还可以选择“打开控制台”来输入命令,通过在控制台输入命令可以做到很多只点鼠标做不到的事情。今天我们模拟的主题是基于命令行的Linux目录系统。 Linux中目录和Windows中文件夹的概念差不多。但是和Windows中每个盘有一个根目录不同,这里的目录系统只有一个根目录,叫做/。子目录和父目录间用斜杠/隔开,形如:/usr/src。 程序执行时有一个“工作目录”的概念,表示现在执行的程序在哪个目录上执行。根据工作目录可以定义相对目录,如当前工作目录若是/home/MrK018,那么相对目录Desktop/dir1就表示/home/MrK018/Desktop/dir1这个目录。特别地,我们定义.表示当前目录,..表示当前目录的父目录。 不妨认为目录系统是存在于内存上的,初始时只有根目录/。请实现如下内容: cd 将工作目录变为另一个目录; mkdir 新建一个目录; touch 新建一个文件(放心,我们没有文件读写方面的需求) ls 列出当前目录的所有直接子目录和文件; rm 删除文件,若是目录则递归地删除所有子目录和下属文件; 目录应首先当作视为相对目录,不能视为相对目录再视为绝对目录。在cd,rm等命令中遇找不到目录或文件的,输出一行Error: not found。文件名不允许为空也不允许带有斜杠,若与无法解析的文件名,输出一行Error: invalid name。 输入 输入包含多行,请读入到文件尾。每一行包含一个命令。 输出 命令的输出结果。除错误信息和ls的输出外,没有其他输出。 样例输入 mkdir usr mkdir usr/src mkdir usr/lib cd usr/lib touch anode touch glibc mkdir Apple mkdir /home/K/Desktop ls touch /home/K/Desktop/hello.txt mkdir ../include cd . cd .. cd inc ls rm lib touch openGL/ ls cd / touch etc/driver/sda1 touch etc/driver/sda1 touch etc2/driver/ cd etc/driver/ ls 样例输出 anode Apple/ glibc Error: not found include/ lib/ src/ Error: invalid name include/ src/ Error: invalid name Error: invalid name sda1 四月 10, 2020,由Mr.K 018修改 题目已更新,修了一些bug 1 链接到点评
yhz012 发布于四月 10, 2020 分享 发布于四月 10, 2020 (已修改) · 只看该作者 第一眼看是操作系统题,溜了溜了.jpg 第二眼看大概还好,感觉还能做 感觉基本就是构建一个树就可以了……? 四月 10, 2020,由yhz012修改 链接到点评
Mr.K 018 发布于四月 10, 2020 作者 分享 发布于四月 10, 2020 · 只看该作者 10 分钟前, ssynn 说道: 想起了当年操作系统的课程设计,不过这个网站上玩这个你是认真的?sstm oj指日可待 10 分钟前, yhz012 说道: 第一眼看是操作系统题,溜了溜了.jpg 这个题不是操作系统题哦~ 链接到点评
乱跑的泰兰德 发布于四月 10, 2020 分享 发布于四月 10, 2020 · 只看该作者 17 分钟前, Mr.K 018 说道: 目录应首先当作视为相对目录,不能视为相对目录再视为绝对目录。 linux不是刚开始有/就是绝对目录,没有就是相对目录么. 应该没有什么不能视为相对目录再视为绝对目录把( 链接到点评
随性而为 发布于四月 10, 2020 分享 发布于四月 10, 2020 · 只看该作者 这个题的意思是输入 mkdir 就真的在目录下创建文件,还是只是模拟,只在程序中意思意思创建啊 随性而为在路上看到一个蘑菇,捡起时被一个从天而降的木桶击中脑袋,花费了医药费 -4节操 链接到点评
Mr.K 018 发布于四月 10, 2020 作者 分享 发布于四月 10, 2020 · 只看该作者 刚刚, 随性而为 说道: 这个题的意思是输入 mkdir 就真的在目录下创建文件,还是只是模拟,只在程序中意思意思创建啊 模拟,不真建文件 也不会有操作系统API供使用的(盯 链接到点评
乱跑的泰兰德 发布于四月 10, 2020 分享 发布于四月 10, 2020 · 只看该作者 1 分钟前, 随性而为 说道: 这个题的意思是输入 mkdir 就真的在目录下创建文件,还是只是模拟,只在程序中意思意思创建啊 程序里,也就是仿造一个环境,假如输入了这些指令,会发生什么. 链接到点评
随性而为 发布于四月 10, 2020 分享 发布于四月 10, 2020 · 只看该作者 2 分钟前, Mr.K 018 说道: 模拟,不真建文件 也不会有操作系统API供使用的(盯 小心思被发现了 随性而为和寒幼藏在半夜盗取清禾的传国玉玺时,无意中挖出了清禾祖传的3DS,卖出手后获得了奖励6节操 链接到点评
乱跑的泰兰德 发布于四月 10, 2020 分享 发布于四月 10, 2020 · 只看该作者 1 分钟前, 随性而为 说道: 小心思被发现了 准备直接import os os.system()来做吗哈哈哈哈哈哈哈 乱跑的泰兰德穿越到里区后,遇见了一只九尾狐狸,完成了她交付的汉化任务后被抚摸。4节操 链接到点评
Mr.K 018 发布于四月 10, 2020 作者 分享 发布于四月 10, 2020 · 只看该作者 4 分钟前, 随性而为 说道: 小心思被发现了 有一说一,这是个模拟题 而且就算用了操作系统API,本质上树还是那棵树啊( 还是说能贪一行就贪一行wwwww 链接到点评
yhz012 发布于四月 10, 2020 分享 发布于四月 10, 2020 · 只看该作者 刚刚, Mr.K 018 说道: 这个题不是操作系统题哦~ 看了一下,感觉最暴力的方法就是维护一个树结构 struct node{ bool folderFlag; char nameLen; char name[128]: struct node *parent; struct node *childrenListHead; struct node *next; }; 层间用树结构组织,层内用循环链表组织大概就可以了吧…… 链接到点评
随性而为 发布于四月 10, 2020 分享 发布于四月 10, 2020 · 只看该作者 刚刚, 乱跑的泰兰德 说道: 准备直接import os os.system()来做吗哈哈哈哈哈哈哈 我还没那么厉害,关于操作系统的api我目前只知道c语言的fopen(),fclose() 我目前只知道c语言,数据结构,html5、c++(现在在学),java(现在在学) 随性而为在诱导萌新女装时被路过的随便拦下,被批评教育并收取学费-3节操 链接到点评
Mr.K 018 发布于四月 10, 2020 作者 分享 发布于四月 10, 2020 · 只看该作者 刚刚, yhz012 说道: 看了一下,感觉最暴力的方法就是维护一个树结构 struct node{ bool folderFlag; char nameLen; char name[128]: struct node *parent; struct node *childrenListHead; struct node *next; }; 层间用树结构组织,层内用循环链表组织大概就可以了吧…… 没错,这就是本题的全部算法 也正因为如此,本期算法po上来是不够的~ 链接到点评
随性而为 发布于四月 10, 2020 分享 发布于四月 10, 2020 · 只看该作者 刚刚, Mr.K 018 说道: 没错,这就是本题的全部算法 也正因为如此,本期算法po上来是不够的~ 欸,这就秒杀了吗 链接到点评
yhz012 发布于四月 10, 2020 分享 发布于四月 10, 2020 (已修改) · 只看该作者 1 分钟前, Mr.K 018 说道: 没错,这就是本题的全部算法 也正因为如此,本期算法po上来是不够的~ 写C系的好累,我还是决定滚去用py写了(x 艹,等下,py没有指针有点烦(x 那我还是滚去用带类C的C++写好了(x 四月 10, 2020,由yhz012修改 1 链接到点评
Mr.K 018 发布于四月 10, 2020 作者 分享 发布于四月 10, 2020 · 只看该作者 1 分钟前, 随性而为 说道: 欸,这就秒杀了吗 这题是个模拟题啊,算法就是这么个算法 模拟题的性质就是几乎没有啥算法,难点全在复杂的程序逻辑(a.k.a.代码量)上面,因此这个题要到伪代码/代码层面才算数哦~ Mr.K 018收和谐资源时被小萝莉围观良心发现失去-2节操 1 链接到点评
yhz012 发布于四月 10, 2020 分享 发布于四月 10, 2020 (已修改) · 只看该作者 提个问题,mkdir是可以一个命令建立多层文件夹的,但是touch看起来是不能连带着文件夹一起建立文件的? 比如说 touch openGL/ 这句话,是因为不存在openGL这个文件夹,所以认为 openGL/ 整个是个文件名,带了反斜杠所以失败了 还是因为后面的文件名为空失败了? 换句话说,如果用的是 touch openGL/a.txt 怎么处理? 以及对于mkdir一个命令建立多层文件夹,如果其中出现了非法文件夹名,怎么处理,把之前的新建文件夹全都撤销掉,还是建了的保留? 举例来说 原来只有根目录的情况,执行 mkdir /a/b/../c 中间的..是非法文件夹名的吧? 这种情况下,我需要把文件夹a和文件夹b也一起撤销掉吗?还是说留着/a/b就可以了? 四月 10, 2020,由yhz012修改 链接到点评
ZERC 发布于四月 10, 2020 分享 发布于四月 10, 2020 · 只看该作者 1 小时前, 原初の冷火 说道: 新人刚来这个论坛 这里就是传说中的csdn嘛 是啊,三次元区转型了www 链接到点评
Mr.K 018 发布于四月 10, 2020 作者 分享 发布于四月 10, 2020 (已修改) · 只看该作者 30 分钟前, yhz012 说道: 提个问题,mkdir是可以一个命令建立多层文件夹的,但是touch看起来是不能连带着文件夹一起建立文件的? 比如说 touch openGL/ 这句话,是因为不存在openGL这个文件夹,所以认为 openGL/ 整个是个文件名,带了反斜杠所以失败了 还是因为后面的文件名为空失败了? 换句话说,如果用的是 touch openGL/a.txt 怎么处理? 以及对于mkdir一个命令建立多层文件夹,如果其中出现了非法文件夹名,怎么处理,把之前的新建文件夹全都撤销掉,还是建了的保留? 举例来说 原来只有根目录的情况,执行 mkdir /a/b/../c 中间的..是非法文件夹名的吧? 这种情况下,我需要把文件夹a和文件夹b也一起撤销掉吗?还是说留着/a/b就可以了? touch openGL/失败是因为不能把openGL/识别为一个指向文件名的目录元素。touch openGL/lib.lib就可以执行 指令应该有一些原子性,如果执行失败,整个命令应该什么都不做 抱歉题目有一些不完整,我稍后做补充 四月 10, 2020,由Mr.K 018修改 Mr.K 018路过听到路过酱的歌声,不小心被路过的鸡仔绊倒,受到了路过酱的赔偿金5节操 链接到点评
yhz012 发布于四月 10, 2020 分享 发布于四月 10, 2020 (已修改) · 只看该作者 1 小时前, Mr.K 018 说道: touch openGL/失败是因为不能把openGL/识别为一个指向文件名的目录元素。touch openGL/lib.lib就可以执行 指令应该有一些原子性,如果执行失败,整个命令应该什么都不做 抱歉题目有一些不完整,我稍后做补充 辛苦啦 我还是决定滚去python了(x 反正伪代码也可以,那我用py也没问题了吧(x 果然我已经是py的形状了 class node(object): #基类 def __init__(self, name, parent): super(node, self).__init__() self.name = name self.parent = parent if self.parent is not None: if hasattr(self.parent, 'childList'): self.parent.childList.append(self) else: print('Error: no childList') return class fileNode(node): #文件 def __init__(self, name, parent): super(fileNode, self).__init__(name, parent) self.isFolder = False return def remove(): self.parent.childList.remove(self) return class folderNode(node): #文件夹 def __init__(self, name, parent): super(folderNode, self).__init__(name, parent) self.isFolder = True self.childList = [] return def remove(): for child in childList: child.remove() self.parent.childList.remove(self) return class envTree(object): #环境 def __init__(self, localDir): super(envTree, self).__init__() self.root = localDir #根 self.localDir = localDir #当前相对路径 self.tempDir = self.localDir #临时工作路径 return def console(cmd): #解析命令 if cmd[:3] == 'cd ': tempFunction = self.moveDir name = cmd[3:] elif cmd[:6] == 'mkdir ': tempFunction = self.mkdir name = cmd[6:] elif cmd[:6] == 'touch ': tempFunction = self.touch name = cmd[6:] elif cmd == 'ls': self.ls() return elif cmd[:3] == 'rm ': tempFunction = self.rm name = cmd[3:] else: return #初始化工作路径 if name == '': return self.tempDir = self.localDir pathList = name.split('/') if pathList[0] == '': self.tempDir = self.root pathList.pop(0) if pathList[0] == '' and len(pathList) == 1: #处理根目录情况下会判定路径非法的bug pathList.pop(0) elif pathList[0] == '.': pathList.pop(0) elif pathList[0] == '..' if self.tempDir.parent is not None: self.tempDir = self.tempDir.parent: pathList.pop(0) else: print('Error: not found.') return #判定语法 for path in pathList: if path == '' or path == '.' or path == '..': print('Error: invalid name.') return else: tempFunction(pathList) return def ls(): for child in self.tempDir: if child.isFolder: print('/', end = '') print(child.name) return def _cd(path): for child in self.tempDir.childList: if child.name == path: if child.isFolder: self.tempDir = child return 0 #正常 else: return -2 #存在同名文件 else: return -1 #不存在路径 def cd(pathList): rtvl = 0 #移动临时工作路径 while pathList: rtvl = self._cd(pathList[0]) if rtvl == 0: pathList.pop(0) elif rtvl == -1: print('Error: not found.') return elif rtvl == -2: print('Error: not found.') return else: print('Error: unknown.') return #移动成功,改变环境 self.localDir = self.tempDir return def _mkdir(path): newFolder = folderNode(path, self.tempDir) self.tempDir = newFolder return def mkdir(pathList): rtvl = 0 #移动临时工作路径 while pathList: rtvl = self._cd(pathList[0]) if rtvl == 0: pathList.pop(0) elif rtvl == -1: break elif rtvl == -2: print('Error: not found.') return else: print('Error: unknown.') return #开始新建文件夹 for path in pathList: self._mkdir(path) return def _touch(name): for child in self.tempDir.childList: if child.name == path: if child.isFolder: return -2 #存在同名文件夹 else: return -1 #存在同名文件 else: newFile = fileNode(name, self.tempDir) return 0 def touch(pathList): if len(pathList) == 0: print('Error: invalid name.') return name = pathList.pop(-1) #移动临时工作路径 while pathList: rtvl = self._cd(pathList[0]) if rtvl == 0: pathList.pop(0) elif rtvl == -1: break elif rtvl == -2: print('Error: not found.') return else: print('Error: unknown.') return #开始新建文件夹 for path in pathList: self._mkdir(path) #新建文件 rtvl = self._touch(name) if rtvl == -2: print('Error: invalid name.') elif rtvl == -1: pass elif rtvl == 0: pass else: print('Error: unknown.') self._touch(name) return def rm(pathList): #移动临时工作路径,检查路径正确性 rtvl = 0 while pathList: rtvl = self._cd(pathList[0]) if rtvl == 0: pathList.pop(0) elif rtvl == -1: print('Error: not found.') return elif rtvl == -2: break else: print('Error: unknown.') return #检测路径完整性 if rtvl == -2: if len(pathList) != 0: print('Error: not found.') return self.tempDir.remove() return 我说实话我没测试,可能会有手滑的地方(逃 另外我假设不会出什么因为IO的问题导致合法的命令中途爆掉的情况,对于新建文件或者文件夹倒是好说,我在开始新建的地方记录一下,爆掉了就删回去就完了。不过如果是删除,我大概是填不回去了(笑) 2020-4-10 04:47:54 修了个根目录路径非法的bug 2020-4-10 04:51:20 处理了一些边界情况会越界的情况 2020-4-10 04:54:38 修了个全都判断好了就是忘了新建文件的智障错误…… 四月 10, 2020,由yhz012修改 注释 Mr.K 018 20.00节操 这么大的模拟,辛苦啦~ 2 链接到点评
fubuki.ss 发布于四月 10, 2020 分享 发布于四月 10, 2020 · 只看该作者 雾槽、这题是要实现一个B+树的节奏? 大学时倒是有写过 ls…现在要写估计只能py凑合了…不过仔细看了一下题目要求好像挺简单的、随便写写试试( sstm oj指日可待( 链接到点评
随性而为 发布于四月 11, 2020 分享 发布于四月 11, 2020 (已修改) · 只看该作者 #include <stdio.h> #include <stdlib.h> #include <string.h> typedef struct tree { int flag; /*1代表目录(文件夹)。2代表文件*/ char name[20]; struct tree *parent; struct tree *child; struct tree *brother; }tree,*list; int checkdir(char dir[]) /*先进行初次判断(绝对路径,相对路径,格式等等,当然还不太完善)*/ { int n=1; if(dir[strlen(dir)-1]=='/'&&strlen(dir)-1!=0)/* '/'能通过而'/new/'不能 */ n=0; if(dir[0]=='/'&&(strstr(dir,"../")!=NULL||strstr(dir,"./")!=NULL))/* 绝对路径下任何地方都不能有'./''../' */ n=0; if(dir[0]!='/'&&((strstr(dir,"../")-dir!=0&&strstr(&dir[3],"../")!=NULL)||(strstr(dir,"./")-dir!=0&&strstr(&dir[2],"./")!=NULL)))/* 相对路径除刚开始不能有'./''../' */ n=0; if(n==0) { printf("error:invalid name,such as '/../new','/new/'"); return 0; } return 1; } /* 下面的exist函数几乎是任何一个操作都要做的,用来看路径中的文件是否存在,如果存在则一步步获取当前文件夹,不存在则看 makeornot,为0时对ls和rm有效 ,提示错误终止命令,为1时代表新建目录,为2时代表新建文件,新建文件(目录)统一用make执行*/ int exist(int makeornot,char dir[],list *now,tree* root) { int i,j=0,a[20],flag=0; tree* cache; tree* temp; if(dir[0]='/')/*绝对路径的情况*/ { cache=root->child; *now=root; for(i=1;dir[i]!='\0';i++) { if(dir[i]!='/') a[j++]=dir[i]; if(dir[i]=='/') { a[j]='\0'; for(;cache;cache=cache->brother) if(strcmp(a,cache->name)==0) { *now=cache; cache=cache->child; flag=1; break; } if(flag==0&&(*now)->flag==2) printf("error:file can't be created");/*判断路径中的每一层,文件是不能存放目录和文件的*/ if(flag==0&&(*now)->flag==1) { if(makeornot==0) { printf("error:not found"); return 0; } else { make(1,dir,now,temp,root,a); cache=NULL; } } flag=0; j=0; } } a[j]='\0'; for(;cache;cache=cache->brother) if(strcmp(a,cache->name)==0) { (*now)=cache; cache=cache->child; //j=0; flag=1; break; } if(flag==0) { if(makeornot==0) { printf("error:not found"); return 0; } else { make(makeornot,dir,now,temp,root,a);/*倒数第一层文论是文件还是目录都可以新建*/ } } return 1; } else/*相对路径的情况*/ { cache=(*now)->child; //*now=(*now); for(i=0;dir[i]!='\0';i++) { if(dir[i]!='/') a[j++]=dir[i]; if(dir[i]=='/') { a[j]='\0'; for(;cache;cache=cache->brother) { if(strcmp(a,"..")==0) { cache=(*now); *now=(*now)->parent; } if(strcmp(a,cache->name)==0) { (*now)=cache; cache=cache->child; flag=1; break; } } if(flag==0&&(*now)->flag==2) printf("error:file can't be created"); if(flag==0&&(*now)->flag==1) { if(makeornot==0) { printf("error:not found"); return 0; } else { make(1,dir,now,temp,root,a); cache=NULL; } } flag=0; j=0; } } a[j]='\0'; for(;cache;cache=cache->brother) if(strcmp(a,cache->name)==0) { (*now)=cache; cache=cache->child; flag=1; break; } if(flag==0) { if(makeornot==0) { printf("error:not found"); return 0; } else { make(makeornot,dir,now,temp,root,a); } } return 1; } } int rmorls(char dir[],tree* now,tree* root,int option)/* 递归操作,option为1时ls,为2时rm */ { if(now==NULL) return; rmorls(dir,now->brother,root,option); rmorls(dir,now->child,root,option); if(option==1) printf("%s/t",now->name); if(option==2) free(now); } int make(int option,char dir[],list *now,tree* temp,tree* root,char a[]) { /*现有文件和已存文件的连接*/ tree *newnode,*p1,*p2; newnode=(tree*)malloc(sizeof(tree)); newnode->brother=NULL; newnode->child=NULL; newnode->parent=(*now); newnode->flag=option; strcpy(newnode->name,a); /*判断新建文件(目录)是否是父目录第一个孩子*/ if((*now)->child==NULL) { (*now)->child=newnode; }else { for(p1=(*now)->child;p1->brother;p1=p1->brother); p1->brother=newnode; } (*now)=temp=newnode; } int cd(char dir[],list *now,tree* root)/*转到路径指定目录,事实上大部分工作被exist函数做了*/ { tree *temp; temp=*now; if(exist(0,dir,now,root)==0) /*如果路径不存在,则当前目录回到没有输入命令前的工作目录*/ *now=temp; /*没有输出*/ } int ls(char dir[],list *now,tree* root)/*因为ls与rm都是对路径递归,只是每次的操作不同,故将其递归部分结合成一个函数lsorrm()*/ { tree *temp; temp=*now; if(exist(0,dir,now,root)==0) { *now=temp; }else { printf("%s:",(*now)->name); rmorls(dir,(*now)->child,root,1); } } int rm(char dir[],list *now,tree* root)/*删除后停留在当前目录*/ { tree *temp,*a,*p1,*p2; temp=*now; if(exist(0,dir,now,root)==0) { *now=temp; }else { rmorls(dir,(*now)->child,root,2); a=(*now)->parent; p1=a->child; if(p1==*now) { p1->parent->child=p1->brother; } else { for(;p2;p2=p1,p1=p1->brother) { if(p2==*now) p1->brother=p2->brother; } } free(*now); *now=a->child; /*因为是删除,连接方式一定会改变,以上步骤就是改变过程*/ } } int main()/*没什么解释的,就是将输入转化为参数,调用对应的函数*/ { tree *root,*now,*temp; root=(tree*)malloc(sizeof(tree)); root->parent=root->child=root->brother=NULL; now=temp=root; int choose; char ope[10]; char dir[100]; while(1) { scanf("%s %s",ope,dir); if(!strcmp(ope,"mkdir")) choose=1; else if(!strcmp(ope,"touch")) choose=2; else if(!strcmp(ope,"cd")) choose=3; else if(!strcmp(ope,"ls")) choose=4; else if(!strcmp(ope,"rm")) choose=5; if(checkdir(dir)==1) { switch(choose) { case 1:exist(1,dir,&now,root);break; case 2:exist(2,dir,&now,root);break; case 3:cd(dir,&now,root);break; case 4:ls(dir,&now,root);break; case 5:rm(dir,&now,root);break; }; } } } 码了一天多终于套完了所有的娃,还没有测试,怕没有达到预期的结果而心跳骤停,再者我软件也缺失debug,要发现问题也是工程量巨大,既然不是正规的,就权当伪代码吧(虽然程序本身并没有语法错误),不过大致框架和思路就是这样,要有一些小问题也不用调整太多,讲真这是我至今为止写过的最长的代码了,也多亏了这道题,我对地址有了更深一步的了解,解决了从上学期以来的一些困惑 ps:这真的是给大一学生做的么,太魔鬼了 修正了些小错误 四月 11, 2020,由随性而为修改 注释 NianRuoshui 20.00节操 恰糖 yhz012 10.00节操 是C党,辛苦了 Mr.K 018 25.00节操 糖~ 链接到点评
推荐贴