指针的进阶(四)

简介: 指针的进阶(四)

七 指向函数指针数组的指针

指向函数指针数组的指针,是一个指针,指针指向存放函数指针的数组。

类型是:int (*(*)[5])(int, int)

1. #include <stdio.h>
2. int Add(int a, int b)
3. {
4.  return a + b;
5. }
6. int Sub(int a, int b)
7. {
8.  return a - b;
9. }
10. int Mul(int a, int b)
11. {
12.   return a * b;
13. }
14. int Div(int a, int b)
15. {
16.   return a / b;
17. }
18. int main()
19. {
20.   int (*pa)(int, int) = Add;函数指针
21.   int (*arr[4])(int, int) = { Add };函数指针数组,存放函数指针的数组
22.   int (*(*arr)[4])(int, int) = &arr;//指向函数指针数组的指针
23.   return 0;
24. }

八 回调函数

       回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。

代码展示:

1. #include <stdio.h>
2. void menu()
3. {
4.  printf("******1.Add    2.Sub*******\n");
5.  printf("******3.Mul    4.Div*******\n");
6.  printf("******0.exit        *******\n");
7.  printf("**********************8****\n");
8. }
9. int Add(int a, int b)
10. {
11.   return a + b;
12. }
13. int Sub(int a, int b)
14. {
15.   return a - b;
16. }
17. int Mul(int a, int b)
18. {
19.   return a * b;
20. }
21. int Div(int a, int b)
22. {
23.   return a / b;
24. }
25. void calc(int (*pf)(int, int))
26. {
27.   int a = 0;
28.   int b = 0;
29.   printf("请输入两个数字");
30.   scanf("%d %d", &a, &b);
31.   int ret = pf(a, b);
32.   printf("%d\n", ret);
33. }
34. int main()
35. {
36.   int input = 0;
37.   do
38.   {
39.     menu();
40.     printf("请选择:->");
41.     scanf("%d", &input);
42.     switch (input)
43.     {
44.     case 1:
45.       calc(Add);
46.       break;
47.     case 2:
48.       calc(Sub);
49.       break;
50.     case 3:
51.       calc(Mul);
52.       break;
53.     case 4:
54.       calc(Div);
55.       break;
56.     case 0:
57.       printf("退出计算机\n");
58.       break;
59.     default:
60.       printf("输入错误\n");
61.       break;
62.     }
63.   } while (input);
64.   return 0;
65. }

8.1 排序

   每一轮确定一个数字的位置,10个数字需要九轮才能排序完成。(冒泡排序,相邻两个两个的进行比较并交换位置)(在C语言初阶 数组知识点 里详细写了关于冒泡排序的知识点,友友们感兴趣的话可以看一下)

代码1展示:(整形冒泡排序)

1. #include <stdio.h>
2. void print(int arr[],int sz)
3. {
4.  int i = 0;
5.  for (i = 0; i < sz; i++)
6.  {
7.    printf("%d ", arr[i]);
8.  }
9. }
10. void buttle_sort(int arr[], int sz)
11. {
12.   int i = 0;
13.   for (i = 0; i < sz - 1; i++)//确定打印趟数
14.   {
15.     int j = 0;
16.     for (j = 0; j < sz - i - 1; j++)//确定每一趟需要比较的次数,每一趟会把最大的元素放在最后面
17.     {
18.       if (arr[j] > arr[j + 1])
19.       {
20.         int tmp = arr[j];
21.         arr[j] = arr[j + 1];
22.         arr[j + 1] = tmp;
23.       }
24.     }
25.   }
26. }
27. int main()
28. {
29.   int arr[] = { 1, 3, 6, 2, 0, 9, 4, 8, 5, 7 };
30.   int sz = sizeof(arr) / sizeof(arr[0]);
31.   buttle_sort(arr, sz);
32.   print(arr, sz);
33.   return 0;
34. }

qsort是一个库函数,快速排序的方法来实现的, 头文件是<stdlib.h>

qsort库函数,void qsort( void *base, size_t num, size_t width, int (__cdecl *compare )(const void *elem1, const void *elem2 ) );传入的参数,一个是指针,一个整形,一个整形一个函数指针,base 数组首元素(就是数组名),num数组里有多少个元素,width每个元素的大小(单位是字节),compare比较两个指针指向的元素,小于  输出小于0的元素,等与  输出0,大于  输出大于0的元素  排序任意类型

