实际项目中经常遇到很多类似操作,比如命令码对应执行函数等,对于此类操作,比较好的方式是使用const数组,将命令码和操作函数绑定在一起,通过查表方式找到操作函数,并执行操作函数。这样可以简化代码,降低复杂度,在c中这种方式很好实现,在c++中会稍微麻烦一些。
以串口命令解析执行为例,首先定义一个结构体,定义操作函数的指针类型:
struct T_ShellInfo
{
string cmd;
void (* DealFunc)(const vector<string> &vectStr);
string desc;
};
定义命令解析执行类,处理函数一定要定义成static,定义一个const static的数组:
class CShell
{
public:
CShell();
~CShell();
void RecvCmd();
private:
enum{SHELL_INFO_NUM_MAX=10};
void GetCmd(const char *cmdStr, vector<string> &vectStr);
void Deal(const vector<string> &vectStr);
static void CmdHelp(const vector<string> &vectStr);
static void CmdLed(const vector<string> &vectStr);
static void CmdTask(const vector<string> &vectStr);
static void CmdDisk(const vector<string> &vectStr);
static void CmdTime(const vector<string> &vectStr);
static void CmdReboot(const vector<string> &vectStr);
CShell *_self;
const static T_ShellInfo _shellInfo[SHELL_INFO_NUM_MAX];
};
实现时,先初始化数组
const T_ShellInfo CShell::_shellInfo[SHELL_INFO_NUM_MAX]=
{
{"?", CmdHelp, "show all cmd"},
{"help", CmdHelp, "show all cmd"},
{"time", CmdTime, "show sys time"},
{"task", CmdTask, "show all task info"},
{"disk", CmdDisk, "disk cmd [info ls cat rm format]"},
{"led", CmdLed, "set led [normal charge alarm]"},
{"reboot", CmdReboot, "reboot sys"},
{"",NULL,""}
};
串口收到命令后,只要遍历此数组,找到相同命令码的执行函数并执行即可
void CShell::Deal(const vector<string> &vectStr)
{
for (u8 i = 0; i< SHELL_INFO_NUM_MAX; i++)
{
if (_shellInfo[i].cmd.length() == 0)
{
break;
}
if (_shellInfo[i].cmd == vectStr[0])
{
_shellInfo[i].DealFunc(vectStr);
return;
}
}
printf("cmd \"%s\" err!\r\n", vectStr[0].c_str());
}
然后逐个实现对应操作函数:
void CShell::CmdTask(const vector<string> &vectStr)
{
u8 pcWriteBuffer[500]={0};
//u8 *pcWriteBuffer = new u8[500]; //这个值要小心,太小会导致数组溢出,太大会导致堆栈溢出
printf("=================================================\r\n");
printf("任务名 任务状态 优先级 剩余栈 任务序号\r\n");
vTaskList((char *)&pcWriteBuffer);
printf("%s\r\n", pcWriteBuffer);
//delete[] pcWriteBuffer;