找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 2319|回復(fù): 25
收起左側(cè)

C語言判斷某個值狀態(tài)過多時,如何優(yōu)化

  [復(fù)制鏈接]
回帖獎勵 10 黑幣 回復(fù)本帖可獲得 10 黑幣獎勵! 每人限 2 次
ID:777254 發(fā)表于 2024-8-1 08:58 | 顯示全部樓層 |閱讀模式
假定有一個16位變量,代表不同狀態(tài),狀態(tài)有幾千種,且某些功能的狀態(tài)值是不連續(xù)的。
開始使用swtch case寫,發(fā)現(xiàn)case太多了,放棄。
又改成if else判斷,這樣可以把某些連續(xù)的狀態(tài)使用一個判斷完成,但是寫下來還是有幾十個if else.
還能在優(yōu)化嗎?
回復(fù)

使用道具 舉報

ID:777254 發(fā)表于 2024-8-1 19:41 | 顯示全部樓層
目前的解析一個協(xié)議,一開始用witch,分支有數(shù)據(jù)讀寫之類的幾個大case;然后讀功能里面需要讀的協(xié)議太多了,我看了協(xié)議文檔,幾千條。所以讀分支里面不能再用switch了,不然又有幾千個分支。目前是在讀分支里面使用if else寫著。因為查表法需要數(shù)組,RAM也要花費好多,所以暫時不用數(shù)組建立表了。還有好方法嗎?盡量不占用/少用RAM空間
回復(fù)

使用道具 舉報

ID:1109793 發(fā)表于 2024-8-1 10:21 | 顯示全部樓層
幾千種,那可是復(fù)雜了,這么復(fù)雜的系統(tǒng),厲害了。要不先分開,比如>10<20,每10個分一組?
回復(fù)

使用道具 舉報

ID:277550 發(fā)表于 2024-8-1 11:15 | 顯示全部樓層
幾十個,不算多了。想優(yōu)化,在if之前優(yōu)化。
回復(fù)

使用道具 舉報

ID:69038 發(fā)表于 2024-8-1 11:18 | 顯示全部樓層
"假定有一個16位變量,代表不同狀態(tài),狀態(tài)有幾千種,且某些功能的狀態(tài)值是不連續(xù)的。"
如果真有幾千種的狀態(tài),只能說這個系統(tǒng)架構(gòu)有問題了。才疏學(xué)淺想不出這么多復(fù)雜的狀態(tài),只用一個16位變量來表示。。

建議參考LCM1602、LCM12864的指令集做個散轉(zhuǎn)表,或許能實現(xiàn)。它是一個8bit的寄存器,從bit7開始,共8個標志,除開標志位,余下的bit是參數(shù)值(如果有的話)。。

圖樣1

圖樣1



回復(fù)

使用道具 舉報

ID:276663 發(fā)表于 2024-8-1 12:41 | 顯示全部樓層
跟樓上意思類似,借鑒IPV4,使用掩碼分級判斷,歸類處理
回復(fù)

使用道具 舉報

ID:744809 發(fā)表于 2024-8-1 15:14 | 顯示全部樓層
寫一個映射表,從值映射到狀態(tài),然后用switch
回復(fù)

使用道具 舉報

ID:220661 發(fā)表于 2024-8-1 15:44 | 顯示全部樓層
數(shù)組吧,節(jié)省空間,提升速度。
回復(fù)

使用道具 舉報

ID:1087128 發(fā)表于 2024-8-1 16:16 | 顯示全部樓層
if先判斷一個范圍
回復(fù)

使用道具 舉報

ID:451718 發(fā)表于 2024-8-1 17:35 | 顯示全部樓層
從數(shù)據(jù)結(jié)構(gòu)的角度出發(fā),你在一個分支下面查詢上千個塞選,本身就是不科學(xué)的。最好的優(yōu)化方法,就是不斷的細分,采用多級查詢。
回復(fù)

使用道具 舉報

ID:624769 發(fā)表于 2024-8-1 18:43 | 顯示全部樓層
c語言如何實現(xiàn) 不太清楚, 匯編的話,可以根據(jù)變量值  直接跳轉(zhuǎn)若干行(比如: JMP  @A+PC),然后在  相應(yīng)的位置寫下分支就可以了。
回復(fù)

使用道具 舉報

ID:777254 發(fā)表于 2024-8-1 19:33 | 顯示全部樓層
xiaobendan001 發(fā)表于 2024-8-1 10:21
幾千種,那可是復(fù)雜了,這么復(fù)雜的系統(tǒng),厲害了。要不先分開,比如>10

