-
sql实现在评分记录集中去掉最高、最低百分之N评分记录
2018-01-13 15:10:13比如,有A、B、C三个员工竞选某要职,HR组织吃瓜群众位对其三位进行评分,出于不清楚的原因,HR在拿到群众们的评分结果后,会先对某侯选人的得分结果记录集进行排序,再按比例去掉记录两头(最高、最低)的N%评分...sql的优势之一是使用单一的命令能够访问到一个记录集,其重要的特点就是非过程化。
在很多企业流行着360评分体系。比如,有A、B、C三个员工竞选某要职,HR组织吃瓜群众位对其三位进行评分,出于不清楚的原因,HR在拿到群众们的评分结果后,会先对某侯选人的得分结果记录集进行排序,再按比例去掉记录两头(最高、最低)的N%评分记录,最后再进行后续计算。
本文是直接解决以上的“去掉记录两头的N%评分记录”的问题的。最少有以下几种方案:
(本文代码基于SQL Server2005,关于@tb_eval表变量的定义见本文最后的附录)
-- 去掉最高20%、最低20%评分
select * from @tb_eval a01 where a01.id not in (select top 20 percent id from @tb_eval a02 where a01.empid=a02.empid order by a02.score desc) and a01.id not in (select top 20 percent id from @tb_eval a02 where a01.empid=a02.empid order by a02.score asc) order by empid, score desc
-- 去掉最高20%、最低20%评分
select * from ( select row_number() over (partition by empid order by score desc) rowno, * from @tb_eval ) a01 where rowno > (select cast(round(count(*)*0.2,0) as int) padcnt from @tb_eval a02 where a01.empid=a02.empid) and rowno <= (select (count(*) - cast(round(count(*)*0.2,0) as int)) padcnt from @tb_eval a02 where a01.empid=a02.empid)
-- 去掉最高20%、最低20%评分
select a01.* from ( select row_number() over (partition by empid order by score desc) rowno, * from @tb_eval ) a01 left join ( select empid, cast(round(count(*)*0.2,0) as int) topcnt, cast(round(count(*)*0.2,0) as int) lastcnt, count(*) as totalcnt from @tb_eval group by empid ) a02 on a01.empid=a02.empid where a01.rowno>a02.topcnt and a01.rowno <= (a02.totalcnt - a02. lastcnt)
本问题其实像是大学时代的课后练习作业,写作本文的原因主要是想说明sql的非过程化,你不应该使用游标去完成本任务。
附录:
1、完整的代码
-- 人员表(本例不使用) declare @tb_emp table table ( id int, -- 人员ID name varchar(64) -- 人员名称 ); insert into @tb_emp (id, name) values(1, 'emp01'); insert into @tb_emp (id, name) values(2, 'emp02'); insert into @tb_emp (id, name) values(3, 'emp03'); insert into @tb_emp (id, name) values(4, 'emp04'); insert into @tb_emp (id, name) values(5, 'emp05'); insert into @tb_emp (id, name) values(6, 'emp06'); insert into @tb_emp (id, name) values(7, 'emp07'); insert into @tb_emp (id, name) values(8, 'emp08'); insert into @tb_emp (id, name) values(9, 'emp09'); insert into @tb_emp (id, name) values(10, 'emp10'); insert into @tb_emp (id, name) values(11, 'emp11'); insert into @tb_emp (id, name) values(12, 'emp12'); insert into @tb_emp (id, name) values(13, 'emp13'); insert into @tb_emp (id, name) values(14, 'emp14'); insert into @tb_emp (id, name) values(15, 'emp15'); insert into @tb_emp (id, name) values(16, 'emp16'); insert into @tb_emp (id, name) values(17, 'emp17'); insert into @tb_emp (id, name) values(18, 'emp18'); insert into @tb_emp (id, name) values(19, 'emp19'); insert into @tb_emp (id, name) values(20, 'emp20'); insert into @tb_emp (id, name) values(21, 'emp21'); insert into @tb_emp (id, name) values(22, 'emp22'); insert into @tb_emp (id, name) values(23, 'emp23'); insert into @tb_emp (id, name) values(24, 'emp24'); insert into @tb_emp (id, name) values(25, 'emp25'); -- 评分表 declare @tb_eval table ( id int not null identity(1,1) primary key, -- 评分表自动编号 empid int, -- 被评分人员ID score decimal(10, 2), -- 评分 examinerid int -- 评分人员ID ); -- 给empid为1, 3, 5的评分 insert into @tb_eval (empid, score, examinerid) values (1,9, 4); insert into @tb_eval (empid, score, examinerid) values (1,76, 19); insert into @tb_eval (empid, score, examinerid) values (1,37, 10); insert into @tb_eval (empid, score, examinerid) values (1,90, 13); insert into @tb_eval (empid, score, examinerid) values (1,29, 7); insert into @tb_eval (empid, score, examinerid) values (1,6, 2); insert into @tb_eval (empid, score, examinerid) values (1,69, 17); insert into @tb_eval (empid, score, examinerid) values (1,76, 5); insert into @tb_eval (empid, score, examinerid) values (1,60, 15); insert into @tb_eval (empid, score, examinerid) values (3,13, 20); insert into @tb_eval (empid, score, examinerid) values (3,49, 6); insert into @tb_eval (empid, score, examinerid) values (3,72, 25); insert into @tb_eval (empid, score, examinerid) values (3,84, 2); insert into @tb_eval (empid, score, examinerid) values (3,4, 22); insert into @tb_eval (empid, score, examinerid) values (3,17, 11); insert into @tb_eval (empid, score, examinerid) values (3,74, 18); insert into @tb_eval (empid, score, examinerid) values (3,66, 21); insert into @tb_eval (empid, score, examinerid) values (3,62, 8); insert into @tb_eval (empid, score, examinerid) values (3,4, 4); insert into @tb_eval (empid, score, examinerid) values (3,66, 13); insert into @tb_eval (empid, score, examinerid) values (3,41, 3); insert into @tb_eval (empid, score, examinerid) values (3,94, 16); insert into @tb_eval (empid, score, examinerid) values (5,87, 24); insert into @tb_eval (empid, score, examinerid) values (5,71, 14); insert into @tb_eval (empid, score, examinerid) values (5,39, 22); insert into @tb_eval (empid, score, examinerid) values (5,55, 12); insert into @tb_eval (empid, score, examinerid) values (5,13, 19); insert into @tb_eval (empid, score, examinerid) values (5,73, 16); insert into @tb_eval (empid, score, examinerid) values (5,45, 10); insert into @tb_eval (empid, score, examinerid) values (5,9, 15); insert into @tb_eval (empid, score, examinerid) values (5,4, 8); insert into @tb_eval (empid, score, examinerid) values (5,31, 11); -- 全部评分按empid分组后,每组从高到低评分 select row_number() over (partition by empid order by score desc) rowno, * from @tb_eval -- 去掉最高20%、最低20%评分 select * from @tb_eval a01 where a01.id not in (select top 20 percent id from @tb_eval a02 where a01.empid=a02.empid order by a02.score desc) and a01.id not in (select top 20 percent id from @tb_eval a02 where a01.empid=a02.empid order by a02.score asc) order by empid, score desc -- 去掉最高20%、最低20%评分 select a01.* from ( select row_number() over (partition by empid order by score desc) rowno, * from @tb_eval ) a01 left join ( select empid, cast(round(count(*)*0.2,0) as int) topcnt, cast(round(count(*)*0.2,0) as int) endcnt, count(*) as totalcnt from @tb_eval group by empid ) a02 on a01.empid=a02.empid where a01.rowno>a02.topcnt and a01.rowno <= (a02.totalcnt - a02.endcnt) -- 去掉最高20%、最低20%评分 select * from ( select row_number() over (partition by empid order by score desc) rowno, * from @tb_eval ) a01 where rowno > (select cast(round(count(*)*0.2,0) as int) padcnt from @tb_eval a02 where a01.empid=a02.empid) and rowno <= (select (count(*) - cast(round(count(*)*0.2,0) as int)) padcnt from @tb_eval a02 where a01.empid=a02.empid)
2、未进行去头、去尾的结果:
rowno
id
empid
score
examinerid
1
4
1
90
13
2
2
1
76
19
3
8
1
76
5
4
7
1
69
17
5
9
1
60
15
6
3
1
37
10
7
5
1
29
7
8
1
1
9
4
9
6
1
6
2
1
22
3
94
16
2
13
3
84
2
3
16
3
74
18
4
12
3
72
25
5
17
3
66
21
6
20
3
66
13
7
18
3
62
8
8
11
3
49
6
9
21
3
41
3
10
15
3
17
11
11
10
3
13
20
12
14
3
4
22
13
19
3
4
4
1
23
5
87
24
2
28
5
73
16
3
24
5
71
14
4
26
5
55
12
5
29
5
45
10
6
25
5
39
22
7
32
5
31
11
8
27
5
13
19
9
30
5
9
15
10
31
5
4
8
3、去头、去尾后的结果:
rowno
id
empid
score
examinerid
3
8
1
76
5
4
7
1
69
17
5
9
1
60
15
6
3
1
37
10
7
5
1
29
7
4
12
3
72
25
5
17
3
66
21
6
20
3
66
13
7
18
3
62
8
8
11
3
49
6
9
21
3
41
3
10
15
3
17
11
3
24
5
71
14
4
26
5
55
12
5
29
5
45
10
6
25
5
39
22
7
32
5
31
11
8
27
5
13
19
-
Xcode中实现函数指针调用和结构体排序
2015-03-25 17:35:13] ,int count,CompareFunctionPointer cfp)函数,调用函数(使用switch…case,通过控制台输入的数字与枚举值匹配实现调用不同的函数)来分别实现按姓名、员工编号、评分排序,其中每种排序的升、降方式都要实现。...<pre name="code" class="cpp"><p><span style="font-family:Microsoft YaHei;font-size:18px;">① 创建一个Teacher数组,利用上面的sortTeachers(Teacher teacher[ ] ,int count,CompareFunctionPointer cfp)函数,调用函数(使用switch…case,通过控制台输入的数字与枚举值匹配实现调用不同的函数)来分别实现按姓名、员工编号、评分排序,其中每种排序的升、降方式都要实现。比如:分别实现对年龄按照升序、降序排列。</span></p><p><span style="font-family:Microsoft YaHei;font-size:18px;">② 输出教师数组中全部的男老师。</span></p><p><span style="font-family:Microsoft YaHei;font-size:18px;">③ 输出教师数组中的所有女老师。 </span></p>
/<span style="font-size:24px;">/ Teacher.h</span> // Exame // // Created by lanou3g on 15-3-25. // Copyright (c) 2015年 lanou3g. All rights reserved. // #import <Foundation/Foundation.h> // 第二种定义 // 性别 // typedef enum sex // { // Man, // Woman // } Sex; // typedef struct teacher // { // char name[20]; // Sex sex; // int age; // int num; // float score; // // } Teacher; typedef struct teacher { char name[20]; char sex; int age; int num; float score; } Teacher; enum FunctionName { CompareNameByAscending = 1, CompareNameByDescending, CompareNumberByAscending, CompareNumberByDescending, CompareScoreByAscending, CompareScoreByDescending, PrintFemaleTeacher, PrintMaleTeacher }; void printTeacher(Teacher *teacher); typedef BOOL (*CompareFunctionPointer)(Teacher teacher1,Teacher teacher2); void sortTeachers(Teacher teacher[],int count,CompareFunctionPointer cfp);//<span style="font-size:24px;"><strong>函数指针的利用</strong></span> void printTeachers(Teacher *teachers,int count); BOOL compareNumberAscending(Teacher teacher1,Teacher teacher2); BOOL compareNumberDescending(Teacher teacher1,Teacher teacher2); BOOL compareNameAscending(Teacher teacher1,Teacher teacher2); BOOL compareNameDescending(Teacher teacher1,Teacher teacher2); BOOL compareScoreDescending(Teacher teacher1,Teacher teacher2); BOOL compareScoreAscending(Teacher teacher1,Teacher teacher2); void printMaleTeacher(Teacher *teacher,int count); void printFemaleTeacher(Teacher *teacher,int count); <pre name="code" class="cpp">// // <strong><span style="font-size:18px;"> Teacher.m</span></strong> // Exame // // Created by lanou3g on 15-3-25. // Copyright (c) 2015年 lanou3g. All rights reserved. // #import "Teacher.h" void printTeacher(Teacher *teacher) { printf("姓名:%s,性别:%c,年龄:%d,编号:%d,评分:%f\n",teacher->name,teacher->sex,teacher->age,teacher->num,teacher->score); } typedef BOOL (*CompareFunctionPointer)(Teacher teacher1,Teacher teacher2);//<span style="font-size:24px;">定义函数指针</span> void sortTeachers(Teacher teacher[],int count,CompareFunctionPointer cfp)//<span style="font-size:24px;">函数回调</span> { for (int i = 0; i < count - 1; i ++) { for (int j = 0; j < count - i - 1; j ++) { if (cfp(teacher[j],teacher[j+1])) { Teacher tea = teacher[j]; teacher[j] = teacher[j+1]; teacher[j+1] = tea; } } } } void printTeachers(Teacher *teachers,int count) { for (int i = 0; i < count; i ++) { printTeacher(&teachers[i]); } } BOOL compareNumberAscending(Teacher teacher1,Teacher teacher2) { return teacher1.num > teacher2.num; } BOOL compareNumberDescending(Teacher teacher1,Teacher teacher2) { return teacher1.num < teacher2.num; } BOOL compareNameAscending(Teacher teacher1,Teacher teacher2) { //return strcmp(teacher1.name,teacher2.name); if (strcmp(teacher1.name,teacher2.name) > 0) { return YES; } else return NO; } BOOL compareNameDescending(Teacher teacher1,Teacher teacher2) { //return strcmp(teacher2.name, teacher1.name); if (strcmp(teacher1.name,teacher2.name) < 0) { return YES; } else return NO; } BOOL compareScoreDescending(Teacher teacher1,Teacher teacher2) { return teacher1.score < teacher2.score; } BOOL compareScoreAscending(Teacher teacher1,Teacher teacher2) { return teacher1.score > teacher2.score; } void printMaleTeacher(Teacher *teacher,int count) { for (int i = 0; i < count; i ++) { if (teacher[i].sex == 'm') { printTeacher(&teacher[i]); } } } void printFemaleTeacher(Teacher *teacher,int count) { for (int i = 0; i < count; i ++) { if (teacher[i].sex == 'f') { printTeacher(&teacher[i]); } } } <strong><span style="font-size:24px;">主函数的实现</span></strong> <pre name="code" class="cpp">// // main.m // Exame // // Created by lanou3g on 15-3-25. // Copyright (c) 2015年 lanou3g. All rights reserved. // #import <Foundation/Foundation.h> #import "Teacher.h" int main(int argc, const char * argv[]) { printf("输入1:实现按照姓名进行升序排列\n输入2:实现按照姓名进行降序排列\n输入3:实现按照员工编号进行升序排列\n输入4:实现按照员工编号进行降序排列\n输入5:实现按照评分进行升序排列\n输入6:实现按照评分进行降序排列\n输入7:实现输出所有的女老师\n输入8:实现输出所有的男老师\n"); printf("=====================\n"); printf("请输入实现功能对应的数字:\n"); Teacher teacher[4] = {{"zhangsan",'m',23,34,5.5},{"lishi",'f',45,56,3.5},{"wangwu",'m',22,12,1.3},{"songliu",'f',45,12,3.2}}; int n = 0; while (scanf("%d",&n)!=EOF) { if (n >= 1 && n <= 8) { switch (n) { case CompareNameByAscending: sortTeachers(teacher,4,compareNameAscending); printTeachers(teacher,4); break; case CompareNameByDescending: sortTeachers(teacher,4,compareNameDescending); printTeachers(teacher,4); break; case CompareNumberByAscending: sortTeachers(teacher,4,compareNumberAscending); printTeachers(teacher,4); break; case CompareNumberByDescending: sortTeachers(teacher,4, compareNumberDescending); printTeachers(teacher,4); break; case CompareScoreByAscending: sortTeachers(teacher,4, compareScoreAscending); printTeachers(teacher,4); break; case CompareScoreByDescending: sortTeachers(teacher,4, compareScoreDescending); printTeachers(teacher,4); break; case PrintFemaleTeacher: printFemaleTeacher(teacher,4); break; case PrintMaleTeacher : printMaleTeacher(teacher,4); break; default: break; } } else printf("请重新输入:\n"); } return 0; }
-
c++怎么把把排序后的结果保存在不同的文件中。_EXCEL按排名对数据自动排序
2021-01-15 17:24:26任务要求:部门每个人绩效考核评分后,表格根据分数,对所有员工进行自动排名并排序,不是显示名次,而是自动按名次重新排列员工顺序。说的多,不如看看动图化的要求吧,就像这样:看明白了么?其实一开始觉得这个...这是一个很有趣的案例。任务要求:部门每个人绩效考核评分后,表格根据分数,对所有员工进行自动排名并排序,不是显示名次,而是自动按名次重新排列员工顺序。说的多,不如看看动图化的要求吧,就像这样:看明白了么?其实一开始觉得这个任务是个悖论,一方面我算出来结果,然后根据结果又原位排列顺序,是不合逻辑的。不过我们可以换个思路,我们可以改为2张表,表1用来计算结果,表2接收表1的结果并自动排列,这样就打破了悖论。这段话没看懂也不要紧,文章看完再回来看这一段。第一步:完成表格版式,及表1数据录入
为演示方便,将表1设为静态表,实际工作中加公式就可以改造为动态的。表1的排名其实可以不设置,这里加上是为了看的清楚。将员工姓名复制粘贴到表2,并用VLOOKUP从表1取得分。
第二步:手动排序,并录制宏这步很关键。自动排列,首先想到这是代码干的,所以要用到宏或VBA。我们先告诉EXCEL要干什么,即录个片段,让EXCEL自动执行就好。点击录制宏,名字随意。然后选择“得分”和“员工姓名”列,记住这里一定不要反哦,因为我们是要按分数排序。然后点击“数据”选项卡——“降序”,再点击停止录制宏,可以查看代码。
至此,静态的排序操作已经完成了,我们加个排名吧。
第三步:让表格动起来这步思想是,每次我操作后,让EXCEL自动做一次自动排序工作,即调用一次“宏2”。点击“开发工具”选项卡——“Visual Basic”,就打开了VBE环境。双击左侧的Sheet1,然后右侧界面第一个下拉框选择“Worksheet”,第二个下拉框选择“SelectionChange”。然后在第一个SUB过程中写上“宏2”,关掉就好。其实前面步骤可以给“宏2”起个好点的名字,比如“自动排名排序”,这里引用的时候就很清楚。
下面就是验证操作结果的时候了!再看一遍动图:完成任务!注意保存文件!因为是有代码的,所以需要保存为启用宏的工作簿xlsm格式。你以为这就结束了??等等,发现排名有点问题。好几个并列分,排名怎么不一样?这里我们写个公式就好,E3=COUNTIF($G$3:$G$20,">"&G3)+1,在右侧得分已经排好序的情况下进行计算。公式具体什么意思呢?简单说,就是计算这个区域数字比G3大的次数,因为牛人7已经最高分了,所以COUNTIF的结果就是0,然后加个1,就是排名;同样啊,牛人9也是并列最高分,所以COUNTIF的结果也是0,然后加个1,就实现了并列第一的目的。再到牛人3,有2个分比他高,所以排名就是2+1=3。
保存文件,打完收工。学有用的知识,做有用的表
-
动态排序实例(函数回调)
2015-06-27 14:43:55定义一个Teacher结构体包括:姓名,性别,年龄,员工编号,评分 2.定义一个对结构体数组排序的函数,包括一个返回值为BOOl类型的回调函数,实现按照不同的条件对结构体成员排序 3.定义一个打印所有老师信息的函数 ...需求分析
1.定义一个Teacher结构体包括:姓名,性别,年龄,员工编号,评分
2.定义一个对结构体数组排序的函数,包括一个返回值为BOOl类型的回调函数,实现按照不同的条件对结构体成员排序
3.定义一个打印所有老师信息的函数
4.实现多个返回值为BOOL类型的函数,用来判断排序中的if交换变量条件
5.定义一个判断并打印所有男老师和女老师的函数
6.定义一个枚举类型,和控制台输入功能的数字相对应
7.使用while循环实现重新输入功能,若输入功能以外的数字,则提示重新输入函数声明
Teacher.h
//定义一个Teacher结构体 typedef struct teacher { char name[20]; char gender; int age; int number; float score; }Teacher; //声明一个枚举和用户从控制台输入的功能数字对应 enum FunctionName { CompareNameByAscending = 1, CompareNameByDescending, CompareNumberByAscending, CompareNumberByDescending, CompareScoreByAscending, CompareScoreByDescending, PrintMaleTeacher, PrintFemaleTeacher }; //打印一个Teacher的函数 void printTeacher(Teacher *teacher); //声明一个函数指针类型,判断条件真假 typedef BOOL(*CompareFunctionPointer)(Teacher teacher1, Teacher teacher2); //Teacher结构体数组排序函数 void sortTeachers(Teacher teacher[], int count, CompareFunctionPointer cfp); //打印Teach结构体数组中所有老师信息 void printTeachers(Teacher *teachers, int count); //按照名字升序排序 BOOL compareNameByAscending(Teacher teacher1, Teacher teacher2); //按照名字降序排序 BOOL compareNameByDescending(Teacher teacher1, Teacher teacher2); //按编号升序排序 BOOL compareNumberByAscending(Teacher teacher1, Teacher teacher2); //按编号降序排序 BOOL compareNumberByDescending(Teacher teacher1, Teacher teacher2); //按评分升序排序 BOOL compareScoreByAscending(Teacher teacher1, Teacher teacher2); //按评分降序排序 BOOL compareScoreByDescending(Teacher teacher1, Teacher teacher2); //输出全部男老师 void printMaleTeacher(Teacher *teachers, int count); //输出全部女老师 void printFemaleTeacher(Teacher *teachers, int count); //打印操作说明 void printInstructions(); //重命名输出男女老师函数指针 typedef void (*PrintByGender)(Teacher *teachers, int count);
函数实现
Teacher.m
//打印Teacher的函数 void printTeacher(Teacher *teacher) { printf("Name:%-20sGender:%-20cAge:%-20dNumber:%-20dScore:%-20f\n", teacher->name, teacher->gender, teacher->age, teacher->number, teacher->score); } //Teacher结构体数组排序函数 void sortTeachers(Teacher teacher[], int count, CompareFunctionPointer cfp) { for (int i = 0; i < count - 1; i++) { for (int j = 0; j < count - 1 - i; j++) { if (cfp(teacher[j], teacher[j + 1])) { Teacher temp = teacher[j]; teacher[j] = teacher[j + 1]; teacher[j + 1] = temp; } } } } //打印Teach结构体数组中所有老师信息 void printTeachers(Teacher *teachers, int count) { for (int i = 0; i < count; i++) { printf("Name:%-20sGender:%-20cAge:%-20dNumber:%-20dScore:%-20f\n", teachers[i].name, teachers[i].gender, teachers[i].age, teachers[i].number, teachers[i].score); } } //按照名字升序排序 BOOL compareNameByAscending(Teacher teacher1, Teacher teacher2) { if (strcmp(teacher1.name, teacher2.name) > 0) { return YES; } return NO; } //按照名字降序排序 BOOL compareNameByDescending(Teacher teacher1, Teacher teacher2) { if (strcmp(teacher1.name, teacher2.name) < 0) { return YES; } return NO; } //按编号升序排序 BOOL compareNumberByAscending(Teacher teacher1, Teacher teacher2) { if (teacher1.number > teacher2.number) { return YES; } return NO; } //按编号降序排序 BOOL compareNumberByDescending(Teacher teacher1, Teacher teacher2) { if (teacher1.number < teacher2.number) { return YES; } return NO; } //按评分升序排序 BOOL compareScoreByAscending(Teacher teacher1, Teacher teacher2) { if (teacher1.score > teacher2.score) { return YES; } return NO; } //按评分降序排序 BOOL compareScoreByDescending(Teacher teacher1, Teacher teacher2) { if (teacher1.score < teacher2.score) { return YES; } return NO; } //输出全部男老师 void printMaleTeacher(Teacher *teachers, int count) { for (int i = 0; i < count; i++) { if (teachers[i].gender == 'm') { printf("Name:%-20sGender:%-20cAge:%-20dNumber:%-20dScore:%-20f\n", teachers[i].name, teachers[i].gender, teachers[i].age, teachers[i].number, teachers[i].score); } } } //输出全部女老师 void printFemaleTeacher(Teacher *teachers, int count) { for (int i = 0; i < count; i++) { if (teachers[i].gender == 'f') { printf("Name:%-20sGender:%-20cAge:%-20dNumber:%-20dScore:%-20f\n", teachers[i].name, teachers[i].gender, teachers[i].age, teachers[i].number, teachers[i].score); } } } //声明一个枚举和用户从控制台输入的功能数字对应 typedef enum FunctionName List; //打印操作说明 void printInstructions() { printf("输入1:实现按照姓名进行升序排序\n"); printf("输入2:实现按照姓名进行降序排序\n"); printf("输入3:实现按照员工编号进行升序排序\n"); printf("输入4:实现按照员工编号进行降序排序\n"); printf("输入5:实现按照评分进行升序排序\n"); printf("输入6:实现按照评分进行降序排序\n"); printf("输入7:实现输出所有的男老师\n"); printf("输入8:实现输出所有的女老师\n"); printf("=================================\n"); printf("请输入实现功能对应的数字:"); }
函数调用
main.m
//创建Teacher类型的结构体数组 Teacher teachers[] = { {"CLS", 'f', 35, 120, 100.0}, {"XQC", 'f', 32, 100, 98.5}, {"CGX", 'm', 36, 110, 99.5}, {"XDL", 'f', 30, 90, 59.5}, {"ZSY", 'm', 24, 190, 60.0} }; int main(int argc, const char * argv[]) { //定义变量 CompareFunctionPointer function = NULL; int n = 0; BOOL isAgain = YES; int count = sizeof(teachers) / sizeof(teachers[0]); //输出用户操作说明 printInstructions(); while (isAgain) { function = NULL; scanf("%d", &n); switch (n) { case CompareNameByAscending: function = compareNameByAscending; break; case CompareNameByDescending: function = compareNameByDescending; break; case CompareNumberByAscending: function = compareNumberByAscending; break; case CompareNumberByDescending: function = compareNumberByDescending; break; case CompareScoreByAscending: function = compareScoreByAscending; break; case CompareScoreByDescending: function = compareScoreByDescending; break; case PrintFemaleTeacher: printFemaleTeacher(teachers, count); break; case PrintMaleTeacher: printMaleTeacher(teachers, count); break; default: { printf("对不起您输入的数字没有对应的函数,请重新输入:"); break; } } if (function != NULL) { sortTeachers(teachers, count, function); printTeachers(teachers, count); } } return 0; }
案例分析
博主手把手教你玩转回调函数
- 拿到一个案例,博主首先想到的是通过需求分析来设计一个程序的整体架构,尽可能将程序拆分为几个独立的模块,并提高程序的内聚性,减少程序的耦合性。接下来博主将通过对本案例尽可能详细的分析来说明这一点。
- 首先我们先放下回调函数不管,按照由整体到局部来对这一案例进行分析,题目要求是创建一个结构体数组并且按照一定的顺序输出,那我们就可以先声明一个结构体,并且写一个函数,用来输出结构体数组的每一个成员的变量。这里楼主使用了
typedef
对结构体重命名,不懂的童鞋自行脑补,内事问度娘。 - 第一步我们做完了,题目的要求是输出排序后的信息,我们可以写一个函数对数组进行排序。我们就先做一个按照评分对老湿们进行排序吧,之前都是老湿们给我们排序,现在换做我们给老湿们排序了,想想都暗爽那!闲话少叙,使用冒泡排序,对结构体数组按照比较部分交换整体的思想进行交换。
for (int i = 0; i < count - 1; i++) { for (int j = 0; j < count - 1 - i; j++) { if ((teacher[j].score - teacher[j + 1].score) > 0) { Teacher temp = teacher[j]; teacher[j] = teacher[j + 1]; teacher[j + 1] = temp; } } }
- 看到这里有人要说了,既然这都已经可以实现了,为什么还要使用函数回调来做?这个问题问得好!如果只按照一种规则对结构体数组排序,确实这样就已经实现了,但题目是要求按照几种方式对老湿门进行排序,这时使用函数回调就能体现其优越性了。通过分析题目,改变排序规则改变的就是冒泡排序中的if判断条件,那么如果我们能将判断条件作为一个参数传入函数的话,就可以通过在主调函数中改变排序的条件。
(teacher[j].score - teacher[j + 1].score) > 0
- 按照这个思路继续想,怎样能将一个判断条件作为函数的参数传入到该函数中那?博主告诉你,回调函数就可以实现这个神奇的功能。有的看客们又要问,为什么回调函数可以作为函数参数那?这个问题问得妙,首先函数是存储在内存中一块叫做代码区的空间的,函数就存储在这块区域,并且每个函数都有一个地址,也就是指针,如果能得到这个地址的话,就可以通过调用定义指针变量指向该地址并调用该函数。
函数名代表函数首地址,这例子代表定义一个返回值是int型并且有2个int型参数的函数指针p指向fun函数。int (*p)(int a, int b) = fun;
- 首先需要定义一个返回值是BOOL类型并且有两个Teacher结构体变量的函数
BOOL isTrue(Teacher teacher1, Teacher teacher2);
为了让函数指针作为参数,需要定义一个相同类型的函数指针类型typedef BOOL(*CompareFunctionPointer)(Teacher teacher1, Teacher teacher2);
看到了吧,有了两个结构体参数teacher1和teacher2就可以尽情的对老湿们进行各种方式的排序了。 - 接下来定义几个CompareFunctionPointer类型的函数用来实现不同的排序,博主写了按照6中方式排序,看客们可以再自行编写对年龄的排序函数。
void sortTeachers(Teacher teacher[], int count, CompareFunctionPointer cfp);
根据博主的提示,相信大家都能完成这样一个排序的函数,其中的cfp就是我们讲到的函数指针,在函数实现部分也会很简单,还记得上面提到的冒泡排序嘛,只要在if的括号中调用函数cfp(teacher[j], teacher[j + 1])
- 好了,万事俱备,接下来就要见证奇迹了,回到主调函数main.m中,先传入一个按照名字升序排序的函数并打印。注意函数指针参数,博主传入的是一个函数名字,而且没有括号和参数哦,原因上面已经说过了,函数名就是函数的地址,也叫做函数指针。输出结果就是按照名字升序排序的老湿信息。
int count = sizeof(teachers) / sizeof(teachers[0]); printInstructions(); sortTeachers(teachers, count, compareNameByAscending); printTeachers(teachers, count);
- 亲们看到这里不知道你们理解了没有,小编答应说要尽量详尽的带着大家学习函数回调,那就再带着大家来总结一下吧。
1.函数回调适用范围:这个东西是一个比普通函数更有逼格的函数,但亲们也要分析具体案例决定使用与否。一般情况下回调函数可以用来替换在函数中的表达式中,达到动态改变条件的作用。
2.函数回调的使用步骤:首先找到要替换的表达式,写出替换的函数并实现,并定义一个相同类型的函数指针类型,在原函数中加入函数指针类型参数,用回调函数替换原函数表达式部分。
博主讲到这里函数回调部分的内容就差不多结束了,本题目中要求输入功能对应数字并打印,那能不能通过输入一个字符串来调用对应的函数那?博主先卖个关子,看客们可以自行实现输入一个运算单词,例如:sum,max,minGB实现和函数的匹配,博主将在下一篇博客中和亲们分享:返回值是函数指针的函数。亲们记得关注哦。
-
怎么实现数据的实时更新_Excel表格使用函数制作在添加数据之后可以实时更新的排序...
2020-12-09 00:56:16在Excel表格中数据的排序是一个经常使用的功能。如果需要对实时更新的数据排序,你是否还在更新...现要求根据每个员工各个任务的总评分进行实时的升序排序(新增任务评分之后自动更新),用于统计工作难度和下次分配任... -
excel 按数据拆分 xlam_EXCEL按排名对数据自动排序
2020-11-24 15:56:18任务要求:部门每个人绩效考核评分后,表格根据分数,对所有员工进行自动排名并排序,不是显示名次,而是自动按名次重新排列员工顺序。说的多,不如看看动图化的要求吧,就像这样:看明白了么?其实一开始觉得这个... -
关于动态排序、结构体的使用
2015-04-22 16:46:00在Teacher.h中,定义一个Teacher结构体,成员变量包括:姓名、性别、年龄、员工编号、评分。2分 声明一个打印Teacher的函数,void printTeacher(Teacher * teacher)。1分 实现部分 4分 定义一个函数指针类型,... -
奥瑞文oTraining在线培训系统
2013-05-31 13:58:12支持主观题人工评分、客观题自动评分 支持报名考试、指定人员考试等考试方式 支持试题导入导出 支持试卷导出到Word 支持以整张试卷方式编辑试题 支持无限层次的机构分组 支持总公司-分公司-中心支公司等数据... -
单位活动现场管理系统 v1.0.rar
2019-07-09 21:02:27活动现场管理系统 v1.0 是一套活动现场电子网络管理系统,可在线进行 web 应用,无需客户端,可联网操作、可单机操作、可在投影大屏上适时显示,包含了一般活动出席人员签到、竞赛活动选手评分、电子摇号、选举唱票... -
EnableQ在线问卷调查引擎 V5.50.rar
2019-07-04 16:45:16EnableQ提供的问卷设计功能包含最为全面的20多种调查问卷问题题型,不仅包含基础的单选、多选、填空、多行填空问题题型,更囊括矩阵单选、评分、比重、排序、文件上传等高阶问题类型。多个不同或相同的问题题型可在... -
EnableQ v8.20免费版
2018-10-23 14:34:12EnableQ提供的问卷设计功能包含最为全面的20多种调查问卷问题题型,不仅包含基础的单选、多选、填空、多行填空问题题型,更囊括矩阵单选、评分、比重、排序、文件上传等高阶问题类型。多个不同或相同的问题题型可在... -
EnableQ在线问卷调查引擎系统_V8.20_免费版_Php 5.3x裸程序
2014-05-28 09:58:54EnableQ提供的问卷设计功能包含最为全面的20多种调查问卷问题题型,不仅包含基础的单选、多选、填空、多行填空问题题型,更囊括矩阵单选、评分、比重、排序、文件上传等高阶问题类型。多个不同或相同的问题题型可在... -
ElasticSearch视频-基础篇
2018-07-15 12:45:12比如入门级的电商网站商品管理案例,基于版本号进行乐观锁并发控制的实验,mget+bulk批量处理的实验,scoll滚动搜索大量数据的实验,scoll+bulk+alias零停机重建索引的实验,基于Java开发的员工管理案例,等等。... -
Excel百宝箱8.0
2011-06-07 21:32:17【根据工资计算钞票】:根据员工的工资计算需要多少张100元、50元......1元的钞票,可以批量计算。发现金工资的财务工作者必备 【隔行插入行】:对工作表隔行插入行,或者隔列插入列,其中行数可以自定义 【折分工作... -
Excel百宝箱 9.0 破解版 批量导入图片等200种功能
2013-05-11 22:46:24【根据工资计算钞票】根据员工的工资计算需要多少张100元、50元......1元的钞票,可以批量计算。发现金工资的财务工作者必备 【隔行插入行】对工作表隔行插入行,或者隔列插入列,其中行数可以自定义 【折分工作簿】... -
PHP和MySQL Web开发第4版pdf以及源码
2015-10-13 09:10:5816.3.3 对公司不满的员工 16.3.4 硬件被盗 16.3.5 我们自身 16.4 代码的安全性 16.4.1 过滤用户输入 16.4.2 转义输出 16.4.3 代码组织 16.4.4 代码自身的问题 16.4.5 文件系统因素 16.4.6 代码稳定性和缺陷 16.4.7 ... -
Excel百宝箱9.0无限制破解版.rar
2012-09-05 09:31:51【按颜色排序】:让Excel 2003也可以按背景色排序数据,2007或者2010用户不需要使用 【返回首页】:配合建立工作表目录工具使用,可以在任何工作表中瞬间返回第一个工作表 【工作簿标签】:将当前开启的工作簿创建... -
C#开发典型模块大全
2014-03-12 18:11:2211.2.7 对ListView控件中的项进行排序 267 11.3 设计过程 267 11.3.1 主窗体预览 267 11.3.2 批量复制、剪切文件 268 11.3.3 批量复制、剪切文件夹 270 11.3.4 批量重命名文件 271 11.3.5 批量删除文件... -
EXCEL集成工具箱完整版 (简体/繁体/英文多国语言版) V7.0
2010-08-13 10:31:10【取RMB张数】 根据员工的工资计算需要多少张100元、50元......1元的钞票,可以批量累计计算。发现金工资的财务工作者的必备工具之一。 【数字转英文】 将选中区域(默认)或已使用区域存储格的金额数字转换成英文... -
EXCEL集成工具箱V6.0
2010-09-11 01:44:37【取RMB张数】 根据员工的工资计算需要多少张100元、50元......1元的钞票,可以批量累计计算。发现金工资的财务工作者的必备工具之一。 【数字转英文】 将选中区域(默认)或已使用区域存储格的金额数字转换成英文... -
EXCEL集成工具箱V8.0 多国语言版(2003-2010通用)
2010-09-11 12:08:58【取RMB张数】 根据员工的工资计算需要多少张100元、50元......1元的钞票,可以批量累计计算。发现金工资的财务工作者的必备工具之一。 【数字转英文】 将选中区域(默认)或已使用区域存储格的金额数字转换成英文... -
EXCEL集成工具箱V8.0完整增强版(精简)
2010-09-23 16:58:17【取RMB张数】 根据员工的工资计算需要多少张100元、50元......1元的钞票,可以批量累计计算。发现金工资的财务工作者的必备工具之一。 【数字转英文】 将选中区域(默认)或已使用区域存储格的金额数字转换成英文... -
EXCEL集成工具箱V9.0 多国语言最终原版(2003-2010通用)
2011-01-07 20:40:25【取RMB张数】 根据员工的工资计算需要多少张100元、50元......1元的钞票,可以批量累计计算。发现金工资的财务工作者的必备工具之一。 【数字转英文】 将选中区域(默认)或已使用区域存储格的金额数字转换成英文...