公司网站与推广免费企业名录网站
2026/3/29 4:41:08 网站建设 项目流程
公司网站与推广,免费企业名录网站,ug wordpress,ppt制作最常用软件系列文章目录 学习系列文章#xff1a; 【初识C语言】选择结构#xff08;if语句和switch语句#xff09;详细解答 【初识C语言】循环结构#xff08;while语句、do…while语句和for语句#xff09;详细解答 实战项目文章#xff1a; 【初识C语言】经典扫雷C语言实战【初识C语言】选择结构if语句和switch语句详细解答【初识C语言】循环结构while语句、do…while语句和for语句详细解答实战项目文章【初识C语言】经典扫雷C语言实战原码解析看完就能上手拆解与修改文章目录系列文章目录前言一、qsort 函数是什么1、核心定位2、函数原型牢记4个参数3、4 个参数通俗解读二、qsort 的核心自定义比较函数重点中的重点1. 比较函数通用规则2.分类型写比较函数场景 1排序 int 类型最基础入门必学场景 2排序 float/double 类型避坑不能直接返回差值场景 3排序 char 类型单个字符按 ASCII 码排序场景 4排序字符串类型两种写法重点区分写法 1二维 char 数组排序常用每行一个字符串写法 2char * 指针数组排序推荐节省内存场景 5排序结构体类型进阶用法面试高频写法 1按结构体 int 成员排序按年龄排序写法 2按结构体字符串成员排序按姓名字典序排序三、qsort 通用技巧 避坑总结1. 通用技巧2. 避坑指南必看总结前言小伙伴们今天给大家分享一个 C 语言里的 “排序万能工具”——qsort函数。平时我们写排序要么手写冒泡、快排还得针对 int、char、结构体分别改代码巨麻烦而qsort函数能一键搞定所有数据类型的排序高效又省心这篇文章就带大家吃透它的含义和用法希望对大家有用一、qsort 函数是什么1、核心定位qsort是 C 语言标准库中的通用快速排序函数定义在 stdlib.h 头文件中支持对任意类型的数组进行排序int、float、字符串、结构体统统不在话下底层实现了快速排序算法时间复杂度接近 O (NlogN)效率拉满2、函数原型牢记4个参数先看官方原型对应我代码里的注释voidqsort(void*base,// 要排序的数组首地址直接传数组名就行比如arr_intsize_tnitems,// 数组元素个数通用写法sizeof(arr)/sizeof(arr[0])size_tsize,// 单个元素的字节大小比如sizeof(int)、sizeof(arr[0])int(*compar)(constvoid*,constvoid*)// 自定义比较函数指针核心决定排序规则);3、4 个参数通俗解读参数名通俗含义代码示例int 数组base告诉 qsort “要排序的数组在哪”数组名本身就是首地址直接传即可arr_int对应 int arr_int []nitems告诉 qsort “数组有多少个元素”可以用 sizeof 计算通用又方便sz sizeof(arr_int)/sizeof(arr_int[0])size告诉 qsort “每个元素占多少内存”推荐用sizeof(arr[0])适配类型变更si sizeof(int) 或 si sizeof(arr_int[0])compar告诉 qsort “怎么比较两个元素”需要我们自定义函数决定是正序还是降序compar_int自定义的 int 比较函数二、qsort 的核心自定义比较函数重点中的重点qsort之所以能适配所有数据类型全靠这个比较函数。它有固定的格式要求也有通用的排序规则我们先掌握基础再分类型拆解。1. 比较函数通用规则格式固定返回值是int两个参数都是const void*通用指针兼容所有类型不能直接解引用必须强制转换返回值含义敲黑板这是排序的关键记死这三句话返回负数第一个参数对应的元素排在第二个参数对应的元素前面正序核心返回0两个元素相等顺序不变返回正数第一个参数对应的元素排在第二个参数对应的元素后面2.分类型写比较函数下面结合我整理的代码逐个讲解不同数据类型的比较函数写法从简单到复杂循序渐进场景 1排序 int 类型最基础入门必学这是最简单的场景比较函数直接返回两个数的差值即可无精度丢失。#includestdio.h#includestdlib.h// 自定义int类型比较函数正序intcompar_int(constvoid*a,constvoid*b){// 步骤1const void* 强制转换为 const int*还原int指针类型// 步骤2解引用得到int类型的值// 步骤3返回差值满足比较函数返回规则return*(constint*)a-*(constint*)b;// 正序// return *(const int*)b - *(const int*)a; // 降序颠倒a和b即可}intmain(){intarr_int[]{3,1,2,5,7,9,10,6,8,4};size_tszsizeof(arr_int)/sizeof(arr_int[0]);// 元素个数size_tsisizeof(arr_int[0]);// 单个元素大小inti0;qsort(arr_int,sz,si,compar_int);// 调用qsort// 打印结果for(i0;isz;i){printf(%d ,arr_int[i]);}return0;}关键细节const void* a不能直接解引用必须先转为const int*再用*解引用获取具体数值。场景 2排序 float/double 类型避坑不能直接返回差值很多新手会踩坑直接返回 f1 - f2 但浮点型差值转 int 会截断小数比如 1.25 和 1.26 的差值 0.01转 int 后变成 0qsort 无法判断大小必须显式判断#includestdio.h#includestdlib.hintcompar_float(constvoid*a,constvoid*b){// 先转换并解引用获取浮点值floatval_a*(constfloat*)a;floatval_b*(constfloat*)b;// 显式判断大小返回1/-1/0避免精度丢失if(val_aval_b){return1;// a在后正序}elseif(val_aval_b){return-1;// a在前正序}else{return0;// 相等}// 降序只需颠倒判断逻辑//if (val_b val_a) {// return 1;//}//else if (val_b val_a) {// return -1;//}//else return 0;}intmain(){floatarr_float[]{1.25f,1.26f,2.58f,9.48f,4.37f};size_tszsizeof(arr_float)/sizeof(arr_float[0]);size_tsfsizeof(arr_float[0]);inti0;qsort(arr_float,sz,sf,compar_float);for(i0;isz;i){printf(%.2f ,arr_float[i]);}return0;}避坑指南double类型的比较函数和float完全一致只需把类型换成double即可同样不能直接返回差值场景 3排序 char 类型单个字符按 ASCII 码排序char本质是 ASCII 码整数比较逻辑和int一致直接返回差值即可还能实现不区分大小写排序拓展用法。#includestdio.h#includestdlib.h#includectype.h// tolower依赖头文件intcompar_char(constvoid*a,constvoid*b){// 正序按ASCII码从小到大AZazreturn*(constchar*)a-*(constchar*)b;// 不区分大小写排序先转小写再比较// return tolower(*(const char*)a) - tolower(*(const char*)b);// 降序return *(const char*)b - *(const char*)a;}intmain(){chararr_char[]{b,A,r,E,P,z,a,o,t,W};size_tszsizeof(arr_char)/sizeof(arr_char[0]);size_tscsizeof(arr_char[0]);inti0;qsort(arr_char,sz,sc,compar_char);for(i0;isz;i){printf(%c ,arr_char[i]);}return0;}小知识ASCII 码中大写字母 小写字母数字 字母。场景 4排序字符串类型两种写法重点区分字符串排序是高频场景分为「二维 char 数组」和「char * 指针数组」两者的比较函数写法不同千万别搞混写法 1二维 char 数组排序常用每行一个字符串#includestdio.h#includestdlib.h#includestring.h// strcmp依赖头文件intcompar_str_2d(constvoid*a,constvoid*b){// 直接转换为const char*传入strcmp比较完整字符串returnstrcmp((constchar*)a,(constchar*)b);// 正序// return strcmp((const char*)b, (const char*)a); // 降序}intmain(){// 二维char数组5行20列每行存一个字符串chararr_str[5][20]{hello,apple,tiger,banana,marry};size_tszsizeof(arr_str)/sizeof(arr_str[0]);size_tscsizeof(arr_str[0]);// 单个元素是一行大小为20inti0;qsort(arr_str,sz,sc,compar_str_2d);for(i0;isz;i){printf(%s ,arr_str[i]);}return0;}关键细节a/b直接指向每行字符串的首地址转换为const char*后可直接传入strcmpstrcmp专门比较字符串返回值符合 qsort 要求。写法 2char * 指针数组排序推荐节省内存#includestdio.h#includestdlib.h#includestring.hintcompar_str_ptr(constvoid*a,constvoid*b){// 步骤1转换为const char**指向char*指针的指针// 步骤2解引用得到const char*字符串首地址// 步骤3用strcmp比较returnstrcmp(*(constchar**)a,*(constchar**)b);// 正序// return strcmp(*(const char**)b, *(const char**)a); // 降序}intmain(){// char*指针数组存储字符串常量的首地址char*arr_str[]{hello,apple,tiger,banana,marry};size_tszsizeof(arr_str)/sizeof(arr_str[0]);size_tscsizeof(arr_str[0]);// 单个元素是char*指针大小4/8字节inti0;qsort(arr_str,sz,sc,compar_str_ptr);for(i0;isz;i){printf(%s ,arr_str[i]);// arr_str[i] 等价于 *(arr_str i)}return0;}关键细节a/b指向的是char*指针数组元素因此必须先转为const char**解引用后才能得到字符串首地址传入strcmp。场景 5排序结构体类型进阶用法面试高频结构体排序需按指定成员排序分为「int 成员」和「字符串成员」写法略有差异但核心不变。写法 1按结构体 int 成员排序按年龄排序#includestdio.h#includestdlib.h// 定义学生结构体structstudent{charname[20];intage;};intcompar_stu_age(constvoid*a,constvoid*b){// 两种等价写法任选其一// 写法1先解引用指针再用.访问成员return(*(conststructstudent*)a).age-(*(conststructstudent*)b).age;// 写法2先转换为指针再用-访问成员更简洁// return ((const struct student*)a)-age - ((const struct student*)b)-age;}intmain(){structstudentarr_stu[]{{zhangsan,18},{lisi,20},{wangwu,21},{zhaoliu,17}};size_tstsizeof(arr_stu)/sizeof(arr_stu[0]);size_tsusizeof(arr_stu[0]);// 单个结构体大小inti0;qsort(arr_stu,st,su,compar_stu_age);for(i0;ist;i){// 两种等价访问方式printf(姓名%s\t年龄%d\n,arr_stu[i].name,arr_stu[i].age);// printf(姓名%s\t年龄%d\n, (arr_stu[i])-name, (arr_stu[i])-age);}return0;}关键细节( * (struct student * )a).age 等价于 ((struct student * )a)-age后者更简洁推荐使用正序 / 降序同样只需颠倒差值顺序即改变a/b位置。写法 2按结构体字符串成员排序按姓名字典序排序#includestdio.h#includestdlib.h#includestring.hstructstudent{charname[20];intage;};intcompar_stu_name(constvoid*a,constvoid*b){// 两种等价写法任选其一returnstrcmp(((conststructstudent*)a)-name,((conststructstudent*)b)-name);// return strcmp((*(const struct student*)a).name, (*(const struct student*)b).name);}intmain(){structstudentarr_stu[]{{Zhangsan,18},{alice,20},{wangwu,21},{zhaoliu,17}};size_tstsizeof(arr_stu)/sizeof(arr_stu[0]);size_tsusizeof(arr_stu[0]);inti0;qsort(arr_stu,st,su,compar_stu_name);for(i0;ist;i){printf(姓名%s\t年龄%d\n,arr_stu[i].name,arr_stu[i].age);}return0;}关键细节结构体字符串成员必须用strcmp比较不能直接用或差值比较三、qsort 通用技巧 避坑总结1. 通用技巧元素个数计算用 sizeof(arr)/sizeof(arr[0])无需手动修改适配所有数组单个元素大小优先用 sizeof(arr[0])比直接写sizeof(int)更灵活数组类型变更时无需修改访问方式等价性arr[i] 等价于 *(arr i)数组下标与指针偏移arr[i].member 等价于 (arr[i])-member结构体变量与指针的访问转换(*p).member 等价于 p-member结构体指针的两种访问方式。2. 避坑指南必看float/double类型绝对不能直接返回差值必须显式判断大小避免精度丢失字符串类型必须用strcmp比较完整字符串不能直接比较指针或单个字符void*指针不能直接解引用必须先强制转换为对应类型再解引用结构体访问变量用.指针用-不能随意互换比较函数返回值必须遵循 “负数在前、正数在后” 的规则否则排序结果异常。总结qsort函数是 C 语言排序的 “万能钥匙”核心在于自定义比较函数只要掌握了不同数据类型的转换技巧和比较逻辑就能轻松搞定所有排序场景。总结一下核心要点qsort 4 个参数首地址、元素个数、单个元素大小、比较函数比较函数固定格式返回值决定排序顺序不同数据类型只需调整转换和比较逻辑高频场景int差值、float显式判断、字符串strcmp、结构体按成员比较通用技巧优先用sizeof(arr[0])牢记等价访问方式避开精度丢失、类型不匹配的坑。掌握 qsort不仅能节省手写排序的时间还能应对学习和面试中的各种排序场景小伙伴们抓紧在编译器里跑一遍加深理解吧~

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询