C语⾔⾯向对象式编程之命令解析器
1 命令解析器
将⽤户输⼊的命令解析到对应的动作的系统,另⼀种说法是状态机。根据上的定义
有限状态机(finite-state machine, FSM,简称状态机)是表⽰有限个状态以及在这些状态之间的转移和动作等⾏为的数学模型
本⽂重点是实现C语⾔⾯向对象式的写法,并尝试对⽐分析这种写法和传统的⾯向过程式的编程有哪些个区别。
2 作⽤
根据我的理解,命令解析器实现⽤户通过命令码与系统进⾏交互,进⽽调⽤函数改变系统的当前状态,与传统的顺序式程序处理相⽐,这种交互式的处理更加灵活。
3 同类框架
<1>⾯向过程,使⽤switch-case实现命令解析器,通过外部声明调⽤模块内函数
<2>⾯向对象,使⽤C语⾔结构体绑定命令码和处理函数,通过函数指针访问模块内函数
对⽐
两种写法在功能实现上都没有⽑病,但是对⽐上边两种写法,有分析得出
⾯向过程式(⽅法⼀)⾯向对象式(⽅法⼆)
命令增加引起跨模块修改(分别在函数实现和调⽤的位置修改)命令增加只要在模块内部进⾏实现和注册即可
⼤量的外部函数,模块间⾼耦合解耦合,模块之间基本独⽴,通过函数指针访问静态的内部函数
除了上述好处,⾯向对象的实现中还讲命令相关的(命令码和对应的处理函数)封装到⼀个结构体中,实现了两者的绑定,⽽不⽤我们在程序中再考虑这层关系。
4 ⾯向对象写法实现
数据类型
<1>命令结构体类型,⽤于绑定命令码和处理函数
typedef struct cmd
{
char cmd_name[MAX_CMD_NAME_LENGTH + 1]; //命令码
handler cmd_operate; //命令操作的⽅法
} CMD;
<2>命令列表,⽤线性表来实现,⽤于存放命令的机制
typedef struct cmds
{
CMD cmds[MAX_CMDS_COUNT]; //cmd对象数组
int num; //当前命令个数标记
} CMDS;
相关操作
<1>批量注册命令
/******************************************************************************
* 函数介绍:命令注册函数
* 输⼊参数:reg_cmds 要注册的命令数组, num命令数量
* 输出参数:⽆
* 返回值:⽆
* 备注:num <= MAX_CMDS_COUNT
******************************************************************************/
void register_cmds(CMD reg_cmds[], int num)
{
int i;
if (num > MAX_CMDS_COUNT)
{
return;
}
for (i = 0;i < num;i++)
{
if (commands.num < MAX_CMDS_COUNT) //命令列表未满
{
ds[i].cmd_name, reg_cmds[i].cmd_name); //注册命令码 ds[i].cmd_operate = reg_cmds[i].cmd_operate; //注册命令处理
++commands.num; //命令个数+1
}
}
}
<2>匹配命令码,并执⾏对应函数
/******************************************************************************
* 函数介绍:命令码匹配执⾏函数
* 输⼊参数:str 待匹配的命令码
* 输出参数:⽆
* 返回值:⽆
* 备注:str长度不能⼤于MAX_CMD_NAME_LENGTH
******************************************************************************/
void match_cmd(const char *str)
{
int i;
if (strlen(str) > MAX_CMD_NAME_LENGTH)
{
return;
}
for (i = 0;i < commands.num;++i)
{
if (ds[i].cmd_name, str) == 0)
{
}
}
}
5 ⾯向对象写法改进(使⽤链表来存放命令)
好处是链表可以动态的增加节点,不⽤考虑命令数量上限问题。
数据类型
<1>命令结构体,⽤于绑定命令码和处理函数
typedef struct cmd
{
char cmd_name[MAX_CMD_NAME_LENGTH + 1]; //命令码
handler cmd_operate; //命令操作的⽅法
} CMD;
<2>命令列表,链表实现,⽤于存放命令的机制
typedef struct node
{
CMD m_cmd; //cmd对象数组
struct node* m_next; //下⼀个节点
} CMD_ListNode;
相关操作
<1>批量注册命令
/******************************************************************************
* 函数介绍:命令注册函数
* 输⼊参数:reg_cmds 要注册的命令数组, num命令数量
* 输出参数:⽆
* 返回值:true 成功, false 失败
* 备注:num <= MAX_CMDS_COUNT
******************************************************************************/
bool register_cmds(CMD reg_cmds[], int num)
{
int i;
if (NULL == cmd_pHead)
{
return false;
}
for (i = 0;i < num;i++)
{
list_head_insert(reg_cmds[i]); //将命令码和⽅法作为节点信息插⼊链表 }
return true;
}
<2>匹配命令码,并执⾏对应函数
/****************************************************************************** * 函数介绍:命令码匹配执⾏函数
c语言listinsert函数* 输⼊参数:str 待匹配的命令码
* 输出参数:⽆
* 返回值:true 成功, false 失败
* 备注:str长度不能⼤于MAX_CMD_NAME_LENGTH
******************************************************************************/ bool match_cmd(const char *str)
{
CMD_ListNode* H = cmd_pHead;
if ((NULL == str) || (NULL == cmd_pHead))
{
return false;
}
if (strlen(str) > MAX_CMD_NAME_LENGTH)
{
return false;
}
//链表不空
while(H)
{
if (strcmp(H->d_name, str) == 0)
{
H->d_operate(); //执⾏⽅法
}
H = H->m_next;
}
return true;
}
5 运⾏结果
6 参考源
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论