協(xié)議功能碼太多了,不同功能發(fā)送不同數(shù)據(jù),越寫case越多,不好搞
回復(fù)

使用道具 舉報

ID:777254 發(fā)表于 2024-8-1 19:35 | 顯示全部樓層
gongnn 發(fā)表于 2024-8-1 15:44
數(shù)組吧,節(jié)省空間,提升速度。

不行啊,一個數(shù)組包含的狀態(tài)也很多,導(dǎo)致RAM不夠。
回復(fù)

使用道具 舉報

ID:777254 發(fā)表于 2024-8-1 19:41 | 顯示全部樓層
zhuls 發(fā)表于 2024-8-1 11:18
"假定有一個16位變量,代表不同狀態(tài),狀態(tài)有幾千種,且某些功能的狀態(tài)值是不連續(xù)的。"
如果真有幾千種的狀 ...

好的,謝謝,我參考一下
回復(fù)

使用道具 舉報

ID:57657 發(fā)表于 2024-8-1 21:42 | 顯示全部樓層
li1069136863 發(fā)表于 2024-8-1 19:35
不行啊,一個數(shù)組包含的狀態(tài)也很多,導(dǎo)致RAM不夠。

你要搞清楚 C語言是單片機還是操作系統(tǒng)運行的 寫法不一樣
回復(fù)

使用道具 舉報

ID:57657 發(fā)表于 2024-8-1 21:51 | 顯示全部樓層
用二分查找,找到的取出索引 然后用該索引地址定位到函數(shù)指針數(shù)組執(zhí)行相應(yīng)的函數(shù),找不到的執(zhí)行default。
回復(fù)

使用道具 舉報

ID:401564 發(fā)表于 2024-8-2 13:07 | 顯示全部樓層
不知道你這個是什么協(xié)議,幾千個狀態(tài),那不得幾千個函數(shù)來處理?在單片機領(lǐng)域,搞這種東西出來的,十有八九是新手
還不如果直接說,你要干嘛,說不定網(wǎng)還能幫到你
如果說從一開始,方向就是錯的,那就太浪費時間了
回復(fù)

使用道具 舉報

ID:1129414 發(fā)表于 2024-8-2 17:00 | 顯示全部樓層
你寫的是啥,判斷幾千個狀態(tài),單片機估計夠嗆
回復(fù)

使用道具 舉報

ID:777254 發(fā)表于 2024-8-2 20:20 | 顯示全部樓層
Y_G_G 發(fā)表于 2024-8-2 13:07
不知道你這個是什么協(xié)議,幾千個狀態(tài),那不得幾千個函數(shù)來處理?在單片機領(lǐng)域,搞這種東西出來的,十有八九是新 ...

電表的DLT645協(xié)議,里面的協(xié)議太多,需要讀取的參數(shù)太多了,不知道怎么優(yōu)化。
回復(fù)

使用道具 舉報

ID:777254 發(fā)表于 2024-8-2 20:28 | 顯示全部樓層
li1069136863 發(fā)表于 2024-8-1 19:41
目前的解析一個協(xié)議,一開始用witch,分支有數(shù)據(jù)讀寫之類的幾個大case;然后讀功能里面需要讀的協(xié)議太多了 ...

是DLT645-2007電表協(xié)議,有做過的大佬嗎?
回復(fù)

使用道具 舉報

ID:57657 發(fā)表于 2024-8-2 22:24 | 顯示全部樓層
狀態(tài)表數(shù)組使用二分查找 可以不連續(xù)但必須從小到大排序,找到的返回索引,找不到的返回指定數(shù)字。
然后用索引訪問指針表數(shù)組,取出函數(shù)指針并傳遞參數(shù)執(zhí)行,最后取回返回值,如果參數(shù)還傳遞其他數(shù)據(jù)類型或數(shù)組可能涉及多級指針。
回復(fù)

使用道具 舉報

ID:982617 發(fā)表于 2024-8-7 16:04 | 顯示全部樓層
面對大量狀態(tài)處理的場景,確實單靠 `switch-case` 或 `if-else` 結(jié)構(gòu)可能會顯得冗長且難以維護。你可以考慮以下幾種優(yōu)化策略:

