函数指针的定义:

函数类型 (标识符 指针变量名)(形参列表)

void  printHello( );

void printHello( ){

  printf("hello world!!! " );

}

main函数中:

//创建函数指针,同时赋值空.

int (*p)() = NULL;

p = printHello  // 将函数名称 赋值给函数指针,相当于函数的入口赋值给一个内存地址.

p( );      // 此时函数指针p就可以像函数名一样调用. 就可以理解为p 于 函数名是"相等".

实用1:

int sumValue(int a , int b){

  return a + b;

}

int subValue(int a , int b ){

  return a - b;

}

main函数:

//创建一个函数指针变量

int (*p2)(int , int);

// char str[] ={0};

// 在堆空间开辟一个 1* 20 字节的空间,同时str指向控制台输入的字符数组.

char *str = malloc( sizeof(char) * 20);

printf("Please enter some thing :");

scanf("%s" , str);         // 注意这里str本身就是指针,一个地址,不需要在用&或者地址,直接赋值.

if(strcmp(str, "sub") == 0){

  p = subValue;    // p 为函数指针,所以赋值给它的是函数的入口地址,就是函数名称 ,需要后面的( )

}else if( strcmp(str , "sum") == 0){

  p = sumValue;

}else {

  printf("you are wrong !! ");

}

int x = 20, y = 45;

int result = p( x, y );  直接使用p来代替subValue或者sumValue函数名称,并调用函数.

printf("%d", result );

free( str );

str = NULL;

实用2:写一函数查找成绩90分以上的学员,使⽤用回调函数在姓名后加”高富帅".

typedef struct {

  int num;

  char name[30];

  char gender;

  float score;

} Student;

void printStudent(Student *stu, int count );

void printStudent(Student *stu, int count ){

  for (int i = 0 ; i< count ; i++){

    printf("%d %s %c %f ", (stu+i)->num, (stu+i)->name, (stu+i)->gender, (stu+i)->score);

  }

}

void getStudent(Student *stu , int count , void (*p)(Student *));

void getStudent(Student *stu , int count , void (*p)(Student *)){

    for(int i = 0 ; i< count ; i++){

        if((stu+i)->score >= 90){

            p(stu+i);  //传入一个指针     

        }

    }

}

void getName(Student *s1);

void getName(Student *s1){

  strcat(s1->name, "白富美");

}

main函数:

Student stu[] ={

{21, "luoshuai", 'm', 76.8},

{12, "luoteng", 'f', 98.6},

{68, "liruoxuan", 'm', 29.6},

{43, "lihuahua", 'f', 99.7},

{87, "guagua", 'm', 23.5}

};

Student *st = stu;

int count = sizeof(stu) / sizeof(Student);

getStudent(st , count , getStudent);

printStudent(st, count);

//动态排序

为函数指针重新命名: 比如说 int (*p)(int ,int ) 在很多地方都可以用到,我觉得很长很丑,简化一下:

typedef int(*PFUNC)(int ,int ) 以后在程序中任何使用到该函数指针的地方都可以用PFUNC xxx 来创建函数指针变量.

仍然使用上述的结构体和结构体数组,我们根据age或者score或者name来进行排序

void sortStudent( Student *stu, int count);

void sortStudent( Student *stu, int count){

  for(int i = 0 ; i< count -1; i++){

    int minKey = i ;

    for(int j = i+1; j< count; j++){

       // 如果有一天我修改条件,根据姓名 或者我又修改,根据学号来排序,我们每次都需要过来修改一次很麻烦.

      //  所以我们引入了动态排序的概率,不在需要,查询该函数的数据,只需要在外部进行不同条件的判断.     

      // if((stu+j)->score  < (stu+minKey)->score ){  

        minKey = j;

       }    

    }

  if(minKey != i ){

    Student temp = *(stu + i);

    *(stu+i ) =*(stu +minKey);

    *(stu+minKey) = temp;

  }

}

}

main函数中:

Student *s1 = stu;

int count = sizeof(stu) /sizeof(Student);

// sortStudent(s1, count);

//  printStudent(s1, count );

修改sortStudent()函数如下:

void sortStudent( Student *stu, int count, BOOL (*p2)(Student *, Student *));

void sortStudent( Student *stu, int count, BOOL (*p2)(Student *, Student *)){

  for(int i = 0 ; i< count -1; i++){

    int minKey = i ;

    for(int j = i+1; j< count; j++){

       // 如果有一天我修改条件,根据姓名 或者我又修改,根据学号来排序,我们每次都需要过来修改一次很麻烦.

      //  所以我们引入了动态排序的概率,不在需要,查询该函数的数据,只需要在外部进行不同条件的判断.     

      if( p2(stu+j, stu+minKey) ){  

        minKey = j;

       }    

    }

  if(minKey != i ){

    Student temp = *(stu + i);

    *(stu+i ) =*(stu +minKey);

    *(stu+minKey) = temp;

  }

}

}

//根据名字来排序

BOOL changeStudentByName(Student *stu1, Student *stu2);

BOOL changeStudentByName(Student *stu1, Student *stu2){

  return strcmp(stu1->name, stu2->name) > 0;  // 注意这里需要大于0才能成立.

}

// 根据分数来排序

BOOL changeStudentByScore(Student *stu1, Student *stu2);

BOOL changeStudentByScore(Student *stu1, Student *stu2){

  return stu1->score > stu2->score ;    // 这里需要两两的分数大于或者小于才成立.

}

最后我们在main函数中调用:

Student *s1 = stu;

int count = sizeof(stu) /sizeof(Student);

sortStudent( stu, count, changeStudentByName );

