理解了C中的聲明和指針的話題後再來看函數指針的用法就很容易了。
C中函數指針主要有兩個用途:
1.作為參數傳遞給另外一個函數(即作為回調函數)
2.轉換表(jump table)
下面分別來介紹作為回調函數的用法和作為轉換表的用法
1.回調函數
在鏈表的查找中使查找函數與類型無關
/*在一個單鏈表中查找一個指定值的函數。它的參數是一個指向鏈表第一個節點的指針 * 一個指向我們需要查找的值的指針和一個函數指針,它所指向的函數用於比較存儲於鏈表中的類型的值*/ #include#include Node * search_list(Node *node,void const *value,int (*compare)(void const *,void const *)){ while(node!=NULL){ if(compare(&node->value,value)==0) break; node=node->link; } return node; }
int compare_ints(void const *a,void const *b){ if(*(int *)a==*(int *)b) return 0; else return 1; }
desired_node=search_list(root,&desired_value,compare_ints);
創建轉移表的兩個步驟:首先,聲明並初始化一個函數指針數組。唯一需要留心之處就是確保這個函數的原型出現在這個數組的聲明之前。
double add(double,double);
double sub(double,double)
...
double (*oper_func[])(double,double);
第二步就是使用oper_func[oper](op1,op2)代替switch語句.
下面是一個從標准輸入中讀取一些字符,並根據下面的分類計算各類字符所占的百分比的程序:
控制字符 iscntrl
空白字符 isspace
數字 isdigit
小寫字母 islower
大寫字母 isupper
標點符號 ispunct
不可打印字符isprint為可打印字符
上面這些字符的分類在ctype.h中都有對應的函數
不使用if語句而使用轉換表的方法如下:
#include#include #include /*計算從標准輸入的積累字符的百分比*/ /*定義一個函數,判斷一個字符是否為可打印字符。這可以消除下面代碼中的這類 * 特殊的情況*/ int is_not_print(int ch){ return !isprint(ch); } /*用於區別每種類型的分類函數的跳轉表*/ static int(*test_func[])(int)={ iscntrl, isspace, isdigit, islower, isupper, ispunct, is_not_print }; #define N_CATEGORIES (sizeof(test_func)/sizeof(test_func[0])) /*每種字符的名字*/ char * label[]={ control, whitespace, digit, lower case, upper case, punctuation, non-printable }; /*目前見到的每種類型的字符數以及字符的總量*/ int count[N_CATEGORIES]; int total; int main(){ int ch; int category; /*讀取和處理每個字符*/ while((ch=getchar())!=EOF){ total+=1; /*為這個字符調用每個測試函數,如果結果為真,增加對於計數器的值*/ for(category=0;category 可以很明顯的看出使用轉換表的好處,代碼簡短了很多,也很清晰。
下面是測試結果:
添加一個小的知識點,就是EOF,在命令行下新輸入一行,按下ctrl+z組合鍵,再點擊回車,就是EOF