指針(五)后半

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…