printStudent(stu, count);

最后一个问题,返回值为函数指针:

typedef BOOL (*PFUNC)(Student *,Student *) ;

typedef struct {

  char name[40];

  PFUNC p;

} nameFunction;

PFUNC getFunctionName(char *str){

  if(strcmp(str, "name") == 0 ){

    return changeStudentByName;

  }else if(strcmp(str, "num") == 0){

    return changeStudentByNum;   // 返回函数主入口的地址.表示为函数名称.

  }else if(strcmp(str, "score") == 0){

    return changeStudentByScore;

  }

  return NULL;

}

int str1[] ={0};

printf(" Please enter some thing s :");

scanf("%s", str1);

PFUNC p3 = getFunctionByName(str1);

if( p3 == NULL){

return 0;

}

sortStudent(st, count, p3);

printStudent(st, count);

C语言基础11的更多相关文章

  1. C语言基础(11)-随机数发生器

    一. rand() rand是一个C语言库函数,功能是生成一个随机数.rand需要一个不同的种子,才能生成不同的随机数. 二. srand(int seed) rand需要一个不同的种子,才能生成不同 ...

  2. C语言基础 (11) 结构体 ,共用体 枚举 typedef

    1 课堂回顾 作用域与生命周期 2 static 局部变量 2 打字游戏 3 内存分区代码分析 4 结构体基本操作 (复合类型[自定义类型 #include <stdio.h> #incl ...

  3. C++语言基础(11)-多态

    一.产生背景 先看下面的例子: #include <iostream> using namespace std; //基类People class People{ public: Peop ...

  4. Java语言基础(11)

    1 构造方法 构造方法是一种特殊的方法,只有在创建对象的时候才被调用,用来执行初始化的操作,比如给属性赋值... 1) 构造方法名字跟类名一致,没有返回值也就没有返回值类型 2) 格式: 类名(参数列 ...

  5. Java入门 - 语言基础 - 11.switch_case

    原文地址:http://www.work100.net/training/java-switch-case.html 更多教程:光束云 - 免费课程 switch_case 序号 文内章节 视频 1 ...

  6. [11 Go语言基础-可变参数函数]

    [11 Go语言基础-可变参数函数] 可变参数函数 什么是可变参数函数 可变参数函数是一种参数个数可变的函数. 语法 如果函数最后一个参数被记作 ...T ,这时函数可以接受任意个 T 类型参数作为最 ...

  7. GO学习-(11) Go语言基础之map

    Go语言基础之map Go语言中提供的映射关系容器为map,其内部使用散列表(hash)实现. map map是一种无序的基于key-value的数据结构,Go语言中的map是引用类型,必须初始化才能 ...

  8. C语言基础回顾

    第一章 C语言基础 1.  C语言编译过程 预处理:宏替换.条件编译.头文件包含.特殊符号 编译.优化:翻译并优化成等价的中间代码表示或汇编代码 汇编:生成目标文件,及与源程序等效的目标的机器语言代码 ...

  9. 【GoLang】GO语言系列--002.GO语言基础

    002.GO语言基础 1 参考资料 1.1 http://www.cnblogs.com/vimsk/archive/2012/11/03/2736179.html 1.2 https://githu ...

随机推荐

  1. python笔记之bisect模块

    python笔记之bisect模块 当你决定使用二分搜索时,这个模块会给你带来很大的帮助. 例子 import bisect L = [1,3,3,6,8,12,15] x = 3 #在L中查找x,x ...

  2. 怎样使用淘宝npm镜像

    淘宝的 NPM 镜像是一个完整的npmjs.org镜像.你可以用此代替官方版本(只读),同步频率目前为 15分钟 一次以保证尽量与官方服务同步. 当前 registry.npm.taobao.org ...

  3. path类和directory类对文件的路径或目录进行操作

    Path: 对文件或目录的路径进行操作(很方便)[只是对字符串的操作] 1.目录和文件操作的命名控件System.IO    2.string Path.ChangeExtension(string ...

  4. 我的第一个MFC的ArcGIS Engine程序

    原文 http://blog.csdn.net/zzahkj/article/details/9003518 (第一版,以VC++6.0+AE9.3为例) 首次,学习MFC,写个笔记,MFC还是挺好学 ...

  5. GRUB启动管理器

    Linux学习笔记之 5 Linux GRUB启动管理器 1.GRUB简介 1.1grub与启动引导器     启动引导器是计算机启动过程中运行的第一个真正的软件,通常计算机启动时在通过BIOS自检后 ...

  6. Linux系统编程(1)——文件与I/O之C标准I/O函数与系统调用I/O

    Linux系统的I/O也就是一般所说的低级I/O--操作系统提供的基本IO服务,与os绑定,特定于Linux平台.而标准I/O是ANSI C建立的一个标准I/O模型,是一个标准函数包和stdio.h头 ...

  7. linux多线程socket编程一些心得

    http://hi.baidu.com/netpet/blog/item/2cc79216d9012b54f2de32b9.html 前段时间将新的web模型办到linux上来,用epoll代替了IO ...

  8. Unity 读取Excel

    游戏有大多数配置文件,比如玩家等级,游戏商店信息等等.通常情况下把这些放入excel中来读取 第一种解决方案: xlsx –> csv –> 改变成UTF-8 或者Unicode编码 –& ...

  9. Elasticlunr.js 简单介绍

    Elasticlunr.js 项目地址:http://elasticlunr.com/ 代码地址:https://github.com/weixsong/elasticlunr.js 文档地址:htt ...

  10. poj2503--Babelfish(特里一水)

    Babelfish Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 32988   Accepted: 14189 Descr ...