函数内的具体代码就不展开了,对代码讲解无帮助。可以看到,ShellFunSet其实是一个函数的集合,里面的函数都有一个共同特点:
1.返回值类型为bool
2.参数类型为string数组(根据C/C++语言特性,其实更应该说是string型指针)。
只有持有按这种规范编写的函数的类才能作为CmdNode<T>以及CmdControl<T>的T类。至于函数为什么必须返回bool值,等下会说的,别急~
接下来说下CmdNode,从第二行代码后的注释可以看出,这个结构体只有两个数据成员,一个是string,代表这个shell内置的命令。另一个则是函数指针型数据,指向返回值为bool,参数为string数组的函数,我将其typedef为pFun。因此在上面代码中,初始化CmdNode数组shellCmds[9]时用到了类似这样的代码 {"pwd",&ShellFunSet::pwd},那个取址算符&取的其实就是ShellFunSet中某个函数的地址,将此地址作为函数指针赋值给CmdNode中的pFun型数据成员。通过这种方式编写代码能够实现如下功能:当用户敲入的命令匹配了某一CmdNode实例的string型数据成员时,程序能通过某种机制调用与该string成员相关联的T类中的函数,执行该命令对应的具体功能。例如{"pwd",&ShellFunSet::pwd}中,当用户敲入"pwd"时,shell程序就会调用ShellFunSet中的bool pwd(string order[])函数,在这个简易shell程序中pwd命令的功能是显示当前工作路径。
附上CmdNode的代码:
template <class T>
struct CmdNode{
typedef bool (T::*pFun)(string *);
string command;
pFun fun;
};
关于这个某种机制(我特意在上面把它高亮了出来,呵呵~)其实就是CmdControl<T>,如果说在这个简易Shell程序中,CmdNode<T>数组shellCmds是它的数据结构,那么这个CmdControl<T>就是这个程序的算法。恩,我知道这种说法很扯,此程序压根不涉及啥稍微有内涵的数据结构与算法,但这只是个比喻。
CmdControl<T>的功能是:获取用户输入的命令及参数并进行匹配,然后执行相应功能,或者在用户输入错误命令时进行报错(注意,只是对错误的命令进行报错,参数错了的话CmdControl<T>是不会去管的),控制命令行模块的启停。
CmdControl<T>的初始化方式如下:
CmdControl<ShellFunSet> cmdModul("YeShizhe@",9,osFunHolder,shellCmds);
参数"YeShizhe@"是自定义的命令行提示符。整型常量9代表这个简易shell内置的命令条数,shellCmds是CmdNode<ShellFunSet>的数组,它包含9个CmdNode<ShellFunSet>型元素。osFunHolder是ShellFunSet类实例。这里请允许我再次强调下:CmdControl与CmdNode属于可复用的代码,而ShellFunSet则是我根据这次操作系统课程设计要求而写的实现简易shell的具体功能代码。
然后,用这样的代码启动这个命令行控制模块cmdModul:
cmdModul.run();
至于怎么停止,这个就要靠ShellFunSet中函数的返回值:bool
当用户输入的命令对应了一个函数,这个函数的返回值是false,一旦cmdModul调用到了该函数就会停止对用户输入的接收,退出命令行控制模式。例如在课程设计中我为"exit"命令写了这么个函数bool exit(string order[]){ return false;},简单得坑爹,但就是它实现了用户输入"exit"时退出shell的这么一个功能。
CmdControl<T>的代码如下:
template <class T>
class CmdControl {
protected:
T holder;//客户程序员根据需要编写的功能类
string prompt;//命令提示符
string cmdNotExist;//自定义的错误命令提示信息
int cmds;//内置命令数
bool running;//用于判断模块处于运行状态
CmdNode<T> *cmdList;//内置命令列表
string* getOrder();//返回字符串数组,存储用户输入的命令及参数
int match(string order);//返回匹配用户输入的命令在cmdList中的下标
public:
void run();
//接收参数:命令条数、命令持有类、命令与函数的关联数组
CmdControl(string prmpt,int num,T Holder,CmdNode<T> *CMD);
};