#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:这真的是给大一学生做的么,太魔鬼了
修正了些小错误