C語言:指針(4)

1. 回調函數

回調函數就是指通過函數指針調用的函數。

如果將函數指針作為參數傳遞給另一個函數,另一個函數根據指針來調這個函數,那么被調用的函數就是回調函數。回調函數不是由這個函數的實現方直接調用,而是在特定的條件下由另一方調用的。

例如在指針(3)中,我們將多個函數的地址放在函數指針數組中,根據不同的選擇來對輸入的x和y執行相應的計算,這里就是采用的就是回調函數的功能。

2.?qsort使用舉例

2.1 qsort函數

在 C 語言中,qsort是標準庫<stdlib.h>提供的快速排序函數,用于對數組進行排序。其函數原型如下:

void qsort(void *base, size_t nmemb, size_t size,int (*compar)(const void *, const void *));

其中:

base是要排序的數組首元素的地址

nmemb是數組中元素的個數

size是每個元素的大小,單位為字節

compar是指比較函數的指針,用來定義排序規則

2.2 利用qsort函數排序整型數據

qsort會根據傳遞的函數指針所指向的那個函數的返回值來排序,例如兩個值a,b進行比較:

當返回值為負時,a就會排在b前面;返回值為正時,a排在b后面;返回值為0時,qsort會將這兩個值視為相等,但并不會保證相等元素排序與原始排序相同,例如:原始排序是 a? b,a在前,而qsort排序后可能會是b? a,即相等的元素排序后的相對位置不一定與原始位置相同。

知道這些我們可以利用qsort函數做一個簡單的排序,讓一個數組中的元素按升序排序:

#include <stdio.h>
#include <stdlib.h>
int i;int cmp(const void* p1,const void* p2)
{return (*(int *)p1 - *(int *)p2);
}
int main()
{int arr[] = {1,4,3,6,8,9,7,2,5,0};int num = sizeof(arr)/ sizeof(arr[0]);int sz = sizeof(arr[0]);qsort(arr,num,sz,cmp);for(i = 0;i < num;i++){printf("%d ",arr[i]);}return 0;
}
0 1 2 3 4 5 6 7 8 9 

我們可以看到輸出結果與預期一致,qsort正確得進行了排序。

另外,我們可以看到我們定義的cmp函數中,在進行運算前前面先將指針p1與p2的類型先強制轉換為了int *,這是因為void *雖然可以接受各種類型的指針,但是卻不能直接使用,必須先進行強制類型轉換。這里因為我們希望是升序,所以返回p1減去p2的值。若p1 < p2,返回值為負,p1排在p2前;若p1 > p2,返回值為正,p1排在p2后。如果我們想要實現降序,只需要將cmp函數體內p1與p2的位置互換或者是在計算表達式前加上 - ,改變正負即可。

2.3?使用qsort排序結構數據

現在我們嘗試利用qsort函數來對結構數據進行排序,例如:

#include <stdio.h>
#include <stdlib.h>
int i;
struct Stu
{char name[10];int age;
};
int cmp_by_name(const void *p1,const void *p2)
{return strcmp(((struct Stu*)p1)->name,((struct Stu*)p2)->name);
}int main()
{struct Stu s[] = {{"zhangsan",20},{"lisi",23},{"wangwu",19}};int len = sizeof(s)/ sizeof(s[0]);int sz = sizeof(s[0]);qsort(s,len,sz,cmp_by_name);for(i = 0;i < len;i++){printf("%s\n",s[i].name);}return 0;
}
lisi
wangwu
zhangsan

根據打印結果,我們發現,qsort成功按照字母順序進行了排序。同樣的,我們也可以寫出cmp_by_age函數,讓qsort按照年齡來進行排序。

另外,我在定義函數cmp_by_name時,在函數體內部用 -> 來訪問結構中的name,而在打印時使用的是 . 。這是因為,我在定義函數的返回值時,這里的數據是指針類型,只能用->來訪問,而在打印時則是直接訪問結構,所以要使用 . 來訪問結構中數據。因此,如果我們不想使用->,也可以先對指針進行解引用操作然后再使用 . 來訪問數據。

3. qsort函數的模擬實現

學習了qsort函數的使用方法后,我們現在嘗試自己寫代碼來模擬實現qsort函數。

例如,我們用冒泡排序的方法法來模擬qsort函數。

那么。根據上面的代碼的經驗,我們可以得到下面的代碼:

#include <stdio.h>int cmp(const void *p1,const void *p2)
{return (*(int*)p1 - *(int*)p2);
}
void swap(void *p1,void *p2,int sz)
{int i;char temp;for(i = 0;i < sz;i++){temp = *((char *)p1 + i);*((char *)p1 + i) = *((char *)p2 + i);*((char *)p2 + i) = temp;}
}void bubble(void* base,int num,int sz,int (*cmp)(const void *p1,const void *p2))
{int i,j;for(i = 0;i < num - 1;i++){for(j = 0;j < num - 1 - i;j++){if(cmp(base + j * sz,base + (j + 1) * sz) < 0){swap(base + j * sz,base + (j + 1) * sz,sz);}}}
}
int main()
{int i;int arr[] = {1,5,3,7,9,4,0,2,6,8};int num = sizeof(arr)/ sizeof(arr[0]);int sz = sizeof(arr[0]);bubble(arr,num,sz,cmp);for(i = 0;i < num;i++){printf("%d ",arr[i]);}return 0;
}
9 8 7 6 5 4 3 2 1 0 

