實際項目中經常遇到很多類似操作,比如命令碼對應執行函數等,對於此類操作,比較好的方式是使用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; }