HeadFirstC笔记_7 高级函数:发挥函数的极限

寻找真命天子……
完成find()函数,用它过滤出ADS列表中所有运动迷,同时他们不能是 Bieber的粉丝。
   
   
   
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. int NUM_ADS = 7;
  5. char *ADS[] = { "William: SBM GSOH likes sports, TV, dining",
  6. "Matt: SWM NS likes art, movies, theater",
  7. "Luis: SLM ND likes books, theater, art",
  8. "Mike: DWM DS likes trucks, sports and bieber",
  9. "Peter: SAM likes chess, working out and art",
  10. "Josh: SJM likes sports, movies and theater",
  11. "Jed: DBM likes theater, books and dining"
  12. };
  13. void find() {
  14. int i;
  15. puts("Search results:");
  16. puts("------------------------------------");
  17. for (i = 0; i < NUM_ADS; i++) {
  18. // if ( strstr(ADS[i],"sports")!=NULL && strstr(ADS[i],"bieber")==NULL) {
  19. // 上面的可以简化为:
  20. if (strstr(ADS[i], "sports") && !strstr(ADS[i], "bieber")) {
  21. printf("%s\n", ADS[i]);
  22. }
  23. }
  24. puts("------------------------------------");
  25. // printf("sizeof(ADS)=%i\n", sizeof(ADS)); // 结果是 sizeof(ADS)=56
  26. }
  27. int main() {
  28. find();
  29. return 0;
  30. }
运行结果:

现在,加入需求改成过滤出ADS列表中所有戏剧迷,该怎么做?
你可能第一感觉就是复制函数然后修改一下。但是...

复制函数会产生很多重复代码
C程序经常会执行一些大同小异的任务,现在 find() 函数为了 搜索匹配字符串,会遍历数组中所有元素,并测试每个字符 串,
而这些测试会写死在代码中,也就是说函数永远只能做一 种测试。 当然也可以把字符串作为参数传递给函数,让函数搜索不同的子串,
但这样 find() 还是无法检查3个字符串,比如“arts”、“theater” 和“dining”。你需要的是一种截然不同的技术。

把代码传给函数
你需要把测试代码传给 find() 函数,如果有办法把代码打 包传给函数,就相当于传给 find() 函数一台测试机,函数 再用测试机测试所有数据。
这样一来 find() 函数中大部分代码可以原封不动。代码 还是要检查数组中所有元素,并显示相同的输出,只是测 试数组元素的代码是你传给它的。

要是把函数名告诉find(),find就可以执行该函数就好了。
函数名是指向函数的指针 …
在C语言中,函数名也是指针变量。当你创建了一个叫 go_to_warp_speed(int speed) 函数的同时也会创 建了一个叫 go_to_warp_speed 的指针变量,
变量中 保存了函数的地址。只要把函数指针类型的参数传给 find() ,就能调用它指向的函数了。
(注:
两者并不完全相同,函数名是L-value,而指针变量是R-value,因此函 数名不能像指针变量那样自加或自减。

如何创建函数指针
     
     
     
  1. int go_to_warp_speed(int speed)
  2. {
  3. ...
  4. }
  5. // 创建一个叫warp_fn的变量,用来保存go_to_warp_speed()函数的地址。
  6. int (*warp_fn)(int); // 第一个int是函数返回值,第二个是函数的参数,可以再加,中间的是函数指针名
  7. warp_fn = go_to_warp_speed;
  8. warp_fn(4); // 相当于调用go_to_warp_speed(4)。
一旦声明了函数指针变量,就可以
像其他变量一样使用它,可以对它赋值,也可以把它加
到数组中,还可以把它传给函数……
修改之前的代码,并添加新的需求:
     
     
     
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. int NUM_ADS = 7;
  5. char *ADS[] = { "William: SBM GSOH likes sports, TV, dining",
  6. "Matt: SWM NS likes art, movies, theater",
  7. "Luis: SLM ND likes books, theater, art",
  8. "Mike: DWM DS likes trucks, sports and bieber",
  9. "Peter: SAM likes chess, working out and art",
  10. "Josh: SJM likes sports, movies and theater",
  11. "Jed: DBM likes theater, books and dining" };
  12. int sports_no_bieber(char *s) {
  13. return strstr(s, "sports") && !strstr(s, "bieber");
  14. }
  15. int sports_or_workout(char *s) {
  16. return strstr(s, "sports") || strstr(s, "working out");
  17. }
  18. int ns_theater(char *s) {
  19. return strstr(s, "theater") && strstr(s, "NS");
  20. }
  21. int arts_theater_or_dining(char *s) {
  22. return strstr(s, "art") || strstr(s, "theater") || strstr(s, "dining");
  23. }
  24. // 调用函数指针变量,将函数名当参数传递进去
  25. //void find(int match(char *s)) { 这种竟然也可以,奇怪?---->可加也可不加
  26. void find(int (*match)(char *s)) {
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值