1. **枚舉類型(Enum)**:將狀態(tài)值定義為枚舉類型,這樣不僅代碼更清晰,還可以利用編譯器的靜態(tài)檢查避免狀態(tài)值的誤用。枚舉類型能提供更好的可讀性,并且可以更方便地添加或修改狀態(tài)。

   ```c
   enum State {
       STATE_1, STATE_2, STATE_3, ... // 具體狀態(tài)
   }
   ```

2. **狀態(tài)機(State Machine)**:如果狀態(tài)之間有明確的轉(zhuǎn)換邏輯,可以設(shè)計一個狀態(tài)機來管理狀態(tài)的轉(zhuǎn)換。狀態(tài)機通過一系列狀態(tài)轉(zhuǎn)換函數(shù)或狀態(tài)對象來實現(xiàn),這樣可以清晰地表示狀態(tài)之間的依賴關(guān)系和轉(zhuǎn)換條件。

   ```c
   void process_state(State current_state) {
       switch (current_state) {
           case STATE_1:
               // 處理STATE_1邏輯
               break;
           case STATE_2:
               // 處理STATE_2邏輯
               break;
           // ...
           default:
               // 處理未知狀態(tài)
               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邏輯\
       } // 更多狀態(tài)\
   } while(0)
   ```

4. **使用函數(shù)指針或宏來封裝狀態(tài)邏輯**:如果每個狀態(tài)的處理邏輯不同且較為復(fù)雜,可以考慮使用函數(shù)指針或宏來封裝邏輯,這樣可以使得每個狀態(tài)的邏輯獨立且易于維護。

   ```c
   typedef void (*StateHandler)(void);
   StateHandler state_handlers[] = {
       &process_state_1,
       &process_state_2,
       // 更多狀態(tài)函數(shù)\
   };

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

5. **使用類或結(jié)構(gòu)體**:對于復(fù)雜的狀態(tài),可以考慮使用類或結(jié)構(gòu)體來封裝狀態(tài)的屬性和處理邏輯。這樣可以更好地組織代碼,提高可讀性和可維護性。

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

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

6. **性能考慮**:在選擇優(yōu)化策略時,也需要考慮性能影響。宏和函數(shù)調(diào)用在某些情況下可能會帶來額外的開銷。在進行優(yōu)化時,可以先進行性能測試,確保優(yōu)化后代碼的執(zhí)行效率滿足需求。

通過上述方法,你可以更有效地管理和處理大量狀態(tài),提高代碼的可讀性和可維護性。根據(jù)具體需求和場景,選擇最適合的優(yōu)化策略。
回復(fù)

使用道具 舉報

ID:688692 發(fā)表于 2024-8-8 14:05 | 顯示全部樓層
li1069136863 發(fā)表于 2024-8-2 20:28
是DLT645-2007電表協(xié)議,有做過的大佬嗎?

你是要實現(xiàn)協(xié)議還是做這個協(xié)議的上位機?我寫過一個簡單的上位機,不復(fù)雜。要實現(xiàn)這個協(xié)議,幾十個if是合理范圍。
回復(fù)

使用道具 舉報

ID:777254 發(fā)表于 2024-8-8 20:20 | 顯示全部樓層
cnos 發(fā)表于 2024-8-8 14:05
你是要實現(xiàn)協(xié)議還是做這個協(xié)議的上位機?我寫過一個簡單的上位機,不復(fù)雜。要實現(xiàn)這個協(xié)議,幾十個if是合 ...

我是接收上位機發(fā)來的DLT645協(xié)議,實現(xiàn)對應(yīng)功能。太多參數(shù)要讀寫了,目前用if else,能把連續(xù)的協(xié)議簡化,看起來沒那么臃腫
回復(fù)

使用道具 舉報

ID:57657 發(fā)表于 2024-8-9 05:30 | 顯示全部樓層
hezezeze 發(fā)表于 2024-8-7 16:04
面對大量狀態(tài)處理的場景,確實單靠 `switch-case` 或 `if-else` 結(jié)構(gòu)可能會顯得冗長且難以維護。你可以考慮 ...

類是操作系統(tǒng)的運行環(huán)境才有的,單片機內(nèi)存小幾乎不可能。
回復(fù)

使用道具 舉報

ID:844772 發(fā)表于 2024-8-9 08:46 | 顯示全部樓層
其實就是個簡單的數(shù)據(jù)庫搜索功能,但用單片機實現(xiàn)就很麻煩。
回復(fù)

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

手機版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機教程網(wǎng)

快速回復(fù) 返回頂部 返回列表