深入解剖指針(4)

個人主頁(找往期文章包括但不限于本期文章中不懂的知識點):?我要學編程(?_?)-CSDN博客

目錄

回調函數

qsort使用舉例

使用qsort函數排序整型數據?

使用qsort排序結構數據?

qsort函數的模擬實現?


?

回調函數

回調函數就是一個通過函數指針調用的函數。 如果你把函數指針(地址)作為參數傳遞給另?個函數,當這個指針被用來調用其所指向的函數時,被調用的函數就是回調函數。回調函數不是由該函數的實現方直接調用,而是在特定的事件或條件發生時由另外的一方調用的,用于對該事件或條件進行響應。

簡單來說就是:當我擁有一個函數(地址)指針時,在一些特定的情況下,通過函數指針回過頭來調用這個函數,那么這個被調用的函數就是回調函數。

在簡易計算器的制作(函數指針數組的實踐)-CSDN博客這篇文章中寫的計算代碼,就是可以用這個回調函數的例子。如果我們要使用加法計算兩個數的值,不是直接由main函調用的,而是由calc函數來調用對應的加法函數。這便是回調函數。

qsort使用舉例

使用qsort函數排序整型數據?

如果我們想要排序一組數據,按照升序或者降序的方式,首先想到的就是冒泡排序。這個排序在深入解剖指針篇(2)-CSDN博客?這篇文章中介紹了。核心思想就是:兩兩相鄰元素的比較。

我們現在就用qsort函數來實現。首先,就得了解什么是qsort函數。

上面就是關于qsort函數的基本介紹。

