C语言基础11
函数指针的定义:
函数类型 (标识符 指针变量名)(形参列表)
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的更多相关文章
- C语言基础(11)-随机数发生器
一. rand() rand是一个C语言库函数,功能是生成一个随机数.rand需要一个不同的种子,才能生成不同的随机数. 二. srand(int seed) rand需要一个不同的种子,才能生成不同 ...
- C语言基础 (11) 结构体 ,共用体 枚举 typedef
1 课堂回顾 作用域与生命周期 2 static 局部变量 2 打字游戏 3 内存分区代码分析 4 结构体基本操作 (复合类型[自定义类型 #include <stdio.h> #incl ...
- C++语言基础(11)-多态
一.产生背景 先看下面的例子: #include <iostream> using namespace std; //基类People class People{ public: Peop ...
- Java语言基础(11)
1 构造方法 构造方法是一种特殊的方法,只有在创建对象的时候才被调用,用来执行初始化的操作,比如给属性赋值... 1) 构造方法名字跟类名一致,没有返回值也就没有返回值类型 2) 格式: 类名(参数列 ...
- Java入门 - 语言基础 - 11.switch_case
原文地址:http://www.work100.net/training/java-switch-case.html 更多教程:光束云 - 免费课程 switch_case 序号 文内章节 视频 1 ...
- [11 Go语言基础-可变参数函数]
[11 Go语言基础-可变参数函数] 可变参数函数 什么是可变参数函数 可变参数函数是一种参数个数可变的函数. 语法 如果函数最后一个参数被记作 ...T ,这时函数可以接受任意个 T 类型参数作为最 ...
- GO学习-(11) Go语言基础之map
Go语言基础之map Go语言中提供的映射关系容器为map,其内部使用散列表(hash)实现. map map是一种无序的基于key-value的数据结构,Go语言中的map是引用类型,必须初始化才能 ...
- C语言基础回顾
第一章 C语言基础 1. C语言编译过程 预处理:宏替换.条件编译.头文件包含.特殊符号 编译.优化:翻译并优化成等价的中间代码表示或汇编代码 汇编:生成目标文件,及与源程序等效的目标的机器语言代码 ...
- 【GoLang】GO语言系列--002.GO语言基础
002.GO语言基础 1 参考资料 1.1 http://www.cnblogs.com/vimsk/archive/2012/11/03/2736179.html 1.2 https://githu ...
随机推荐
- Array类型(二)
1.concat()方法可以基于当前数组中的所有项创建一个新数组. 先创建当前数组的一个副本,然后将接收到的参数添加到这个副本的末尾,最后返回新构建的数组. var colors = ["r ...
- discuz论坛目录功能详解
在某处收集来的discuz目录资料,二次开发挺有用的.记录下.(基于7.0的标准程序,部分与插件无关的文件不作说明) 文件颜色说明: 红色:程序核心文件,修改这类文件时千万要注意安全! 橙色:做插件几 ...
- arcpy批量打印地图
有个处理数据的需求是把一个图层中的要素单独显示在底图上,设置固定的比例尺,并打印出图片. 考虑到后续会有重复的大量的数据要处理,决定使用arcpy处理. 首先新建一个mxd底图文档,把需要打印的地图都 ...
- C语言编译过程简介
刚开始接触编程的时候,只知道照书敲敲代码,一直都不知道为什么在windows平台下代码经过鼠标那样点击几下,程序的结果就会在那个黑色的屏幕上.现在找了个机会将C语言的编译原理做一下小小的总结,这样也能 ...
- BC 65 ZYB's Premutation (线段树+二分搜索)
题目简述:有一个全排列,一直每个前缀区间的逆序对数,还原这个排列. fi记录逆序对数,pi记录该位置数值,则k=fi-f(i-1)表示前i-1个数比pi大的数的个数,那么只要在剩余元素求出按大小顺序第 ...
- Hdu1001(1到100的和)
常规算法: #include <stdio.h> int main() { // 常规算法 int a; while(scanf("%d",&a)!=EOF){ ...
- mysql----show slave status \G 说明
show slave status \G 可以用来查看mysql 的复制状态,有些列名所表达的意思不太明确,现整理如下: 1. Slave_IO_State:ID线程的状态,如果master 的所有变 ...
- Android Fragment中使用Intent组件拍照
要在activity里面去接受,然后传递给fragment对象,fragment有很多回调调用不到 你的设备有摄像头吗? 为了确保市场上的大多数设备都能运行你的程序,必须在项目中做一些检测,保证使用的 ...
- Populating Next Right Pointers in Each Node 解答
Question Given a binary tree struct TreeLinkNode { TreeLinkNode *left; TreeLinkNode *right; TreeLink ...
- Linux下alias命令
功能说明:设置指令的别名.语 法:alias[别名]=[指令名称]参 数 :若不加任何参数,则列出目前所有的别名设置.举 例 :ermao@lost-desktop:~$ alias ...