找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1020|回复: 25
打印 上一主题 下一主题
收起左侧

C语言判断某个值状态过多时,如何优化

  [复制链接]
回帖奖励 10 黑币 回复本帖可获得 10 黑币奖励! 每人限 2 次
跳转到指定楼层
楼主
假定有一个16位变量,代表不同状态,状态有几千种,且某些功能的状态值是不连续的。
开始使用swtch case写,发现case太多了,放弃。
又改成if else判断,这样可以把某些连续的状态使用一个判断完成,但是写下来还是有几十个if else.
还能在优化吗?
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏1 分享淘帖 顶 踩
回复

使用道具 举报

来自 2#
ID:777254 发表于 2024-8-1 19:41 | 只看该作者
目前的解析一个协议,一开始用witch,分支有数据读写之类的几个大case;然后读功能里面需要读的协议太多了,我看了协议文档,几千条。所以读分支里面不能再用switch了,不然又有几千个分支。目前是在读分支里面使用if else写着。因为查表法需要数组,RAM也要花费好多,所以暂时不用数组建立表了。还有好方法吗?尽量不占用/少用RAM空间
回复

使用道具 举报

板凳
ID:1109793 发表于 2024-8-1 10:21 | 只看该作者
几千种,那可是复杂了,这么复杂的系统,厉害了。要不先分开,比如>10<20,每10个分一组?
回复

使用道具 举报

地板
ID:277550 发表于 2024-8-1 11:15 | 只看该作者
几十个,不算多了。想优化,在if之前优化。
回复

使用道具 举报

5#
ID:69038 发表于 2024-8-1 11:18 | 只看该作者
"假定有一个16位变量,代表不同状态,状态有几千种,且某些功能的状态值是不连续的。"
如果真有几千种的状态,只能说这个系统架构有问题了。才疏学浅想不出这么多复杂的状态,只用一个16位变量来表示。。

建议参考LCM1602、LCM12864的指令集做个散转表,或许能实现。它是一个8bit的寄存器,从bit7开始,共8个标志,除开标志位,余下的bit是参数值(如果有的话)。。



回复

使用道具 举报

6#
ID:276663 发表于 2024-8-1 12:41 | 只看该作者
跟楼上意思类似,借鉴IPV4,使用掩码分级判断,归类处理
回复

使用道具 举报

7#
ID:744809 发表于 2024-8-1 15:14 | 只看该作者
写一个映射表,从值映射到状态,然后用switch
回复

使用道具 举报

8#
ID:220661 发表于 2024-8-1 15:44 | 只看该作者
数组吧,节省空间,提升速度。
回复

使用道具 举报

9#
ID:1087128 发表于 2024-8-1 16:16 | 只看该作者
if先判断一个范围
回复

使用道具 举报

10#
ID:451718 发表于 2024-8-1 17:35 | 只看该作者
从数据结构的角度出发,你在一个分支下面查询上千个塞选,本身就是不科学的。最好的优化方法,就是不断的细分,采用多级查询。
回复

使用道具 举报

11#
ID:624769 发表于 2024-8-1 18:43 | 只看该作者
c语言如何实现 不太清楚, 汇编的话,可以根据变量值  直接跳转若干行(比如: JMP  @A+PC),然后在  相应的位置写下分支就可以了。
回复

使用道具 举报

12#
ID:777254 发表于 2024-8-1 19:33 | 只看该作者
xiaobendan001 发表于 2024-8-1 10:21
几千种,那可是复杂了,这么复杂的系统,厉害了。要不先分开,比如>10

协议功能码太多了,不同功能发送不同数据,越写case越多,不好搞
回复

使用道具 举报

13#
ID:777254 发表于 2024-8-1 19:35 | 只看该作者
gongnn 发表于 2024-8-1 15:44
数组吧,节省空间,提升速度。

不行啊,一个数组包含的状态也很多,导致RAM不够。
回复

使用道具 举报

14#
ID:777254 发表于 2024-8-1 19:41 | 只看该作者
zhuls 发表于 2024-8-1 11:18
"假定有一个16位变量,代表不同状态,状态有几千种,且某些功能的状态值是不连续的。"
如果真有几千种的状 ...

好的,谢谢,我参考一下
回复

使用道具 举报

15#
ID:57657 发表于 2024-8-1 21:42 | 只看该作者
li1069136863 发表于 2024-8-1 19:35
不行啊,一个数组包含的状态也很多,导致RAM不够。

你要搞清楚 C语言是单片机还是操作系统运行的 写法不一样
回复

使用道具 举报

16#
ID:57657 发表于 2024-8-1 21:51 | 只看该作者
用二分查找,找到的取出索引 然后用该索引地址定位到函数指针数组执行相应的函数,找不到的执行default。
回复

使用道具 举报

17#
ID:401564 发表于 2024-8-2 13:07 | 只看该作者
不知道你这个是什么协议,几千个状态,那不得几千个函数来处理?在单片机领域,搞这种东西出来的,十有八九是新手
还不如果直接说,你要干嘛,说不定网还能帮到你
如果说从一开始,方向就是错的,那就太浪费时间了
回复

使用道具 举报

18#
ID:1129414 发表于 2024-8-2 17:00 | 只看该作者
你写的是啥,判断几千个状态,单片机估计够呛
回复