void qsort(void* base, //這個base就是要排序的元素的起始地址size_t num, //這個num就是要排序的元素個數size_t size,//這個size就是要排序的元素對應字節數int (*compar)(const void*, const void*));//這個其實就是一個 有比較功能函數 的指針

上面那個比較功能就是你要怎么實現這個排序,就用什么功能。例如:我要實現升序功能,那么這個函數就是實現升序的功能。?

我們現在就可以開始模擬實現冒泡排序了。

#include <stdio.h>
#include <stdlib.h>//qsort函數所需的頭文件//打印數據看看是否排序成功
void Print(int arr[], int sz)
{for (int i = 0; i < sz; i++){printf("%d ", arr[i]);}
}//調用的排序函數
//由于創造這個函數的人,不知道我們會比較什么樣的數據,因此,就要void*來接收。
int int_cmp(const void* p1, const void* p2)
{//qsort默認的是升序,由于void*不能直接解引用,所以就先得強制轉換為要比較(int*)的數據類型return (*(int*)p1 - *(int*)p2);//如果我們像排成降序,就可以把這個給反過來
}int main()
{int arr[] = { 9,8,7,6,5,4,3,2,1,0 };int sz = sizeof(arr) / sizeof(arr[0]);qsort(arr, sz, sizeof(arr[0]), int_cmp);Print(arr, sz);return 0;
}

可以看出來這個qsort函數排序是正確的。

使用qsort排序結構數據?

我們假設要排序一些不是整型的數據,那么冒泡排序肯定是不行的。但是我們可以采用其思想,來進行排序。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct stu//創建一個結構體類型:學生
{char name[20];int age;
};int cmp_stu_by_name(const void* e1, const void* e2)
{return strcmp(((struct stu*)e1)->name, ((struct stu*)e2)->name);
}void Print(struct stu* p, int sz)
{for (int i = 0; i < sz; i++){printf("%s ", (p+i)->name);//結構體指針->成員名}printf("\n");
}
int main()
{//創建一個結構體數組并且初始化struct stu arr[] = { {"zhangsan", 20},{"lisi" ,30}, {"wangwu", 18} };int sz = sizeof(arr) / sizeof(arr[0]);qsort(arr, sz, sizeof(arr[0]), cmp_stu_by_name);Print(arr, sz);return 0;
}

?strcmp是用來比較字符串大小的,具體用法請看:字符函數與字符串函數(上)-CSDN博客?

通過上面的學習,我們就可以發現這個qsort函數在使用時,需要我們根據自己的需求來寫出對應的比較函數。

結構體成員的間接訪問?

我們在訪問結構體成員時,有兩種操作符,一種是 . (直接訪問),還有一種是 ->(間接訪問)。

直接訪問在操作符詳解(下)-CSDN博客?里講過。

結構體指針->成員名 ,即當 -> 的左邊滿足時結構體指針時,我們要訪問結構體成員就可以用->。?

上面是排序其名字,我們還可以排序其年齡

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct stu
{char name[20];int age;
};int cmp_stu_by_age(const void* e1, const void* e2)
{return (((struct stu*)e1)->age - ((struct stu*)e2)->age);
}void Print(struct stu* p, int sz)
{for (int i = 0; i < sz; i++){printf("%d ", (p + i)->age);}printf("\n");
}int main()
{struct stu arr[] = { {"zhangsan", 20},{"lisi" ,30}, {"wangwu", 18} };int sz = sizeof(arr) / sizeof(arr[0]);qsort(arr, sz, sizeof(arr[0]), cmp_stu_by_age);Print(arr, sz);return 0;
}

qsort函數的模擬實現?

我們現在就來通過模擬實現qsort函數(用冒泡的方式)來排序整形數組。

#include <stdio.h>
int cmp(const void* e1, const void* e2)
{return *(int*)e1 - *(int*)e2;
}//因為前面有強制轉換為char*了,所以我們也就不用void*了
void Swap(char* p1, char* p2, size_t width)
{//如果是排序char的數據,我們就只能一個字節一個字節的交換for (int i = 0; i < width; i++){char tmp = *(p1+i);*(p1+i) = *(p2+i);*(p2+i) = tmp;}
}void bubble_sort(void* base, size_t num, size_t width, int(*cmp)(void*, void*))
{for (int i = 0; i < num - 1; i++){for (int j = 0; j < num - 1 - i; j++){//如果前者大于后者,也就是降序,會返回一個大于0的數(根據這個cmp的函數來的)//不知道是啥類型,強制轉換為最小的就行(類型占字節最小的是字符型)if (cmp((char*)base + j * width, (char*)base + (j + 1) * width) > 0){//交換Swap((char*)base + j * width, (char*)base + (j + 1) * width, width);}}}
}int main()
{int arr[] = { 9,8,7,6,5,4,3,2,1,0 };int sz = sizeof(arr) / sizeof(arr[0]);bubble_sort(arr, sz, sizeof(arr[0]), cmp);//采用冒泡的方式for (int i = 0; i < sz; i++){printf("%d ", arr[i]);}printf("\n");return 0;
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/716854.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/716854.shtml
英文地址,請注明出處:http://en.pswp.cn/news/716854.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【Android12】Android性能調優工具SystemServerTiming日志

Android性能調優工具SystemServerTiming日志 性能優化、穩定性優化是Android系統優化的兩大方面&#xff0c;對于性能調試Android提供了很多工具&#xff0c;比如&#xff1a;bootchart、systrace、perfboot、log、dmsg等等。 SystemServerTiming是Android原生系統中一個日志…

《Spring Security 簡易速速上手小冊》第10章 未來趨勢與高級話題(2024 最新版)

文章目錄 10.1 云原生安全性趨勢10.1.1 基礎知識10.1.2 重點案例&#xff1a;保護微服務通信10.1.3 拓展案例 1&#xff1a;容器安全最佳實踐10.1.4 拓展案例 2&#xff1a;自動化安全審計和合規性檢查 10.2 反應式編程與 Spring Security10.2.1 基礎知識10.2.2 重點案例&#…

nginx-圖片模塊

./configure --with-http_image_filter_module location / {root html;index index.html index.htm;if ($arg_w "") {set $arg_w -;}if ($arg_h "") {set $arg_h -;}image_filter resize $arg_w $arg_h;image_filter_jpeg_quality 95; } 訪問: 1234…

CSS錐形漸變:conic-gradient()

畫一個扇形圖&#xff0c;使用常規方法可能很難畫&#xff0c;但是用錐形漸變的話非常好畫 <style>.pattern{width: 100px; height: 100px;border-radius: 50%;background: conic-gradient(yellow 30deg , black 30deg , black 90deg , yellow 90deg ,yellow 150d…

Git分布式版本控制系統——git學習準備工作

一、Git倉庫介紹 開發者可以通過Git倉庫來存儲和管理文件代碼&#xff0c;Git倉庫分為兩種&#xff1a; 本地倉庫&#xff1a;開發人員自己電腦上的Git倉庫 遠程倉庫&#xff1a;遠程服務器上的Git倉庫 倉庫之間的運轉如下圖&#xff1a; commit&#xff1a;提交&#xff…

Decoupled Knowledge Distillation解耦知識蒸餾

Decoupled Knowledge Distillation解耦知識蒸餾 現有的蒸餾方法主要是基于從中間層提取深層特征&#xff0c;而忽略了Logit蒸餾的重要性。為了給logit蒸餾研究提供一個新的視角&#xff0c;我們將經典的KD損失重新表述為兩部分&#xff0c;即目標類知識蒸餾&#xff08;TCKD&a…

c++之旅——第四彈

大家好啊&#xff0c;這里是c之旅第三彈&#xff0c;跟隨我的步伐來開始這一篇的學習吧&#xff01; 如果有知識性錯誤&#xff0c;歡迎各位指正&#xff01;&#xff01;一起加油&#xff01;&#xff01; 創作不易&#xff0c;希望大家多多支持哦&#xff01; 本篇文章的主…

如何對比 MySQL 主備數據的一致性?

隨著業務范圍的擴大&#xff0c;很多企業為了保障核心業務的高可用性&#xff0c;選擇了 MySQL 主從架構&#xff0c;這一套方案通常具備主備數據同步、數據備份與恢復、讀寫分離、高可用切換等特性&#xff0c;是一種相當成熟可靠的數據庫架構方案。然而這套方案在特定情況下可…

Redis小白入門教程

Redis入門教程 1. Redis入門1.1 Redis簡介1.2 Redis服務啟動與停止1.2.1 Redis下載1.2.2 服務啟動命令1.2.3 客戶端連接命令1.2.4 修改Redis配置文件 2. Redis數據類型2.1 五種常用數據類型介紹2.1.1 字符串操作命令2.1.2 哈希操作命令2.1.3 列表操作命令2.1.4 集合操作命令2.1…

雙周回顧#006 - 這三個月

斷更啦~~ 上次更新時間 2023/11/23, 斷更近三個月的時間。 先狡辯下&#xff0c;因為忙、著實忙。因為忙&#xff0c;心安理得給斷更找了個借口&#xff0c;批評下自己~~ 這三個月在做啥&#xff1f;跨部門援助&#xff0c;支援公司互聯網的 ToC 項目&#xff0c;一言難盡。 …

智能時代:人工智能引領未來創新

智能時代&#xff1a;人工智能引領未來創新 1. 人工智能的定義與特點 人工智能&#xff08;Artificial Intelligence&#xff0c;AI&#xff09;是指模擬、延伸和擴展人類智能的理論、方法、技術及應用系統的一門交叉學科。其特點包括學習能力、推理能力、感知能力和交互能力…

【C語言】InfiniBand 驅動mlx4_ib_init和mlx4_ib_cleanup

一、中文講解 這兩個函數是Linux內核模塊中對于Mellanox InfiniBand 驅動程序初始化和清理的函數。 mlx4_ib_init()函數是模塊初始化函數&#xff0c;使用__init宏標注&#xff0c;表示該函數只在模塊加載時運行一次。 函數執行的步驟如下&#xff1a; 1. 通過alloc_ordered_w…

數據結構——lesson5棧和隊列詳解

hellohello~這里是土土數據結構學習筆記&#x1f973;&#x1f973; &#x1f4a5;個人主頁&#xff1a;大耳朵土土垚的博客 &#x1f4a5; 所屬專欄&#xff1a;數據結構學習筆記 &#x1f4a5;對于順序表鏈表有疑問的都可以在上面數據結構的專欄進行學習哦~感謝大家的觀看與…

ElasticSearch開篇

1.ElasticSearch簡介 1.1 ElasticSearch&#xff08;簡稱ES&#xff09; Elasticsearch是用Java開發并且是當前最流行的開源的企業級搜索引擎。能夠達到實時搜索&#xff0c;穩定&#xff0c;可靠&#xff0c;快速&#xff0c;安裝使用方便。 1.2 ElasticSearch與Lucene的關…

Angular項目升級的一般步驟?

升級Angular項目是一個重要的任務&#xff0c;可以帶來性能改進、新功能和安全性增強等好處。以下是升級Angular項目的一般步驟&#xff1a; 1、備份項目文件&#xff1a; 在進行升級之前&#xff0c;務必對整個項目進行備份&#xff0c;以防意外情況發生。 2、查看當前版本&…

如何快速遷移其他云服務器中的網站數據到騰訊云輕量應用服務器中?教你使用寶塔Linux面板遷移網站

要快速遷移其他云服務器中的網站數據到騰訊云輕量應用服務器中&#xff0c;可以遵循以下步驟&#xff1a; 準備遷移前的工作&#xff1a;首先&#xff0c;確保你已經有了從其他云服務器到騰訊云輕量應用服務器的數據備份。這一步是為了在遷移過程中避免數據丟失或損壞。 使用寶…

模擬器抓HTTP/S的包時如何繞過單向證書校驗(XP框架)

模擬器抓HTTP/S的包時如何繞過單向證書校驗&#xff08;XP框架&#xff09; 逍遙模擬器無法激活XP框架來繞過單向的證書校驗&#xff0c;如下圖&#xff1a; ?? 解決辦法&#xff1a; 安裝JustMePlush.apk安裝Just Trust Me.apk安裝RE管理器.apk安裝Xposedinstaller_逍遙64位…

智能邊緣小站 CloudPond(低延遲、高帶寬和更好的數據隱私保護)

智能邊緣小站 CloudPond(低延遲、高帶寬和更好的數據隱私保護) 邊緣小站的主要功能是管理用戶在線下部署的整機柜設施&#xff0c;一個邊緣小站關聯一個華為云指定的區域和一個用戶指定的場地&#xff0c;相關的資源運行狀況監控等。 邊緣計算 邁入5G和AI時代&#xff0c;新…

利用redis實現秒殺功能

6、秒殺優化 這個是 圖靈 的redis實戰里面的一個案例 6.1 秒殺優化-異步秒殺思路 我們來回顧一下下單流程 當用戶發起請求&#xff0c;此時會請求nginx&#xff0c;nginx會訪問到tomcat&#xff0c;而tomcat中的程序&#xff0c;會進行串行操作&#xff0c;分成如下幾個步驟…

基于單片機的紅外遙控解碼程序設計與實現

摘要:該文介紹基于士蘭半導體芯片(SC6122)的紅外發射遙控器,通過單片機解碼程序,實現紅外遙控信號的解碼和接收。紅外接收頭與單片機特定的引腳連接,通過設置單片機定時計數器,采樣來自紅外接收頭的高、低電平寬度解碼遙控信號。該解碼程序設計主要應用在LED數碼顯示控制…