无具体类型的指针,void*作用是 :void*的指针变量可以存放任意类型的指针,void*的指针不能直接进行解引用操作(进行解引用要进行强制转换)*(*int)pa';void*也不能进行+-整数;

代码2展示:(各种类型的排序)(qsort)

排序的内容可以是整形数组、浮点型数组、字符数组,结构体数组

把代码1用qsort表示:

使用qsort 函数,需要写一个compare函数(注意,返回类型是数字)

1. #include <stdio.h>
2. #include <stdlib.h>
3. void print(int arr[],int sz)
4. {
5.  int i = 0;
6.  for (i = 0; i < sz; i++)
7.  {
8.    printf("%d ", arr[i]);
9.  }
10. }
11. //比较e1和e2指向的元素
12. int com_int(const void* e1, const void* e2)
13. {
14.   return *(int*)e1 - *(int*)e2;
15. }
16. int main()
17. {
18.   int arr[] = { 1, 3, 6, 2, 0, 9, 4, 8, 5, 7 };
19.   int sz = sizeof(arr) / sizeof(arr[0]);
20.   qsort(arr, sz, sizeof(arr[0]), com_int);
21.   print(arr, sz);
22.   return 0;
23. }

比较结构体 score

1. #include <stdio.h>
2. #include <stdlib.h>
3. struct stu
4. {
5.  char name[10];
6.  int age;
7.  float score;
8. };
9. 
10. int cmp_stu_by_score(const void* e1, const void* e2)
11. {
12.   if (((struct stu*)e1)->score > ((struct stu*)e2)->score)//浮点数不能减,因为返回的是int
13.   {
14.     return 1;
15.   }
16.   else if (((struct stu*)e1)->score < ((struct stu*)e2)->score)
17.   {
18.     return -1;
19.   }
20.   else
21.   {
22.     return 0;
23.   }
24. }
25. 
26. void print_stu(struct stu arr[], int sz)
27. {
28.   int i = 0;
29.   for (i = 0; i < sz; i++)
30.   {
31.     printf("%s %d %f\n", arr[i].name, arr[i].age, arr[i].score);
32.   }
33.   printf("\n");
34. }
35. 
36. int main()
37. {
38.   struct stu arr[] = { {"zhangsan", 20, 87.5f},{"lisi", 22, 99.0f},{"wangwu", 10, 68.5f} };//按照成绩来排序
39.   int sz = sizeof(arr) / sizeof(arr[0]);
40.   qsort(arr, sz, sizeof(arr[0]), cmp_stu_by_score);
41.   print_stu(arr, sz);
42.   return 0;
43. }

比较结构体 age

1. #include <stdio.h>
2. #include <stdlib.h>
3. struct stu
4. {
5.  char name[10];
6.  int age;
7.  float score;
8. };
9. 
10. int cmp_stu_by_age(const void* e1, const void* e2)
11. {
12.   return ((struct stu*)e1)->age - ((struct stu*)e2)->age;
13. }
14. 
15. void print_stu(struct stu arr[], int sz)
16. {
17.   int i = 0;
18.   for (i = 0; i < sz; i++)
19.   {
20.     printf("%s %d %f\n", arr[i].name, arr[i].age, arr[i].score);
21.   }
22.   printf("\n");
23. }
24. 
25. int main()
26. {
27.   struct stu arr[] = { {"zhangsan", 20, 87.5f},{"lisi", 22, 99.0f},{"wangwu", 10, 68.5f} };//按照成绩来排序
28.   int sz = sizeof(arr) / sizeof(arr[0]);
29.   qsort(arr, sz, sizeof(arr[0]), cmp_stu_by_age);
30.   print_stu(arr, sz);
31.   return 0;
32. }

比较结构体 name

1. #include <stdio.h>
2. #include <stdlib.h>
3. struct stu
4. {
5.  char name[10];
6.  int age;
7.  float score;
8. };
9. 
10. int cmp_stu_by_name(const void* e1, const void* e2)
11. {
12.   return strcmp(((struct stu*)e1)->name, ((struct stu*)e2)->name);
13. }
14. 
15. void print_stu(struct stu arr[], int sz)
16. {
17.   int i = 0;
18.   for (i = 0; i < sz; i++)
19.   {
20.     printf("%s %d %f\n", arr[i].name, arr[i].age, arr[i].score);
21.   }
22.   printf("\n");
23. }
24. 
25. int main()
26. {
27.   struct stu arr[] = { {"zhangsan", 20, 87.5f},{"lisi", 22, 99.0f},{"wangwu", 10, 68.5f} };//按照成绩来排序
28.   int sz = sizeof(arr) / sizeof(arr[0]);
29.   //qsort(arr, sz, sizeof(arr[0]), cmp_stu_by_score);
30.   //qsort(arr, sz, sizeof(arr[0]), cmp_stu_by_age);
31.   qsort(arr, sz, sizeof(arr[0]), cmp_stu_by_name);
32.   print_stu(arr, sz);
33.   return 0;
34. }

