Re: [問題] swith_case 用法

作者: totemist (totem)   2015-06-15 16:13:38
※ 引述《tropical72 (藍影)》之銘言:
: ※ 引述《totemist (totem)》之銘言:
: <恕刪>
: : input是相同的512筆data
: : 經由case去選擇不同的處理方式
: <恕刪>
: : 補充說明(Supplement):
: : 因為我是要做濾波器(fir filter - bandpass)
: : 我希望能給使用者自己選擇頻率(0~540hz,每60hz為一單位)
: : 所以我總共要做C10取2 有 45個case要做
: <恕刪>
: : ex:
: : printf("enter A=100_500 or D=200_600 = ");
: : 就是直接給使用者看著指令選擇
: : 但是我想做到的是給使用者自動輸入想要的頻寬
: : 只是覺得這樣對使用者比較方便,不用把我45個代號看完就可以自動輸入這樣
: 對於敘述其實有點看不懂,因裡面算出來的數字我真沒辦法對上 Orz
: 0~540 , 每 60 hz 為一個單位 , 這樣只會切成 10 分,
: 為什麼後面多出了 C(10,2) = 45 個 conditions ?
: A=100_500 代表若輸入的是 'A', filter 範圍是 (100,500)
: D=200_600 代表若輸入的是 'D', filter 範圍是 (200,600)
: 以下的敘述猜測就是 Feis 所提的方法。
: 根據最後一段敘述,我假設你需要的是 要做45次判斷,依序執行相對應之函式,
: 那你倒是可以這麼做
: const int iBoundCount = 45;
: const int iLowerBand[iBoundCount] = { 100,200,150,180,200, .... } ;
: const int iUpperBand[iBoundCount] = { 500.700.600.400.600. .... } ;
: iLowerBand 和 iUpperBand 可以用 struct stBand { int m_iLower , m_iUpper};
: 這裡不贅述。另上面這些常數可以寫到檔案裡面去,程式初始化時從檔案讀出,
: 這裡也不贅述。值得注意的是,如果你的 Bound 範圍是有規律的,事實上,上面的表
: 可以不用建立,只是為了說明方便,我還是以建表方式說明。
: 再來是使用者輸入的時候,你可以讓使用者自己去輸入
: lower bound 及 upper bound ,再去搜尋對應到的是哪一個 index
: int iUserLower , iUserUpper ; // 假設已拿到數值
: int iSelIndex ; // 判斷輸入數值落在陣列裡的哪個區間。
: for(iSelIndex = 0 ; iSelIndex < iBoundCount ; ++iSelIndex)
: if( iLowerBound[iSelIndex] == iUserLower &&
: iUpperBound[iSelIndex] == iUserUpper )
: break;
: if(iSelIndex == iBoundCount) { // 這裡是使用者輸入的值沒在兩個 array 找到 }
: else { // 這裡是使用者輸入的值剛好在 Lower[iSelIndex]/Upper[iSelIndex] }
: 換句話說,到這裡得到的 iSelIndex 會是 [ 0, iBoundCount ] 之連續整數。
: 如果硬要用 switch 寫的話還是可以,就變成了
: switch(iSelIndex)
: {
: case 0 : func0() ; break;
: case 1 : func1() ; break;
: case 2 : func2() ; break;
: ...
: case 44 : func44() ; break;
: default : InputError(); break; // 這裡是 iSelIndex == 45
: }
: 這樣看起來好像沒什麼改變對不對? 不對唷!關鍵是 iSelIndex 已經調整成 0~45,
: 它又可以拿來當陣列的索引值了,這時候就需要 函式指標陣列 了。
: 假設你的 function 每個都長得一樣,都是長成 void func(void) ; (長其他樣子也行,
: 重點是要長得一樣),上面的 switch 可被拿掉變成
: typedef void (*pFilterFunc)(void) ;
: pFilterFunc pFuncAry[iBoundCount] = {
: func1 , func2 , func3 , func4 , func5 , ... , func45
: };
: if(iSelIndex != iBoundCount) // 別忘了剛剛的 iSelIndex 怎來的
: {
: // User Input Error Process
: }
: else
: {
: pFuncAry[iSelIndex] () ; // 使用函式指標陣列進行呼叫函式
: }
: 好了,你要的東西上面應該已經提供一套 solution 給你了,但其他更好的架構
: 方式,像是
: struct {
: int iLowerBound ;
: int iUpperBound ;
: void (*pFilter)() ;
: }FilterInfo[] = {
: {100,200, func1},
: {200,500, func2},
: ...
: {150,700, func45}
: };
: 資料結構和詳細作法我也不再贅述了,也只是上述的東西再包過而已。然後這是用
: 純 C 的刻法,另一種解法是 C++ template ,這個我也不贅述。
: 重點是…嗯…你可以先確認一下,知不知道什麼是函式指標,什麼是函式指標陣列。
: 不知道的話必須先補起來,才能討論比較簡潔、"好一點點" 的架構。
: 但.是 (如果沒有但是的話下面可以不用看了...)
: 但.是. 如果好死不死,那些 func1 , func2 的 prototype 長得不一樣的話呢?
: 像是 void func1(int, int) , double func2(double, int) , ... etc ,
: 這裡其實我覺得還是直接用 45 個 switch-case 下去硬幹會比較方便,
: 走 C 風格的話還是可以用 函式指標陣列,只是所有函式必須改寫成
: void func(void *) 或是 int func( void *) ,至於 C++ 有沒有比較好的解法?
: 嗯,我想是有的,只是我也沒用過,也想知道。
這幾天又重回這個問題啦!!!!
經過學長的提點,這次的想法跟Tropical大有點像
首先我先把我原本45個1維array,變成一個2維的array: myfilter[45][406]
然後我目前想法是
設一個 int filter_id
然後利用Fpass和Fstop 找對應filter_id 一對一 函數的關係
Fpass Fstop filter_id
0 60 0
0 120 1
.
.
.
.
0 540 8
60 120 9
60 180 10
.
.
.
60 540 16
120 180 17
120 240 18
.
.
.
120 540 23
.
.
.
.
一直到最後
480 540 44
共有45個filter_id (0~44)
這樣的好處是
只要能找到filter_id,就能簡化把filer變成 myfilter[filter_id][406];
在function就不用像我之前那樣硬是要用45個case
一個就可以搞定了
只是我目前找的規律性還沒有很好,有點硬湊OAQ
也是分了很多if else來找filter_id
if (Fpass == 0)
filter_id = (Fstop/60)-1;
else if (Fpass == 60)
filter_id = (Fpass/10)+(Fstop/60)+(Fstop/60)-1;
else if (Fpass == 120)
filter_id = (Fpass/10)+(Fstop/60)+(Fstop/60)-1;
else if (Fpass ==180)
filter_id = (Fpass/10)+(Fstop/60)+2;
.
.
方法不同
.
.
else (Fpass == 480)
filter_id = 44;
有沒有人能有更簡潔的關係式來找filter_id呢?
謝謝
作者: Feis (永遠睡不著 @@)   2015-06-15 16:32:00
https://gist.github.com/feis/1ff45ffdd71c0d3a0849應該只是基礎的離散數學
作者: anyoiuo   2015-06-15 16:53:00
9+8+7+6+5+4+3+2+1這是等差級數和n[(2*a1+(n-1)*d)]/2F大借抄一部分,感恩! https://ideone.com/Mzs6f3這不是程式這是數學來著...XDa1=9帶入就會發現是F大的答案了
作者: tropical72 (藍影)   2015-06-15 20:20:00
所以我之前發的不算是廢文了嗎…滿滿的感動
作者: anyoiuo   2015-06-16 14:34:00
加油吧! 問題 => 找規律 => 思考 => Divide & Conquer你的方向是對的,想出自己解法,再看看人家解法,就會進步!

Links booklink

Contact Us: admin [ a t ] ucptt.com