做一个网站需要多少费用阿里去可以做几个网站

当前位置: 首页 > news >正文

做一个网站需要多少费用,阿里去可以做几个网站,电子商务网站建设策划书的流程,外网wordpress好慢目录 1、函数指针数组 1.1、函数指针数组是什么#xff1f; 1.2、函数指针数组的用途#xff1a;转移表 2、扩展#xff1a;指向函数指针的数组的指针 3、回调函数 3.1、回调函数介绍 3.2、回调函数的案例#xff1a;qsort函数 3.2.1、回顾冒泡排序 3.2.1、什么是qso…目录 1、函数指针数组 1.1、函数指针数组是什么 1.2、函数指针数组的用途转移表 2、扩展指向函数指针的数组的指针 3、回调函数 3.1、回调函数介绍 3.2、回调函数的案例qsort函数 3.2.1、回顾冒泡排序 3.2.1、什么是qsort函数 1、函数指针数组 1.1、函数指针数组是什么 函数指针数组是什么首先主语是数组数组是一个存放相同类型数据的存储空间。那我们已经学习了指针数组比如 char* arr[5]  ———— 字符指针数组它是一个数组存放的是字符指针。 int* arr[5]     ———— 整型指针数组它是一个数组存放的是整型指针。 假设有这么一个使用场景我需要将几个函数的地址存放到一个数组中那应该怎么存下面给大家介绍一下函数指针数组 int Add(int x, int y) {return x y; }int Sub(int x, int y) {return x - y; }int main() {int (*pf1)(int, int) Add; //pf1和pf2是函数指针int (*pf2)(int, int) Sub;//数组中存放类型相同的多个数组int (*pfArr[4])(int, int) { Add,Sub }; //pfArr就是函数指针数组return 0; } 函数指针数组的写法与函数指针非常相似只需要在名字后加个方括号[ ]就可以了。 注意因为数组是一个存放相同类型数据的存储空间所以函数指针数组只能够存放返回类型和参数类型都一致的函数的函数地址。 1.2、函数指针数组的用途转移表 用C语言实现一个计算器功能加减乘除 int add(int a, int b) {return a b; } int sub(int a, int b) {return a - b; } int mul(int a, int b) {return a * b; } int div(int a, int b) {return a / b; }void menu() {printf(****************************\n);printf(*** 1.add 2.sub **\n);printf(*** 3.mul 4.div **\n);printf(*** 0.exit **\n);printf(**************************\n); }int main() {int input 0;int a 0;int b 0;int ret 0;do{menu();printf(请选择:);scanf(%d, input);switch (input){case 1:printf(请输入2个操作数:);scanf(%d %d, a, b);ret add(a, b);printf(%d\n, ret);break;case 2:printf(请输入2个操作数:);scanf(%d %d, a, b);ret sub(a, b);printf(%d\n, ret);break;case 3:printf(请输入2个操作数:);scanf(%d %d, a, b);ret mul(a, b);printf(%d\n, ret);break;case 4:printf(请输入2个操作数:);scanf(%d %d, a, b);ret div(a, b);printf(%d\n, ret);break;case 0:printf(退出计算器\n);break;default:printf(选择错误重新选择\n);break;}} while (input);return 0; } 上面的代码虽然能实现一个计算器功能但是可以发现这个代码特别地冗余重复的部分非常多并且如果需要添加多一个功能是又需要再添加多一个case导致代码越来越长重复部分也越来越多这是非常不好的代码习惯那有什么办法能够解决呢     其实我们通过观察可以发现这些函数有一些特点就是除了函数名不同之外返回类型以及参数类型都是一致的。     既然除了函数名不同之外其余都相同那么是否就可以使用函数指针数组来改造一下代码 int add(int a, int b) {return a b; } int sub(int a, int b) {return a - b; } int mul(int a, int b) {return a * b; } int div(int a, int b) {return a / b; }void menu() {printf(**************************\n);printf(*** 1.add 2.sub **\n);printf(*** 3.mul 4.div **\n);printf(*** 0.exit **\n);printf(**************************\n); }int main() {int input 0;int a 0;int b 0;int ret 0;do{menu();printf(请选择:);scanf(%d, input);//创建一个函数指针数组int (pfArr[])(int, int) { NULL,add,sub,mul,div };//为了使数组下标与菜单序号对应起来在0下标处放置一个NULLif (input 0){printf(退出计算器\n);}else if (input 1 input 4){printf(请输入2个操作数:);scanf(%d %d, a, b);ret pfArrinput; //下标访问数组中的函数并调用printf(ret %d\n, ret);}else{printf(选择错误重新选择\n);}} while (input);return 0; } 可以看到使用函数指针数组一样可以完成。未来如果还需要添加其他功能时只需要在菜单发生变化然后写出实现功能的函数再将函数放入函数指针数组当中就可以了。而我们把这种场景下使用的函数指针数组就叫做转移表。 这也就是说使用函数指针数组不仅大大提高了代码的质量而且大大降低了维护成本。 2、扩展指向函数指针的数组的指针 指向函数指针数组的指针是一个指针指针指向一个数组 数组的元素都是函数指针 。 如何定义 void test(const char str) {printf(%s\n, str); } int main() {//函数指针pfunvoid (pfun)(const char) test;//函数指针的数组pfunArrvoid (pfunArr[5])(const char str);pfunArr[0] test;//指向函数指针数组pfunArr的指针ppfunArrvoid (*(ppfunArr)[5])(const char) pfunArr;return 0; } void (*(ppfunArr)[5])(const char) void (*(ppfunArr)[5])(const char)ppfunArr首先与结合所以它是一个指针。 void ((ppfunArr)[5])(const char)再和[5]结合表示指针指向一个大小为5的数组每个数组存放的类型是函数指针void ()(const char)。 当然这里讲到的函数指针数组指针已经是很深入的内容了使用场景非常少只作为扩展了解即可看不懂也不需要太过于担心。 3、回调函数 3.1、回调函数介绍 回调函数在C语言中的地位非常高非常重要。回调函数是依赖函数指针的有了函数指针才能实现回调函数。在前面计算器功能使用函数指针数组调用加减乘除函数的时候加减乘除函数就被成为回调函数。 回调函数就是一个通过函数指针调用的函数。如果你把函数的指针地址作为参数传递给另一个函数当这个指针被用来调用其所指向的函数时我们就说这是回调函数。回调函数不是由该函数的实现方直接调用而是在特定的事件或条件发生时由另外的一方调用的用于对该事件或条件进行响应。 再次用计算器功能作为例子讲解 观察代码可以发现 只有调用函数部分不一样那么能不能定义一个cacl()函数通过将加减乘除函数作为参数传入到calc函数中达到在calc函数中调用加减乘除函数 按照这个思路修改后的代码 int add(int a, int b) {return a b; } int sub(int a, int b) {return a - b; } int mul(int a, int b) {return a * b; } int div(int a, int b) {return a / b; }void menu() {printf(**************************\n);printf(*** 1.add 2.sub **\n);printf(*** 3.mul 4.div **\n);printf(*** 0.exit **\n);printf(****************************\n); }void calc(int(*pf)(int, int)) {int a 0;int b 0;int ret 0;printf(请输入2个操作数:);scanf(%d %d, a, b);ret pf(a, b);printf(%d\n, ret); }int main() {int input 0;do{menu();printf(请选择:);scanf(%d, input);switch (input){case 1:calc(add);break;case 2:calc(sub);break;case 3:calc(mul);break;case 4:calc(div);break;case 0:printf(退出计算器\n);break;default:printf(选择错误重新选择\n);break;}} while (input);return 0; } 【图解】 可以把calc函数理解为中转站给我参数传递什么函数地址我就调用什么函数。 提示在往期博客中我有得出过一个结论函数指针在调用所指向函数时可以不写*直接和函数名一样调用函数而*号在这里其实就只是一个摆设同样是为了照顾初学者的使用习惯所以才会导致当加了很多*号去解引用时得出来的结果依然是正确的结果。 即(pf)(a,b)等价于pf(a,b)。 如果想要了解更透彻可以前往我的往期博客阅读函数指针部分。链接点击前往 3.2、回调函数的案例qsort函数 3.2.1、回顾冒泡排序 为了方便对比我们先复习一下冒泡排序 //冒泡排序算法 //给一组整型数据然后使用冒泡排序对数据进行升序排序。void bubble_sort(int arr[], int sz) {//趟数int i 0;for ( i 0; i sz - 1; i){//每一趟冒泡排序的过程int j 0;for ( j 0; j sz - 1 - i; j){if (arr[j] arr[j 1]){int tmp arr[j];arr[j] arr[j 1];arr[j 1] tmp;}}} }int main() {int arr[] { 10,9,8,7,6,5,4,3,2,1 };int sz sizeof(arr) / sizeof(arr[0]);bubble_sort(arr, sz);int i 0;for ( i 0; i sz; i){printf(%d , arr[i]);}return 0; } 上面就是冒泡排序的实现但是可以看到这个冒泡排序其实是有缺陷的它的参数是int类型限制了它只能够排序整型数据而这里即将讲到的qsort函数就是一个可以用来排序任意类型数据的函数。 3.2.1、什么是qsort函数 qsort是一个库函数底层使用的是快速排序的方式对数据进行排序。头文件stdlib.h 这个函数可以直接使用用来排序任意类型的数据。 当然除了快速排序还有很多排序例如冒泡排序、选择排序希尔排序归并排序等等 qsort函数定义原型 void qsort (void base, size_t num, size_t size, int (compar)(const void,const void)); void base待排序数组的第一个元素的地址size_t num待排序数组的元素个数size_t size以字节为单位待排序数组中一个元素的大小。int (compar)(const void,const void)函数指针指向一个函数用来比较两个元素由用户自行创建并封装。 比较函数的形参中为什么用的是void void* 是无具体类型的指针不能进行解引用操作符也不能进行-整数的操作它是用来存放任意类型数据的地址可以理解为垃圾桶什么都能装当需要用时再强制类型转换为需要的类型。只有void*被允许存放任意类型数据的地址如果是其他类型的指针编译器会报错。正是因为定义qsort函数时用的是voidqsort函数才可以排序任意类型的数据。 使用qsort函数最重要的就是最后一个参数这个参数决定了qsort函数比较两个元素的规则。这里先写一个用于排序整型数据的比较函数cmp_int int cmp_int(const void e1, const void* e2) {return (int)e1 - (int)e2; } 比较函数的要求 当p1指向的元素大于p2指向的元素时返回大于0的数当p1指向的元素等于p2指向的元素时返回0当p1指向的元素小于p2指向的元素时返回小于0的数 【完整代码】 使用qsort函数排序整型数据。 int cmp_int(const void* e1, const void* e2) {return (int)e1 - (int)e2; }int main() {int arr[] { 10,9,8,7,6,5,4,3,2,1 };int sz sizeof(arr) / sizeof(arr[0]);qsort(arr, sz, sizeof(arr[0]), cmp_int);int i 0;for ( i 0; i sz; i){printf(%d , arr[i]);}return 0; } 同理qsort函数排序结构体类型数据下面例子以结构体中的年龄来排序 struct Stu {char name[20];int age; };int cmp_struct(const void* e1, const void* e2) {return ((struct Stu)e1)-age - ((struct Stu)e2)-age; }int main() {struct Stu arr[] { {zhangsan,20},{lisi,21},{wangwu,22} };int sz sizeof(arr) / sizeof(arr[0]);qsort(arr, sz, sizeof(arr[0]), cmp_struct);return 0; } 【运行结果】 可以发现确实是完成了按年龄排序。 如果觉得作者写的不错求给博主一个大大的点赞支持一下你们的支持是我更新的最大动力 如果觉得作者写的不错求给博主一个大大的点赞支持一下你们的支持是我更新的最大动力 如果觉得作者写的不错求给博主一个大大的点赞支持一下你们的支持是我更新的最大动力