strcmp(s1, s2),比较字符串的大小,两个字符串从左向右逐个字符相比(按ASCII的值大小相比),直到某一个字符不相等或者其中一个字符比较完毕才停止比较,字符的比较为ASCII码的比较(若字符串1大于字符串2,返回结果大于0,若字符串1小于字符串2,返回结果小于0,若字符串1等于字符串2,返回结果等于0.)

strcmp的头文件是<string.h>

用 冒泡排序 实现qsort()的功能

1. #include <stdio.h>
2. void print(int arr[], int sz)
3. {
4.  int i = 0;
5.  for (i = 0; i < sz; i++)
6.  {
7.    printf("%d ", arr[i]);
8.  }
9. }
10. 
11. void swap(char* buf1, char* buf2, int width)
12. {
13.   int i = 0;
14.   for (i = 0; i < width; i++)
15.   {
16.     char tmp = *buf1;
17.     *buf1 = *buf2;
18.     *buf2 = tmp;
19.     buf1++;
20.     buf2++;
21.   }
22. }
23. 
24. void bubble_sort(void* base, int sz, int width, int (*cmp)(const void* e1, const void* e2))
25. {
26.   int i = 0;
27.   int j = 0;
28.   for (i = 0; i < sz; i++)
29.   {
30.     for (j = 0; j < sz - 1 - i; j++)
31.     {
32.       if (cmp((char*)base + j * width, (char*)base + (j + 1) * width) > 0)
33.       {
34.         swap((char*)base + j * width, (char*)base + (j + 1) * width, width);//一个字节一个字节的交换
35.       }
36.     }
37.   }
38. }
39. 
40. int com_int(const void* e1, const void* e2)
41. {
42.   return *(int*)e1 - *(int*)e2;
43. }
44. int main()
45. {
46.   int arr[] = { 1, 3, 6, 2, 0, 9, 4, 8, 5, 7 };
47.   int sz = sizeof(arr) / sizeof(arr[0]);
48.   bubble_sort(arr, sz, sizeof(arr[0]), com_int);
49.   print(arr, sz);
50.   return 0;
51. }

排序的作者:不知道排序的类型

排序的使用者:知道待排序的类型,以及每种类型的排序方法。

相关文章
|
5月前
|
C语言
指针进阶(C语言终)
指针进阶(C语言终)
|
5月前
|
机器学习/深度学习 搜索推荐 算法
【再识C进阶2(下)】详细介绍指针的进阶——利用冒泡排序算法模拟实现qsort函数,以及一下习题和指针笔试题
【再识C进阶2(下)】详细介绍指针的进阶——利用冒泡排序算法模拟实现qsort函数,以及一下习题和指针笔试题
|
5月前
|
C语言
指针进阶(回调函数)(C语言)
指针进阶(回调函数)(C语言)
|
5月前
|
存储 C语言 C++
指针进阶(函数指针)(C语言)
指针进阶(函数指针)(C语言)
|
5月前
|
编译器 C语言
指针进阶(数组指针 )(C语言)
指针进阶(数组指针 )(C语言)
|
5月前
|
搜索推荐
指针进阶(2)
指针进阶(2)
47 4
|
5月前
指针进阶(3)
指针进阶(3)
37 1
|
5月前
|
C++
指针进阶(1)
指针进阶(1)
42 1
|
5月前
|
存储 安全 编译器
C++进阶之路:何为引用、内联函数、auto与指针空值nullptr关键字
C++进阶之路:何为引用、内联函数、auto与指针空值nullptr关键字
41 2
|
5月前
|
Java 程序员 Linux
探索C语言宝库:从基础到进阶的干货知识(类型变量+条件循环+函数模块+指针+内存+文件)
探索C语言宝库:从基础到进阶的干货知识(类型变量+条件循环+函数模块+指针+内存+文件)
45 0