1、 qsort 函数

1.1、qsort 函数排列结构体

在这里,我们创建结构体类型的数组,用于 qsort 函数的传参。

#include<stdio.h>
#include<stdlib.h>
#include<string.h>struct Stu//创建结构体变量
{char name[30];int age;
};struct Stu arr[] = { { "zhangsan", 18 }, { "lisi", 20 }, { "wangwu", 38 } };void Print(struct Stu* p, int sz)//打印函数
{for (int i = 0; i < sz; i++){printf("%s: %d\n", p->name, p->age);p++;}
}cmp_str_by_age(const void* p1, const void* p2)//排年龄函数
{return (((struct Stu*)p1)->age - ((struct Stu*)p2)->age);
}test1()//按年龄大小
{int sz = sizeof(arr) / sizeof(arr[0]);qsort(arr, sz, sizeof(arr[0]), cmp_str_by_age);Print(arr, sz);
}cmp_str_by_name(const void* p1, const void* p2)//排姓名函数
{return strcmp(((struct Stu*)p1)->name, ((struct Stu*)p2)->name);
}test2()//按姓名
{int sz = sizeof(arr) / sizeof(arr[0]);qsort(arr, sz, sizeof(arr[0]), cmp_str_by_name);Print(arr, sz);
}int main()
{test1();printf("-------------------------\n");test2();return 0;
}

这里讲两点:

1、结构成员访问操作符: ->

使用方法为:结构体指针 -> 成员变量。上面代码中, ((struct Stu*)p1)->age 也可以换为 *(struct Stu*)p1.age 。

2、 strcmp 函数

使用方法为,向函数中传入两个字符串类型的数据,比较对应位置字符的 ASCII 码值的大小。以顺序为例,若前一个字符串对应位置字符的 ASCII 码值应大于后一个,返回大于0的值;相等返回0,小于返回小于0的值。

1.2、 qsort 函数的模拟实现

既然要实现 qsort 函数,那么向其中传入的参数,也应该是:首元素地址、元素个数、元素大小、比较函数。

#include<stdio.h>int int_cmp(const void* p1, const void* p2)
{return *(int*)p1 - *(int*)p2;
}void Bubble_qsort(void* base, int count, int size, int (*cmp)(void*, void*))}void test1()
{int arr[] = { 4,5,2,7,9,12,34,101 };int count = sizeof(arr) / sizeof(arr[0]);Bubble_qsort(arr, count, sizeof(arr[0]), int_cmp);
}int main()
{test1();//实现整型值的排序return 0;
}

将这个函数的名字取为 Bubble_qsort ,是因为我们将用冒泡排列的方式来模拟实现 qsort 函数。

所以,我们要交代趟数,也要交代每趟交换数据的次数。

而交换操作中,我们可以将每两个数(的地址)传入 int_cmp 函数中,观察返回的值。若返回正数值,则再创建一个交换函数。

但是, void* 类型的指针不能进行任何操作。也许会用强制类型转换,转换成什么? int* ?但这可是在模拟 qsort 函数,这个函数原来是可以排列任意类型的数据的。

所以,我们不妨将 void* 类型,强制转换成 char* 类型

#include<stdio.h>int int_cmp(const void* p1, const void* p2)
{return *(int*)p1 - *(int*)p2;
}void Swap(char* buf1, char* buf2)
{}void Bubble_qsort(void* base, int count, int size, int (*cmp)(void*, void*))
{for (int i = 0; i < count - 1; i++){for (int j = 0; j < count - i - 1; j++){if (cmp((char*)base + j * size, (char*)base + (j + 1) * size) > 0){Swap((char*)base + j * size, (char*)base + (j + 1) * size, size);}}}
}void test1()
{int arr[] = { 4,5,2,7,9,12,34,101 };int count = sizeof(arr) / sizeof(arr[0]);Bubble_qsort(arr, count, sizeof(arr[0]), int_cmp);
}int main()
{test1();//实现整型值的排序return 0;
}

而在交换函数中,既然地址已被强制转换成 char* ,那么我们就不能一次性交换干净,而是一点一点交换。交换的次数,自然是元素的大小。

