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

综合服务门户网站建设环县网站怎么做

综合服务门户网站建设,环县网站怎么做,软件推广平台,网站开发基础与提高Hi~#xff01;这里是奋斗的小羊#xff0c;很荣幸各位能阅读我的文章#xff0c;诚请评论指点#xff0c;关注收藏#xff0c;欢迎欢迎~~ #x1f4a5;个人主页#xff1a;小羊在奋斗 #x1f4a5;所属专栏#xff1a;C语言 本系列文章为个人学习笔记#x…                   Hi~这里是奋斗的小羊很荣幸各位能阅读我的文章诚请评论指点关注收藏欢迎欢迎~~                                      个人主页小羊在奋斗                                 所属专栏C语言    本系列文章为个人学习笔记在这里撰写成文一为巩固知识二为同样是初学者的学友展示一些我的学习过程及心得。文笔、排版拙劣望见谅。 1、qsort 使用举例 1.1qsort 是什么 1.2使用 qsort 函数排序整型数据 1.3使用 qsort 函数排序结构数据 2、qsort 函数的模拟实现 本节内容较多如有需要请收藏阅读。 1、qsort 使用举例 1.1qsort 是什么 qsort 是C语言中的一个库函数使用 qsort 库函数需要包含头文件 stdlib.h。这个函数是用来对任意数据类型的数据排序的。 我们之前也写过一个排序函数 //冒泡排序 — 升序 #include stdio.hvoid bubble_sort(int arr[], int m) {int i 0;for (i 0; i m - 1; i){int j 0;int flag 1;for (j 0; j m - 1 - i; j){if (arr[j] arr[j 1]){flag 0;int tmp arr[j];arr[j] arr[j 1];arr[j 1] tmp;}}if (1 flag){break;}} }int main() {int arr[100] { 0 };int n 0;do{scanf(%d, arr[n]);} while (arr[n - 1] ! -1);//以-1为结束标志bubble_sort(arr, --n);int i 0;for (i 0; i n; i){printf(%d , arr[i]);}return 0; } 上面是我们之前写过的一个冒泡排序它可以实现排序但它排序的对象只能是整型所以它的功能太单一。而 qsort 函数可以实现对任意类型的数据进行排序它不仅可以完成上面我们写的冒泡排序的功能还能对字符型、字符串型、实型、结构体类型等排序我们只要需要提供一个比较函数就行。  我们先来了解一下 qsort 函数的用法 以下图片均截自C 标准库头文件 - cppreference.com 更多详细内容请跳转查看。 上图为 qsort 函数的参数个数、参数类型、函数返回值类型及其功能的简单介绍。 上图为 qsort 函数参数的详细介绍。其中最后一个参数是一种函数指针类型我们需要自定义一个比较函数将地址传给这个函数指针变量再通过这个指针调用函数这个函数就是一个回调函数。 上图为 qsort 函数的使用实例。 为什么要有 qsort 函数呢它能帮我们做什么在回答这个问题之前让我们的目光再回到上节我们写的冒泡排序中先思考另一个问题为什么我们写的冒泡排序只能排整形数据呢 原因就在上面的红色方框中。因为如果我们想排字符串的话字符串不能用 号比较大小应该用字符串比较函数 strcmp 简单地修改后我们发现其他的地方基本不需要再做修改。所以我们只需要改变上面红色方框中的代码就可以实现对字符串排序了。 也就是说排序的基本框架不变变的只是数据的比较部分那我们把基本框架封装成一个函数而用于数据的比较部分我们再写一个函数这样的话我们想排序什么类型只需要写一个相应类型的比较函数再将这个函数传给事先就分装好的框架函数不就实现了想排序什么类型的数据就排序什么类型的数据吗 很明显我们所说的将基本框架分装一个函数就是我们要学习的 qsort 函数而需要我们自己写的比较函数它的地址就作为 qsort 函数的第四个参数。 qsort 函数就像一个半自动的机器想使用它必须要有人操作而且这个人必须事先明确自己想要得到什么需要给 qsort 函数传递一个什么东西它才能给出我们想要的结果。 1.2使用 qsort 函数排序整型数据  通过上面的了解接下来我们就来模仿 qsort 函数的使用示例写一个排序整型的小程序 #include stdio.h #include stdlib.hvoid cmp_int(const void* a, const void* b) {if (*(int*)a *(int*)b){return 1;}else if (*(int*)a *(int*)b){return -1;}else{return 0;} }void print(const void* pa, int sz) {int i 0;for (i 0; i sz; i){printf(%d , *((int *)pa i));} }void text() {int arr[] { 5,3,2,7,8,1,0,4,9,6 };int sz sizeof(arr) / sizeof(arr[0]);qsort(arr, sz, sizeof(arr[0]), cmp_int);print(arr, sz); }int main() {text();return 0; } 上面的代码中有一些细节的地方比如 指针变量a和b的类型都是 void * 类型而我们在之前的文章中说过 void * 类型的指针是不能直接进行解引用的。由于上面的程序是排序整型数据所以我们需要将 void * 类型的指针变量a和b强转为 int * 类型再解引用。 在 C语言指针2 中我们说过这么两段话 虽然void *类型的指针不能直接进行解引用操作也不能 - 整数的操作 但是当我们不知道别人给我们传的地址是什么类型的时候我们就可以放心地去用void *来接收这就是它的作用。 一般void *类型的指针是使用在函数参数的部分用来接收不同类型数据的地址这样的设计可以实现泛型编程的效果使得一个函数来处理多种类型的数据。在后面的文章中会深入探讨。  相信我们现在已经明白了其中的含义。正是因为 void * 类型的特殊qsort 函数才得以对任意数据类型的数据进行排序。  上面函数的功能只是打印出排序好的整型数据 因此并不希望数据被改变所以我们可以用 const 修饰指针变量增强数据的健壮性防止我们不小心通过指针间接地改变了数据。 1.3使用 qsort 函数排序结构数据 为了证明 qsort 函数确实可以对任意类型的数据排序我们再来用 qsort 函数排序结构型数据 #include stdio.h #include stdlib.h #include string.hstruct people {char name[20];int age; };void cmp_struct_name(const void* a, const void* b) {return strcmp((*(struct people*)a).name, (*(struct people*)b).name); }void print_struct(const struct people* p, int sz) {int i 0;for (i 0; i sz; i){printf(%s , (*(p i)).name);} }void text1()//排序结构体数据类型的数据 {struct people p[] { { xiaoshuai, 25}, { xiaomei, 24 }, { xiaochou, 23 } };int sz sizeof(p) / sizeof(p[0]);qsort(p, sz, sizeof(p[0]), cmp_struct_name);print_struct(p, sz); }int main() {text1();return 0; } 上面是结构体成员——名字的排序其中也有几处细节需要注意 值得一说的是strcmp 函数的返回值规则是当第一个字符串大于第二个字符串时返回一个正数小于时返回一个负数相等时则返回0这与 qsort 函数是一致的所以这里没有使用 if—else 分支来判断而是直接return了strcmp函数的返回值。 同样的道理我们上面写过的排序整型数据的这部分代码也是可以写成下面这样的这样写更加简单高效 但是这样写是有一点风险的虽然这个风险微乎其微但还是值得说一下。其实细心的朋友已经知道了因为我们之前给出的截图中已经有两行大字明确说明了这种写法的风险并且推荐了更加科学的写法。 虽然第二种写法在现实中发生错误的概率很小很小但我们不能因为如此就放肆地使用这种写法最后养成一种坏习惯。作为一名技术人员应当时刻保持严谨、科学、负责任的工作态度这样才能写出高质量且万无一失的代码。 我们下面还要写一个结构体成员——年龄的排序但是在写这个代码之前我们先来补充一个关于结构体成员访问、之前欠下的一点内容。 结构体成员访问有两种方法一种是我们用过的 . 结构体成员访问操作符还有一种就 是 “-” 结构体成员访问操作符。它们两个的使用方法是 下面就来用结构体成员访问操作符 “ - ” 来实现结构体成员——年龄的排序 #include stdio.h #include stdlib.hstruct people {char name[20];int age; };void cmp_struct_age(const void* a, const void* b) {int arg1 ((struct people*)a)-age;int arg2 ((struct people*)b)-age;return (arg1 arg2) - (arg1 arg2); }void print_struct(const struct people* p, int sz) {int i 0;for (i 0; i sz; i){printf(%d , (*(p i)).age);} }void text2()//排序结构体数据类型的数据 {struct people p[] { { xiaoshuai, 25}, { xiaomei, 24 }, { xiaochou, 23 } };int sz sizeof(p) / sizeof(p[0]);qsort(p, sz, sizeof(p[0]), cmp_struct_age);print_struct(p, sz); }int main() {//text1();text2();return 0; } 而上面的方法就不需要对结构体指针变量a和b进行解引用操作了。  说到这里我来对 qsort 函数做一个简单的总结 1qsort 函数是一个库函数使用需要包含头文件 stdlib.h 2qsort 函数使用的排序算法为快速排序并且默认排升序 3qsort 函数可以实现对任意数据类型的数据排序但只是一个 “半成品” 需要我们自己写一个某种数据类型的比较函数 再通过函数指针调用 4qsort 函数能实现的关键就是 void * 类型正是因为它能接收任意类型的指针而实现了泛型编程的效果。 qsort 函数默认排升序那能不能想办法让它排降序呢其实实现起来很简单比如下面的这个代码我们只需要把a和b的值交换就可以实现降序了。 2、qsort 函数的模拟实现 我们是否可以将 bubble_sort 函数改造一下让它就像 qsort 函数一样可以实现对任意数据类型的数据排序呢其实是可以的。既然我们已经搞清楚了 qsort 函数的实现逻辑那就可以仿照 qsort 函数来改造我们的冒泡排序使它也能完成对任意类型的数据排序。 首先我们可以将自己的意识分为两个一个是小帅另一个是小美。小帅现在需要写一个 bubble_sort 函数这个函数可以实现对任意类型的数据排序默认排升序。虽然小帅不知道小美要用他写的这个函数排什么类型的数据但他可以定一个规则告诉小美她想使用这个函数的话需要做些什么。 现在我们将意识转换为小帅。我要创建一个可以对任意类型的数据排序的函数起个名字叫bubble_sort 函数不需要返回值。第一个参数需要接收小美传过来的数组首元素的地址但我不知道这个元素是什么类型所以只能定义为 void * 类型有了数组首元素的地址我还需要知道数组内元素的个数所以第二个参数要接收数组内元素的个数我还需要知道一个元素占多少个字节因为我没法仅通过首元素的地址和元素的个数来找到其他的元素最后还需要一个参数来接收小美传过来的比较函数的地址这个比较函数需要小美自己写并且这个比较函数的规则是当前一个元素大于后一个元素时返回一个正值小于返回一个负值等于则返回0。 梳理清楚后我就可以写出下面函数的主体部分用到的排序算法是冒泡排序  void bubble_sort(void *pa, size_t sz, size_t width, int (*cmp)(const void *a, const void *b)) {int i 0;for (i 0; i sz - 1; i){int j 0;int flag 1;for (j 0; j sz - 1 - i; j){//判断大小}if (1 flag){break;}} } 接下来我需要调用小美写的比较函数并判断其返回值当返回值大于0时我要交换这两个比较的值的位置。但是由于我并不知道小美要排什么类型的数据所以我在调用小美的比较函数时怎样传参就是一个问题。 我现在知道首元素的地址还知道一个元素的大小宽度那我想要访问其他元素的时候就可以先将这个元素强转为最小类型也就是 char * 类型的指针再给这个元素加上n个元素的宽度就可以实现访问每个元素的地址了。那我就可以写出下面的代码 void bubble_sort(void *pa, size_t sz, size_t width, int (*cmp)(const void *a, const void *b)) {int i 0;for (i 0; i sz - 1; i){int j 0;int flag 1;for (j 0; j sz - 1 - i; j){//判断大小if (cmp((char*)pa j * width, (char*)pa (j 1) * width) 0){//交换两个值的位置}}if (1 flag){break;}} } 如果这个回调函数的返回值大于0我就要交换这两个指针地址指向的数据的位置那我再写一个交换函数来实现交换操作。想要交换就必须对指针进行解引用解引用的前提又必须对 void * 类型的指针转换类型但是在不知道类型的情况下很明显又是一个棘手的问题。 虽然我不知道指针的类型但我知道元素的大小类似于上面指针访问的思想我可以一个字节一个字节的交换因为无论是什么类型它的大小都大于或等于一个字节那对于n个字节大小的元素我就交换n次很明显这个n就是我们知道的元素的大小宽度。那我就可以写出下面的代码 void swap(char* buf1, char* buf2, size_t width) {int i 0;for (i 0; i width; i){char tmp *buf1;*buf1 *buf2;*buf2 tmp;buf1;buf2;} }void bubble_sort(void *pa, size_t sz, size_t width, int (*cmp)(const void *a, const void *b)) {int i 0;for (i 0; i sz - 1; i){int j 0;int flag 1;for (j 0; j sz - 1 - i; j){//判断大小if (cmp((char*)pa j * width, (char*)pa (j 1) * width) 0){//交换两个值的位置flag 0;swap((char*)pa j * width, (char*)pa (j 1) * width, width);}}if (1 flag){break;}} } 到这里这个函数我已经基本写好了最后再写一个打印函数就完成了。  现在我们将意识转换为小美。我现在知道了小帅写的 bubble_sort 函数的规则首先我需要准备好我想排序的一组数据到数组中再调用小帅写的 bubble_sort 函数将数组首元素的地址、数组元素个数、元素大小宽度、自定义的比较函数地址等作为参数最后调用打印函数即可。那我需要写的代码就是下面这些 int cmp_int(const void* a, const void* b) {int arg1 *(int*)a;int arg2 *(int*)b;return (arg1 arg2) - (arg1 arg2); }int main() {int arr[] { 5,2,7,4,9,1,0,3,8,6 };int sz sizeof(arr) / sizeof(arr[0]);bubble_sort(arr, sz, sizeof(arr[0]), cmp_int);print_int(arr, sz); } 到此我们就完成了冒泡排序的改造实现了一个类似于 qsort 函数的 bubble_sort 函数。为了区分函数的编写者和使用者我们可以将 bubble_sort 函数的实现放在另一个文件中在别人需要使用这个函数时只需要包含相应的头文件即可。 另外上面只是以整型类型的数据为例进行排序最后我们再使用各种类型的数据对我们写的 bubble_sort 函数进行测试。 sort.c #define _CRT_SECURE_NO_WARNINGS#include sort.hvoid swap(char* buf1, char* buf2, size_t width) {int i 0;for (i 0; i width; i){char tmp *buf1;*buf1 *buf2;*buf2 tmp;buf1;buf2;} }void bubble_sort(void *pa, size_t sz, size_t width, int (*cmp)(const void *a, const void *b)) {int i 0;for (i 0; i sz - 1; i){int j 0;int flag 1;for (j 0; j sz - 1 - i; j){//判断大小if (cmp((char*)pa j * width, (char*)pa (j 1) * width) 0){//交换两个值的位置flag 0;swap((char*)pa j * width, (char*)pa (j 1) * width, width);}}if (1 flag){break;}} }void print_int(int* pa, int sz) {int i 0;for (i 0; i sz; i){printf(%d , *(pa i));} } sort.h #pragma once#include stdio.h//排序 void bubble_sort(void* pa, size_t sz, size_t width, int (*cmp)(const void* a, const void* b)); //打印 void print_int(int* pa, int sz); main.c #define _CRT_SECURE_NO_WARNINGS#include sort.hint cmp_int(const void* a, const void* b) {int arg1 *(int*)a;int arg2 *(int*)b;return (arg1 arg2) - (arg1 arg2); }void text1() {int arr[] { 5,2,7,4,9,1,0,3,8,6 };int sz sizeof(arr) / sizeof(arr[0]);bubble_sort(arr, sz, sizeof(arr[0]), cmp_int);print_int(arr, sz); }int cmp_struct_name(const void* a, const void* b) {return strcmp((*(struct people*)a).name, (*(struct people*)b).name); }void text2() {struct people p[] { { xiaoshuai, 25, 75.5 }, { xiaomei, 24, 54.3 }, { xiaochou, 23, 67.8 } };int sz sizeof(p) / sizeof(p[0]);bubble_sort(p, sz, sizeof(p[0]), cmp_struct_name);int i 0;for (i 0; i sz; i){printf(%s , (*(p i)).name);} }int cmp_struct_weight(const void* a, const void* b) {double arg1 (*(struct people*)a).weight;double arg2 (*(struct people*)b).weight;return (arg1 arg2) - (arg1 arg2); }void text3() {struct people p[] { { xiaoshuai, 25, 75.5 }, { xiaomei, 24, 54.3 }, { xiaochou, 23, 67.8 } };int sz sizeof(p) / sizeof(p[0]);bubble_sort(p, sz, sizeof(p[0]), cmp_struct_weight);int i 0;for (i 0; i sz; i){printf(%lf , (*(p i)).weight);} }int cmp_struct_age(const void* a, const void* b) {int arg1 (*(struct people*)a).age;int arg2 (*(struct people*)b).age;return (arg1 arg2) - (arg1 arg2); }void text4() {struct people p[] { { xiaoshuai, 25, 75.5 }, { xiaomei, 24, 54.3 }, { xiaochou, 23, 67.8 } };int sz sizeof(p) / sizeof(p[0]);bubble_sort(p, sz, sizeof(p[0]), cmp_struct_age);int i 0;for (i 0; i sz; i){printf(%d , (*(p i)).age);} }int main() {//text1();/*text2();*//*text3();*//*text4();*/return 0; }通过实验我们改造的 bubble_sort 函数确实可以对任意类型的数据排序并且排升序和降序都是可行的。  如果觉得我的文章还不错请点赞、收藏 关注支持一下我会持续更新更好的文章。 点击跳转下一节 — C语言指针9
http://www.zqtcl.cn/news/565879/