這里主體的邏輯和上面的代碼一樣,值得一提的是swap這個函數。

在定義這個函數的時候我們是將指針類型強制轉換為char * 類型,這樣處理的好處是:我們為了模擬qsort函數實現通用設計,在不知道接受的數據類型的前提下,將指針類型強制轉換為char *類型,而char *類型指針和 i 相加時只會跳過 i 個字節,這樣能夠充分交換每一個字節中的數據,防止遺漏,保證了數據的準確性。?? ? ? ??

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

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

相關文章

vue--video使用動態src時,視頻不更新

問題描述 在 Vue項目中&#xff0c;嘗試動態更新 標簽的 元素 src 屬性來切換視頻時&#xff0c;遇到了一個問題&#xff1a;即使 src 已更改&#xff0c;瀏覽器仍不顯示視頻。 <template><video width"100%" height"100%" controlspause"…

計算機視覺--opencv(代碼詳細教程)(一)

在計算機視覺的廣袤領域中&#xff0c;OpenCV 是一座極為關鍵的里程碑。無論是在前沿的學術研究&#xff0c;還是在蓬勃發展的工業界&#xff0c;OpenCV 憑借其強大的功能與高效的性能&#xff0c;為開發者提供了豐富的圖像處理和計算機視覺算法&#xff0c;助力無數項目落地。…

物聯網通訊協議-MQTT、Modbus、OPC

引言在物聯網迅速發展的今天&#xff0c;設備間的通信協議扮演著至關重要的角色。它們是不同設備、系統之間實現數據交換的橋梁。本文將詳細介紹三種在物聯網領域廣泛應用的通訊協議——MQTT、Modbus和OPC&#xff0c;包括它們的基礎概念、特點及在C#中的實現方法。一、MQTT協議…

牛客周賽R104 小紅的矩陣不動點

D-小紅的矩陣不動點_牛客周賽 Round 104 賽時這道題卡了一段時間&#xff0c;賽時代碼如下&#xff1a; #include<bits/stdc.h> using namespace std; int ans,h; int a[505][505]; signed main(){ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);int n,m;cin>…

Rust面試題及詳細答案120道(19-26)-- 所有權與借用

《前后端面試題》專欄集合了前后端各個知識模塊的面試題&#xff0c;包括html&#xff0c;javascript&#xff0c;css&#xff0c;vue&#xff0c;react&#xff0c;java&#xff0c;Openlayers&#xff0c;leaflet&#xff0c;cesium&#xff0c;mapboxGL&#xff0c;threejs&…

Jenkins + SonarQube 從原理到實戰三:SonarQube 打通 Windows AD(LDAP)認證與踩坑記錄

前言 在前兩篇文章中&#xff0c;已經介紹了 SonarQube 的部署 以及 通過 sonar-cxx 插件實現 C/C 代碼掃描。 本篇將重點講 如何讓 SonarQube 對接 Windows AD&#xff08;LDAP&#xff09;&#xff0c;實現域賬號登錄和基于 AD 組的權限管理。 一、背景與需求分析 需求分析…

[AI React Web] 包與依賴管理 | `axios`庫 | `framer-motion`庫

第七章&#xff1a;包與依賴管理 在我們使用open-lovable的旅程中&#xff0c;已經探索了它如何管理對話狀態&#xff08;第一章&#xff1a;對話狀態管理&#xff09;、將創意轉化為可運行代碼&#xff08;第二章&#xff1a;AI代碼生成管道&#xff09;、如何在安全的虛擬環…

PanSou 一款開源網盤搜索項目,集成前后端,一鍵部署,開箱即用

PanSou 網盤搜索API PanSou是一個高性能的網盤資源搜索API服務&#xff0c;支持TG搜索和自定義插件搜索。系統設計以性能和可擴展性為核心&#xff0c;支持并發搜索、結果智能排序和網盤類型分類。 項目地址&#xff1a;https://github.com/fish2018/pansou 特性&#xff08…

java爬蟲實戰

本人目前在做魚皮的《智能協同云圖庫》&#xff0c;涉及到了以圖搜圖圖片爬取&#xff0c;雖然以前有爬過圖片&#xff0c;但是用的都是別人現成的代碼&#xff0c;不怎么去理解為什么要這樣做&#xff0c;這次有在嘗試理解每一個步驟。本人基礎極差&#xff0c;屬于一點基礎也…

深入詳解C語言的循環結構:while循環、do-while循環、for循環,結合實例,講透C語言的循環結構