#include<stdio.h>void Print(int arr[], int count)//打印函数
{for (int i = 0; i < count; i++){printf("%d ", arr[i]);}printf("\n");
}int int_cmp(const void* p1, const void* p2)//比较函数
{return *(int*)p1 - *(int*)p2;
}void Swap(char* buf1, char* buf2, int size)//交换函数
{for (int i = 0; i < size; i++){char tmp = *(buf1 + i);*(buf1 + i) = *(buf2 + i);*(buf2 + i) = tmp;}
}void Bubble_qsort(void* base, int count, int size, int (*cmp)(void*, void*))
{                                                   //模拟 qsort 的函数for (int i = 0; i < count - 1; i++){for (int j = 0; j < count - i - 1; j++){if (cmp((char*)base + j * size, (char*)base + (j + 1) * size) > 0){Swap((char*)base + j * size, (char*)base + (j + 1) * size, size);}}}
}void test1()
{int arr[] = { 4,5,2,7,9,12,34,101 };int count = sizeof(arr) / sizeof(arr[0]);Print(arr, count);Bubble_qsort(arr, count, sizeof(arr[0]), int_cmp);Print(arr, count);
}int main()
{test1();//实现整型值的排序return 0;
}

这样一来,这个函数连结构体都能排列。但是要加一点比较函数代码:

#include<stdio.h>struct Stu//创建结构体
{char name[30];int age;
};void Print(int arr[], int count)//打印函数
{for (int i = 0; i < count; i++){printf("%d ", arr[i]);}printf("\n");
}void Print1(struct Stu* p, int sz)//打印结构体
{for (int i = 0; i < sz; i++){printf("%s: %d\n", p->name, p->age);p++;}
}int int_cmp(const void* p1, const void* p2)//比较函数
{return *(int*)p1 - *(int*)p2;
}int cmp_str_by_name(const void* p1, const void* p2)//比较字符串
{if (strcmp(((struct Stu*)p1)->name, ((struct Stu*)p2)->name) > 0)return 1;else if (strcmp(((struct Stu*)p1)->name, ((struct Stu*)p2)->name) < 0)return -1;elsereturn 0;
}void Swap(char* buf1, char* buf2, int size)//交换函数
{for (int i = 0; i < size; i++){char tmp = *(buf1 + i);*(buf1 + i) = *(buf2 + i);*(buf2 + i) = tmp;}
}void Bubble_qsort(void* base, int count, int size, int (*cmp)(void*, void*))
{                                                   //模拟 qsort 的函数for (int i = 0; i < count - 1; i++){for (int j = 0; j < count - i - 1; j++){if (cmp((char*)base + j * size, (char*)base + (j + 1) * size) > 0){Swap((char*)base + j * size, (char*)base + (j + 1) * size, size);}}}
}void test1()
{int arr[] = { 4,5,2,7,9,12,34,101 };int count = sizeof(arr) / sizeof(arr[0]);Print(arr, count);Bubble_qsort(arr, count, sizeof(arr[0]), int_cmp);Print(arr, count);
}void test2()
{struct Stu arr[] = { { "zhangsan", 18 }, { "lisi", 20 }, { "wangwu", 38 } };int count = sizeof(arr) / sizeof(arr[0]);Print1(arr, count);printf("-------------------------\n");Bubble_qsort(arr, count, sizeof(arr[0]), cmp_str_by_name);Print1(arr, count);
}int main()
{//test1();//实现整型值的排序test2();//实现结构体的排列return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/diannao/99018.shtml
繁体地址,请注明出处:http://hk.pswp.cn/diannao/99018.shtml
英文地址,请注明出处:http://en.pswp.cn/diannao/99018.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

TDengine 特殊选择函数 MODE() 用户手册

MODE 函数用户手册 函数定义 MODE(expr)功能说明 MODE() 函数返回指定列中出现频率最高的值&#xff08;众数&#xff09;。如果有多个值具有相同的最高频率&#xff0c;系统会返回其中一个值。该函数会忽略 NULL 值。 算法原理 MODE 函数的计算过程如下&#xff1a; 数据…

智能外骨骼技术应用场景及价格可接受区间分析

一、引言 智能外骨骼机器人融合机械、人工智能和传感器技术,增强或恢复人体运动能力。2025年,该技术在医疗康复、工业生产、军事应用和消费市场快速普及。本文分析其应用场景、市场需求、典型产品、价格可接受区间及相关来源,探讨普及的关键因素。 二、主要应用场景及产品…

Vue模板中传递对象或数组时,避免直接使用字面量[]和{}

在 Vue 中&#xff0c;直接在模板中使用 [] 或 {} 作为 prop 值会导致子组件不必要的重新渲染&#xff0c;因为每次父组件渲染时都会创建新的引用。以下是解决方案和最佳实践&#xff1a; 1. 避免在模板中直接使用字面量 <!-- 避免这样写 --> <ChildComponent :items&…

【C++】list容器的模拟实现

目录 1. 节点(list_node) 的结构 2. 哨兵位头节点 3. list容器的成员变量 4. 插入/删除操作 4.1 插入操作&#xff08;insert&#xff09; 4.2 删除操作&#xff08;erase&#xff09; 5. 迭代器的实现 6. 不同迭代器和const容器的限制 7. 重载operator-> 8. 迭代器…

三大运营商eSIM手机业务开通加速

截至2025年9月11日&#xff0c;中国三大运营商eSIM手机业务开通情况呈现明显差异化&#xff1a;中国联通已率先支持eSIM手机业务&#xff0c;但仅限于特定城市和设备&#xff1b;中国移动和中国电信则处于"技术准备就绪&#xff0c;等待政策批复"阶段&#xff0c;预计…

基于SpringBoot的足球论坛系统+论文示例参考

1.项目介绍 系统角色&#xff1a;管理员、普通用户功能模块&#xff1a;用户管理、足球赛事、球员信息、推荐话题、帖子信息、周边商城、订单信息、系统管理等技术选型&#xff1a;SpringBoot&#xff0c;Vue等 测试环境&#xff1a;idea2024&#xff0c;jdk1.8&#xff0c;mys…

数据库中悲观锁小结

实际上&#xff0c;悲观并发控制实际上是“先取锁再访问”的保守策略&#xff0c;为数据处理的安全提供了保证。但是在效率方面&#xff0c;处理加锁的机制会让数据库产生额外的开销&#xff0c;还有增加产生死锁的机会&#xff1b;另外&#xff0c;在只读型事务处理中由于不会…

结构光三维重建原理详解(1)

1. 基本原理概述 结构光三维重建&#xff08;Structured Light 3D Reconstruction&#xff09;是一种主动式光学测量方法。其核心思想是&#xff1a; 向物体表面投射一组 已知的、编码好的光栅/条纹图案&#xff1b;使用一个或多个摄像机拍摄这些条纹在物体表面的变形情况&…

TruckSim与Matlab-Simulink联合仿真(一)

摘要 从0到1的TruckSim与Matlab-Simulink 简单的联合仿真。 1. 环境搭建 matlab版本&#xff1a;R2022a TruckSim版本&#xff1a;2019 其他适配版本自行搜索。 matlabR2022a安装参考&#xff1a;参考链接 TruckSim2019安装包百度网盘链接&#xff0c;里面有安装流程&#x…

后端post请求返回页面,在另一个项目中请求过来会出现的问题

目录 1.后端post请求返回页面&#xff0c;跨域问题 一、核心问题&#xff1a;跨域&#xff08;CORS&#xff09;限制&#xff08;最直接的技术障碍&#xff09; 具体表现&#xff1a; 二、安全性问题&#xff1a;CSRF 攻击风险被放大 原理与危害&#xff1a; 三、交互体验…

APT32F0042F6P6 32位微控制器(MCU)单片机 APT爱普特微电子 芯片核心解析

一、核心解析&#xff1a;APT32F0042F6P6 是什么&#xff1f;1. 电子元器件类型APT32F0042F6P6 是爱普特微电子&#xff08;APTCHIP&#xff09; 推出的一款基于平头哥THead内核的32位微控制器&#xff08;MCU&#xff09;。它采用TSSOP20封装&#xff0c;是一款主打高性价比、…

SDR集成式收发器设计资源

一、AD9361 制造商产品编号&#xff1a;ADRV9361-Z7035 库存编号&#xff1a;4032703 价格&#xff1a;CNY17,737.18 含税 制造商产品编号&#xff1a;ADRV1CRR-BOB 库存编号&#xff1a;4023108 价格&#xff1a;CNY3,145.87 含税 制造商产品编号&#xff1a;ADRV1CRR-FMC 库存…

将Varjo XR技术融入飞行模拟器,有效降低成本提升训练效果

扩展现实(XR)飞行模拟器通过以较低的成本提供沉浸式和逼真的飞行环境&#xff0c;彻底改变了飞行训练。本文将XR利用了最近的研究和数据进行综合分析&#xff0c;评估飞行模拟器的有效性。此外&#xff0c;根据XR技术在航空训练中的优势和应用&#xff0c;评估XR飞行模拟器最终…

简单的GIT操作学习记录

Git 版本控制基本使用 1.Idea版本共计基本操作 公司使用Git作为代码版本管理工具&#xff0c;平时使用非常频繁这里简单整理方便后续学习查看 1.1 merge未推送回滚 我们代码merge操作后&#xff0c;并且没有推送到远端&#xff0c;本地项目发现有推送箭头&#xff0c;可以使…

Spring Boot 与前端文件下载问题:大文件、断点续传与安全校验

前言在企业级 Spring Boot 项目中&#xff0c;文件下载 是非常常见的功能场景&#xff1a;用户下载报表、合同、发票 PDF下载图片、音视频资源系统导出大规模 Excel/CSV 数据然而&#xff0c;很多开发者在实现文件下载时&#xff0c;会遇到 下载失败、文件损坏、性能瓶颈、断点…

主板硬件研发基础--HDMI工作原理

HDMI 接口 技术原理:HDMI 接口采用 TMDS 技术传输数字信号,不仅可以传输高清视频信号,还能同时传输多声道音频信号。它支持 EDID 和 DDC2B,设备之间能够自动协商并选择最合适的视频 / 音频格式,实现 “即插即用” 功能。 接口类型:常见的有标准 HDMI 接口、Mini-HDMI 接口…

`Object.groupBy`将数组中的数据分到对象中

Object.groupBy 将一个对象或者数组的元素按照规则分组&#xff0c; 返回一个新对象&#xff0c; Object.groupBy(items, callbackFn) items&#xff1a;要分组的对象或数组&#xff08;通常是数组&#xff09;。 callbackFn(element, index, array)&#xff1a;回调函数&#…

反序列化漏洞详解

用途限制声明&#xff0c;本文仅用于网络安全技术研究、教育与知识分享。文中涉及的渗透测试方法与工具&#xff0c;严禁用于未经授权的网络攻击、数据窃取或任何违法活动。任何因不当使用本文内容导致的法律后果&#xff0c;作者及发布平台不承担任何责任。渗透测试涉及复杂技…

SQL数据分析原代码--创建表与简单查询

CREATE TABLE&#xff1a;创建表&#xff0c;定义字段名、类型、注释INSERT INTO&#xff1a;插入数据&#xff0c;支持单条或批量插入SELECT&#xff1a;查询数据&#xff0c;*表示所有字段&#xff0c;AS可起别名&#xff0c;DISTINCT去重WHERE&#xff1a;条件筛选&#xff…

k8s查询ServiceAccount有没有列出 nodes 的权限

要检查 ServiceAccount xxxxxx:default 是否具有列出 nodes 的权限&#xff0c;可以使用以下方法&#xff1a;1. **使用 kubectl auth can-i 命令**这是最直接的方法&#xff0c;可以检查特定用户或 ServiceAccount 是否具有特定权限&#xff1a;kubectl auth can-i list nodes…