使用道具 举报

19#
ID:777254 发表于 2024-8-2 20:20 | 只看该作者
Y_G_G 发表于 2024-8-2 13:07
不知道你这个是什么协议,几千个状态,那不得几千个函数来处理?在单片机领域,搞这种东西出来的,十有八九是新 ...

电表的DLT645协议,里面的协议太多,需要读取的参数太多了,不知道怎么优化。
回复

使用道具 举报

20#
ID:777254 发表于 2024-8-2 20:28 | 只看该作者
li1069136863 发表于 2024-8-1 19:41
目前的解析一个协议,一开始用witch,分支有数据读写之类的几个大case;然后读功能里面需要读的协议太多了 ...

是DLT645-2007电表协议,有做过的大佬吗?
回复

使用道具 举报

21#
ID:57657 发表于 2024-8-2 22:24 | 只看该作者
状态表数组使用二分查找 可以不连续但必须从小到大排序,找到的返回索引,找不到的返回指定数字。
然后用索引访问指针表数组,取出函数指针并传递参数执行,最后取回返回值,如果参数还传递其他数据类型或数组可能涉及多级指针。
回复

使用道具 举报

22#
ID:982617 发表于 2024-8-7 16:04 | 只看该作者
面对大量状态处理的场景,确实单靠 `switch-case` 或 `if-else` 结构可能会显得冗长且难以维护。你可以考虑以下几种优化策略:

1. **枚举类型(Enum)**:将状态值定义为枚举类型,这样不仅代码更清晰,还可以利用编译器的静态检查避免状态值的误用。枚举类型能提供更好的可读性,并且可以更方便地添加或修改状态。

   ```c
   enum State {
       STATE_1, STATE_2, STATE_3, ... // 具体状态
   }
   ```

2. **状态机(State Machine)**:如果状态之间有明确的转换逻辑,可以设计一个状态机来管理状态的转换。状态机通过一系列状态转换函数或状态对象来实现,这样可以清晰地表示状态之间的依赖关系和转换条件。

   ```c
   void process_state(State current_state) {
       switch (current_state) {
           case STATE_1:
               // 处理STATE_1逻辑
               break;
           case STATE_2:
               // 处理STATE_2逻辑
               break;
           // ...
           default:
               // 处理未知状态
               break;
       }
   }
   ```

3. **宏定义**:对于某些频繁使用的逻辑,可以考虑使用宏来定义,简化代码并提高可读性。

   ```c
   #define PROCESS_STATE(state) do {\
       if (state == STATE_1) {\
           // 处理STATE_1逻辑\
       } else if (state == STATE_2) {\
           // 处理STATE_2逻辑\
       } else if (state == STATE_3) {\
           // 处理STATE_3逻辑\
       } // 更多状态\
   } while(0)
   ```

4. **使用函数指针或宏来封装状态逻辑**:如果每个状态的处理逻辑不同且较为复杂,可以考虑使用函数指针或宏来封装逻辑,这样可以使得每个状态的逻辑独立且易于维护。

   ```c
   typedef void (*StateHandler)(void);
   StateHandler state_handlers[] = {
       &process_state_1,
       &process_state_2,
       // 更多状态函数\
   };

   void process_state(State state) {
       state_handlers[state]();
   }
   ```

5. **使用类或结构体**:对于复杂的状态,可以考虑使用类或结构体来封装状态的属性和处理逻辑。这样可以更好地组织代码,提高可读性和可维护性。

   ```c
   struct State {
       void (*handle)(void);
   };

   void process_state(State state) {
       state.handle();
   }
   ```

6. **性能考虑**:在选择优化策略时,也需要考虑性能影响。宏和函数调用在某些情况下可能会带来额外的开销。在进行优化时,可以先进行性能测试,确保优化后代码的执行效率满足需求。

通过上述方法,你可以更有效地管理和处理大量状态,提高代码的可读性和可维护性。根据具体需求和场景,选择最适合的优化策略。
回复

使用道具 举报

23#
ID:688692 发表于 2024-8-8 14:05 | 只看该作者
li1069136863 发表于 2024-8-2 20:28
是DLT645-2007电表协议,有做过的大佬吗?

你是要实现协议还是做这个协议的上位机?我写过一个简单的上位机,不复杂。要实现这个协议,几十个if是合理范围。
回复

使用道具 举报

24#
ID:777254 发表于 2024-8-8 20:20 | 只看该作者
cnos 发表于 2024-8-8 14:05
你是要实现协议还是做这个协议的上位机?我写过一个简单的上位机,不复杂。要实现这个协议,几十个if是合 ...

我是接收上位机发来的DLT645协议,实现对应功能。太多参数要读写了,目前用if else,能把连续的协议简化,看起来没那么臃肿
回复

使用道具 举报

25#
ID:57657 发表于 2024-8-9 05:30 | 只看该作者
hezezeze 发表于 2024-8-7 16:04
面对大量状态处理的场景,确实单靠 `switch-case` 或 `if-else` 结构可能会显得冗长且难以维护。你可以考虑 ...

类是操作系统的运行环境才有的,单片机内存小几乎不可能。
回复

使用道具 举报

26#
ID:844772 发表于 2024-8-9 08:46 | 只看该作者
其实就是个简单的数据库搜索功能,但用单片机实现就很麻烦。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表