Re: [問題] swith_case 用法

作者: tropical72 (藍影)   2015-06-02 22:39:12
※ 引述《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++ 有沒有比較好的解法?
嗯,我想是有的,只是我也沒用過,也想知道。
作者: loveme00835 (髮箍)   2015-06-02 22:48:00
好久沒看到這帳號
作者: tropical72 (藍影)   2015-06-02 22:49:00
我也好久沒看到 loveme~ 發言了 Orz
作者: Feis (永遠睡不著 @@)   2015-06-02 23:05:00
我沒猜錯的話, 他不同的範圍只是選不同的陣列.所以還用不上函式指標陣列 Orz
作者: tropical72 (藍影)   2015-06-02 23:08:00
啊!好吧, 我又發廢文了 Orz
作者: totemist (totem)   2015-06-03 00:04:00
感謝T大分享想法~ 我會好好從中學習,因為我C不強,就是邊做邊學這樣。抱歉我在敘述上可能沒有講得很明確仔細,不過真的很感謝T大寫了這篇文章,絕對不會是廢文~ 原文我也有再修過了

Links booklink

Contact Us: admin [ a t ] ucptt.com