nunnifsmgen-有限状态机程序代码自动生成器

nunnifsmgen-有限状态机程序代码自动生成器

这个是从同事那边知道的好东西, Nunni FSM Generator,它能自动根据你输入的配置文件产生状态机的程序代码,详细的数据请查阅软件的使用说明,但我要讲的重点在于它"自动产生的程序代码部份",因为自动产生的code封装得十分漂亮,所以我想对code做点介绍

以前写状态机的东西,不脱离if,else,case,switch…等这几种语法搭配,可是写出来的code"不 大容易读懂",比如说我今天有个状态机如下图,假设有一张桌子,上面只能摆一个瓶子,我如果拿走了这个瓶子,那我就不能从桌子上再拿走瓶子了,如果桌子上 已经摆了一个瓶子,那桌子上就再也不能多加瓶子上去

如果用if-else语法写写看,可能会像下面这样

  1. #include
  2. int bottles=1;
  3. void GetBottleAPI()
  4. {
  5. if (bottles==1)
  6. {
  7. printf("You got bottle/n");
  8. bottles--;
  9. }
  10. else printf("No bootle to get/n");
  11. }
  12. void PutBottleAPI()
  13. {
  14. if (bottles==0)
  15. {
  16. printf("You put a bottle/n");
  17. bottles++;
  18. }
  19. else printf("Too much bootles/n");
  20. }
  21. int main()
  22. {
  23. GetBottleAPI();
  24. GetBottleAPI();
  25. PutBottleAPI();
  26. PutBottleAPI();
  27. GetBottleAPI();
  28. }

用int bottles当global变量判断get or put的动作是否合法,这种写法如果用在小型的状态机还OK,如果状态机又多又大又复杂,可以想见程序代码会为这些状态多写好几个判断变量

试试看下面的程序代码,我只要定义好每个状态与外来动作的触发机制,就可以写出蛮漂亮的code

  1. #include
  2. struct TableState ;
  3. struct TableFSM
  4. {
  5. int (*GetBottleStatus)( struct TableFSM *fsm, void * o );
  6. int (*PutBottleStatus)( struct TableFSM *fsm, void * o );
  7. void (*changeState)( struct TableFSM *fsm, struct TableState *nextState );
  8. struct TableState *m_state;
  9. };
  10. struct TableState
  11. {
  12. int (*GetBottleStatus)( struct TableFSM *fsm, void * o );
  13. int (*PutBottleStatus)( struct TableFSM *fsm, void * o );
  14. };
  15. static struct TableState TableFull;
  16. static struct TableState TableEmpty;
  17. void GetBottle()
  18. {
  19. printf("You get a bottle/n");
  20. }
  21. void GiveBottle()
  22. {
  23. printf("You put bottle on the table/n");
  24. }
  25. void NoBottle()
  26. {
  27. printf("There is no bottle on the table/n");
  28. }
  29. void BottleFull()
  30. {
  31. printf("There is too much bottle on the table/n");
  32. }
  33. int FSMGetBottleStat( struct TableFSM *fsm, void * o )
  34. {
  35. return fsm->m_state->GetBottleStatus( fsm, o );
  36. }
  37. int FSMPutBottleStat( struct TableFSM *fsm, void * o )
  38. {
  39. return fsm->m_state->PutBottleStatus( fsm, o );
  40. }
  41. void FSMChangeState( struct TableFSM *fsm, struct BottleState *newState )
  42. {
  43. fsm->m_state = newState;
  44. }
  45. int GetBottleAPI( struct TableFSM *fsm, void * o )
  46. {
  47. GetBottle();
  48. fsm->changeState( fsm, &TableEmpty);
  49. }
  50. int GiveBottleAPI(struct TableFSM *fsm, void * o )
  51. {
  52. GiveBottle();
  53. fsm->changeState( fsm, &TableFull );
  54. }
  55. int TooFewBottleAPI(struct TableFSM *fsm, void * o )
  56. {
  57. NoBottle();
  58. fsm->changeState( fsm, &TableEmpty );
  59. }
  60. int TooMuchBottleAPI(struct TableFSM *fsm, void * o )
  61. {
  62. BottleFull();
  63. fsm->changeState( fsm, &TableFull );
  64. }
  65. int main()
  66. {
  67. static struct TableFSM bf;
  68. TableFull.GetBottleStatus = GetBottleAPI;
  69. TableFull.PutBottleStatus = TooMuchBottleAPI;
  70. TableEmpty.GetBottleStatus = TooFewBottleAPI;
  71. TableEmpty.PutBottleStatus = GiveBottleAPI;
  72. bf.GetBottleStatus=FSMGetBottleStat;
  73. bf.PutBottleStatus=FSMPutBottleStat;
  74. bf.changeState=FSMChangeState;
  75. bf.m_state=&TableFull;
  76. FSMGetBottleStat(&bf,0);
  77. FSMGetBottleStat(&bf,0);
  78. FSMPutBottleStat(&bf,0);
  79. FSMPutBottleStat(&bf,0);
  80. }

上面的程序代码相当简洁,当外部动作触发内部状态改变,会把FSM指定的函式指定到转入后的state callback,所以programmer可以完全专注在GetBottleAPI之类的函式实作,而不用考虑state转换的程序复杂度

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值