相关文章:

  • 深圳建站公司网站免费推广预期效果
  • html5 国外网站后台网站要做权限前端还是后台做
  • 免费建自己的网站网站标题 关键词 描述之间的关系
  • 提供响应式网站建设wordpress怎么做背景图片
  • 相亲网与做网站做网站的目的与意义
  • 做网站字体大小网站建设是属于虚拟产品吗
  • 网站的内链怎么做校园网建设网站特色
  • 优化网站标题企业的网站一般做哪些维护
  • 聊天网站备案南阳定制网站制作价格低
  • 广州镭拓科技网站建设公司长春招聘
  • 视频网站app怎么做跨境贸易电子商务服务平台
  • 丽水网站seo餐饮vi设计案例
  • 娄底网站建设报价山东省住房和建设厅注册中心网站
  • 公司网站建设工作重点网站建设吉金手指专业11
  • vue做前台网站怎么做钓鱼网站吗
  • 个人建设网站如何定位烟台h5网站开发
  • 广州网站定制多少钱html5游戏开发
  • 使用angularjs的网站域名怎么解析到服务器
  • 地方门户网站盈利模式宝塔 wordpress
  • 西安网站备案软件开发基础教程
  • 有服务器做网站软件系统开发怎样容易
  • 网站建设的公司有发展吗织梦婚纱网站模板
  • 淘宝销售书网站建设方案wordpress调用评论数据
  • 搭建网站需要什么软件苏州吴中区建设局工程网站
  • 长沙市网站推广公司wordpress 弹窗登录插件
  • 网站策划怎么做内容朔州网站建设公司
  • 宁波拾谷网站建设蚌埠网站建设中心
  • 青岛专业设计网站公司加拿大广播公司
  • 盘锦市建设局网站地址八桂职教网技能大赛
  • 投资建设一个网站多少钱和淘宝同时做电商的网站