&#x1f525;個人主頁&#xff1a;艾莉絲努力練劍 ?專欄傳送門&#xff1a;《C語言》、《數據結構與算法》、C語言刷題12天IO強訓、LeetCode代碼強化刷題、C/C干貨分享&學習過程記錄 &#x1f349;學習方向&#xff1a;C/C方向 ??人生格言&#xff1a;為天地立心&#…

北京-4年功能測試2年空窗-報培訓班學測開-第七十四天-線下面試-聊的很滿意但可能有風險-等信吧

今天沒去教室&#xff0c;因為下午有個線下面試。其實是可以去教室的&#xff0c;但我實在太焦慮了&#xff0c;我覺得去了教室我心情會更不好&#xff0c;什么都干不下去&#xff0c;所以我選擇不去早上依舊是帶著滿滿焦慮起來的&#xff0c;會覺得自己的一切都不令自己滿意&a…

在ubuntu服務器下安裝cuda和cudnn(筆記)

目錄 0 引言 1 相關環境查詢 2 安裝cuda 2.1 下載并安裝 2.2 安裝選項配置 2.3 驗證安裝 3 安裝cudnn 3.1 下載 3.2 解壓 3.3 刪除舊版本 cuDNN 3.4 復制新文件到 CUDA 目錄 3.5 設置文件權限 3.6 創建軟鏈接 3.7 驗證安裝 0 引言 我在使用服務器的cuda11.8的時…

docker安裝centos

docker庫地址https://hub.docker.com/ 嘗試使用centos7試了幾次超時 換了個版本就可以了 docker pull centos:centos7.9.2009有時候需要更新資源地址 可以使用 vim /etc/docker/daemon.json配置其他資源地址 {"registry-mirrors": ["http://hub-mirror.c.163…

內容索引之word轉md工具 - markitdown

切分文檔構建RAG庫過程中&#xff0c;langchain、llamaindex更期望處理latex、md類帶有顯式結構文檔。 langchain、llamaindex切分word&#xff0c;有可能將段落中間截斷&#xff0c;導致切分后的塊語義不完整。 所以&#xff0c;需要先將word轉化為md格式&#xff0c;然后再…

MaxKB+合合信息TextIn:通過API實現PDF掃描件的文檔審核

上海合合信息科技股份有限公司&#xff08;以下簡稱為合合信息&#xff09;是一家深耕人工智能、OCR&#xff08;光學字符識別&#xff09;及商業大數據技術領域的科技企業。該公司擁有領先的智能文字識別技術&#xff0c;其名片全能王&#xff08;CamCard&#xff09;、掃描全…

MyBatis 核心入門:從概念到實戰,一篇掌握簡單增刪改查

目錄 一、什么是 MyBatis&#xff1f;為什么要用它&#xff1f; 二、MyBatis 核心概念&#xff08;通俗理解&#xff09; 1.SqlSessionFactory 2.SqlSession 3.Mapper接口 4.映射文件&#xff08;XML&#xff09; 三、手把手搭建第一個 MyBatis 項目 1. 準備工作 2. 核心配置文…

數據結構初階(12)排序算法—插入排序(插入、希爾)(動圖演示)

2. 常見排序算法的實現2.0 十大排序算法2.1 插入排序 2.1.1 基本思想直接插入排序是一種簡單的插入排序法&#xff1a;基本思想把待排序的記錄按其關鍵碼值的大小逐個插入到一個已經排好序的有序序列中。直到所有的記錄插入完為止&#xff0c;得到一個新的有序序列 。 比 挪 (…

MySQL優化常用的幾個方法

本實例是對慢sql從2萬優化到5千優化方法的匯總。 首先貼上優化效果&#xff1a;1、更新數據時使用ID更新&#xff1b;2、"分頁/輪詢"查詢時先獲取符合數據要求主鍵的最大和最小ID&#xff0c;然后WHERE條件增加ID步增查詢&#xff1b;3、檢查SQL是否命中WHERE條件&am…

深入解析 AUTOSAR:汽車軟件開發的革命性架構

引言在汽車智能化、網聯化、電動化浪潮席卷全球的今天&#xff0c;汽車電子系統的復雜性與日俱增。傳統“煙囪式”的 ECU 開發模式&#xff08;各供應商獨立開發軟硬件&#xff09;帶來了巨大的兼容性、復用性和維護成本挑戰。AUTOSAR&#xff08;AUTomotive Open System ARchi…

計算機視覺(opencv)實戰一——圖像本質、數字矩陣、RGB + 圖片基本操作(灰度、裁剪、替換等)

OpenCV 入門教程&#xff1a; OpenCV&#xff08;Open Source Computer Vision Library&#xff09;是一個開源的計算機視覺庫&#xff0c;廣泛應用于圖像處理、視頻分析、機器學習等領域。 在 Python 中&#xff0c;cv2 是 OpenCV 的主要接口模塊。本文將帶你一步步掌握 cv2…