目录
一、答案
1.mysh.c
#include<unistd.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void main()
{
int size = 20;
int pid;
char pos[size];
char command[size];
while(1)
{
getcwd(pos,size);
printf("%s$\n",pos);
scanf("%s",command);
if(!strcmp(command,"cd"))
{
char path[size];
scanf("%s",path);
chdir(path);
}
else if(!strcmp(command,"sync"))
{
sync();
}
else if(!strcmp(command,"exit"))
{
exit(0);
}
else if(!strcmp(command,"ls"))
{
char ls_command[size];
strcpy(ls_command,"ls ");
strcat(ls_command,pos);
// sprinf(ls_command,"ls %s", pos);
system("ls");
}
else if(!strcmp(command,"cat"))
{
char filename[size];
char cat_command[size];
scanf("%s",filename);
strcpy(cat_command,"cat ");
if(filename[0] != '/')
{
strcat(cat_command,pos);
strcat(cat_command,"/");
}
strcat(cat_command,filename);
// sprintf(cat_command,"cat %s/%s",pos, filename);
system(cat_command);
}
}
}
2.mysh.c注释版
/*注:在Bochs虚拟机中不用添加头文件*/
#include<unistd.h>/*getcwd、chdir、sync等系统调用*/
#include<stdio.h>/*scanf、printf等函数*/
#include<stdlib.h>/*system函数*/
#include<string.h>/*str开头的函数*/
void main()
{
int size = 20;
int pid;/*未使用*/
char pos[size];
char command[size];
while(1)
{
/*getcwd:将当前的(mysh中的)路径的值赋给第一个参数*/
getcwd(pos,size);
printf("%s$\n",pos);
scanf("%s",command);
/*strcmp:两个参数匹配则返回值为0*/
if(!strcmp(command,"cd"))
{
char path[size];
scanf("%s",path);
/*chdir:将mysh中的目录切换为path,其中..对应上一级目录*/
chdir(path);
}
else if(!strcmp(command,"sync"))
{
sync();
}
else if(!strcmp(command,"exit"))
{
exit(0);
}
else if(!strcmp(command,"ls"))
{
char ls_command[size];
strcpy(ls_command,"ls ");
strcat(ls_command,pos);
// sprinf(ls_command,"ls %s", pos);
system("ls");
}
else if(!strcmp(command,"cat"))
{
char filename[size];
char cat_command[size];
scanf("%s",filename);
strcpy(cat_command,"cat ");
if(filename[0] != '/')
{
/*strcat:将第二个参数加到第一个参数的末尾,并将返回值赋给第一个参数*/
strcat(cat_command,pos);
strcat(cat_command,"/");
}
strcat(cat_command,filename);
// sprintf(cat_command,"cat %s/%s",pos, filename);
system(cat_command);
}
}
}
二、实验过程中遇到的问题
1.没有按照实验准备中给的命令解释器程序的一般结构
来组织本文命令解释器的结构
主要是因为自己没有想明白创建子进程和父进程等待子进程结束这两个过程的意义。
2.未使用execvp
和execve
这两个函数
在使用上述两个函数的时候出现了未知原因的段segament fault
,这里本文并没有做深入探究,猜想应该和进程调度相关内容有关(本文没有使用的fork
),而是改为经常使用的stdlib.h
库中的system
函数。
3.sprintf函数
在bochs虚拟机中可以正常调用sprintf函数,在评测的时候则不可以,于是改用了strcpy和strcat这两个函数来实现相关功能。
4.exit函数
bochs虚拟机中可以直接使用exit(),而评测的时候必须给exit加上参数。
5.变量声明
变量声明必须放在每一个代码结构的最起始位置,比如if语句中,如果在scanf语句后声明一个变量,bochs虚拟机中gcc编译时将会报错。
6.为一个字符串赋值
用=
为字符串赋值的方法是错误的,尽量使用string.h中的函数
7.scanf函数
写代码的时候一直觉得scanf
的写法为scanf("%s", &str)
,但是在评测时这样的写法报错,不能够加&
符号。加&
的时scanf
中的%d
等格式化字符串。
8.mysh执行时的显示的目录与系统所在目录不同步
这个问题导致了在mysh
使用cd
命令切换了当前所在目录后,使用system
函数直接调用ls
命令会出现现实的内容与当前mysh
目录不一致,这就需要mysh
中的ls
调用system
函数时,需要ls
的参数为当前mysh
显示的路径。cat
同理,但是cat
的参数为相对路径和绝对路径时,所进行的操作是不一样的。
本文代码实现的ls
命令是不完善的,当前实现的功能仅为查看当前目录的内容,未考虑ls
命令之后有参数的情况。
9.ls
显示的内容没有myls
、mycat
等文件
主要是觉得没有必要。
三、educoder的上传文件的功能
可以上传代码到实验环境