C中函数指针的用法

理解了C中的声明和指针的话题后再来看函数指针的用法就很容易了。

C中函数指针主要有两个用途:

1.作为参数传递给另外一个函数(即作为回调函数)

2.转换表(jump table)


下面分别来介绍作为回调函数的用法和作为转换表的用法

1.回调函数

在链表的查找中使查找函数与类型无关

/*在一个单链表中查找一个指定值的函数。它的参数是一个指向链表第一个节点的指针
 * 一个指向我们需要查找的值的指针和一个函数指针,它所指向的函数用于比较存储于链表中的类型的值*/
#include <stdio.h>
#include <node.h>

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);

2.转移表

创建转移表的两个步骤:首先,声明并初始化一个函数指针数组。唯一需要留心之处就是确保这个函数的原型出现在这个数组的声明之前。

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 <stdlib.h>
#include <stdio.h>
#include <ctype.h>

/*计算从标准输入的积累字符的百分比*/

/*定义一个函数,判断一个字符是否为可打印字符。这可以消除下面代码中的这类
 * 特殊的情况*/
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<N_CATEGORIES;category++){
			if(test_func[category](ch))
				count[category]++;
		}
	}

	/*打印结果*/
	if(total==0)
		printf("No characters in the input!\n");
	else{
		printf("total characters:%d\n",total);
		for(category=0;category<N_CATEGORIES;category++){
			printf("%3.0f%% %s characters\n",count[category]*100.0/total,label[category]);
		}
	}	
	return 0;
}

可以很明显的看出使用转换表的好处,代码简短了很多,也很清晰。

下面是测试结果:




添加一个小的知识点,就是EOF,在命令行下新输入一行,按下ctrl+z组合键,再点击回车,就是EOF


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值