程序詩篇里的靈動筆觸:指針繪就數據的夢幻藍圖<7>

在這里插入圖片描述

大家好啊,我是小象?(?òωó?)?
我的博客:Xiao Xiangζ?????

很高興見到大家,希望能夠和大家一起交流學習,共同進步
在這里插入圖片描述

今天我們一起來學習轉移表,回調函數,qsort…

目錄

  • 一、轉移表
    • 1.1 定義與原理
    • 1.3 優點
  • 二、回調函數是什么?
    • 1.1 原理
    • 1.2 使用方法
    • 1.3 優點
  • 三、qsort 使用舉例
    • 3.1 使用qsort函數排序整型數據
    • 3.2 使用qsort排序結構數據
  • 四、結尾

一、轉移表

在 C 語言中,轉移表(Jump Table)是一種用于實現多路分支選擇的技術,也被稱為跳轉表或分支表。

1.1 定義與原理

轉移表本質上是一個函數指針數組,數組中的每個元素都是一個指向函數的指針。它的原理是通過計算索引值來選擇調用數組中的某個函數指針,從而實現根據不同條件跳轉到不同代碼段的功能,類似于根據索引查找表中的內容并執行相應操作。

1.3 優點

代碼清晰簡潔:
相比于使用大量的if-else語句或switch語句嵌套,轉移表能使代碼結構更加清晰,邏輯更加直觀。尤其是在處理多個分支情況時,代碼的可讀性更高。
高效性:
在執行多路分支選擇時,轉移表的查找和跳轉操作通常比復雜的if-else或switch判斷更快。因為它主要通過數組索引直接定位到目標函數,而不需要逐個進行條件判斷。
可擴展性:
當需要添加新的分支或功能時,只需在轉移表中添加相應的函數指針,并實現對應的函數邏輯即可,對原有代碼的改動較小,易于維護和擴展。

舉例:計算器的?般實現:

#include <stdio.h>
int add(int a, int b)
{return a + b;
}
int sub(int a, int b)
{return a - b;
}
int mul(int a, int b)
{return a * b;
}
int div(int a, int b)
{return a / b;
}
int main()
{int x, y;int input = 1;int ret = 0;do{printf("*************************\n");printf(" 1:add 2:sub \n");printf(" 3:mul 4:div \n");printf(" 0:exit \n");printf("*************************\n");printf("請選擇:");scanf("%d", &input);switch (input){case 1:printf("輸?操作數:");scanf("%d %d", &x, &y);ret = add(x, y);printf("ret = %d\n", ret);break;case 2:printf("輸?操作數:");scanf("%d %d", &x, &y);ret = sub(x, y);printf("ret = %d\n", ret);break;case 3:printf("輸?操作數:");scanf("%d %d", &x, &y);ret = mul(x, y);printf("ret = %d\n", ret);break;case 4:printf("輸?操作數:");scanf("%d %d", &x, &y);ret = div(x, y);printf("ret = %d\n", ret);break;case 0:printf("退出程序\n");break;default:printf("選擇錯誤\n");break;}} while (input);return 0;
}

使?函數指針數組的實現:

#include <stdio.h>
int add(int a, int b)
{return a + b;
}
int sub(int a, int b)
{return a - b;
}
int mul(int a, int b)
{return a * b;
}
int div(int a, int b)
{return a / b;
}
int main()
{int x, y;int input = 1;int ret = 0;int(*p[5])(int x, int y) = { 0, add, sub, mul, div }; //轉移表do{printf("*************************\n");printf(" 1:add 2:sub \n");printf(" 3:mul 4:div \n");printf(" 0:exit \n");printf("*************************\n");printf("請選擇:");scanf("%d", &input);if ((input <= 4 && input >= 1)){printf("輸?操作數:");scanf("%d %d", &x, &y);ret = (*p[input])(x, y);printf("ret = %d\n", ret);}else if (input == 0){printf("退出計算器\n");}else{printf("輸?有誤\n");}} while (input);return 0;
}

二、回調函數是什么?

回調函數是一個作為參數傳遞給另一個函數的函數,而接收回調函數作為參數的函數會在合適的時候調用這個傳遞進來的函數。簡單來說,就是 A 函數將 B 函數作為參數傳遞給 C 函數,C 函數在某個時刻調用 B 函數,此時 B 函數就是回調函數。

1.1 原理

回調函數的核心原理基于函數指針。在 C 語言中,函數名本質上代表該函數的入口地址,而函數指針則可以存儲這個地址。通過將函數指針作為參數傳遞給另一個函數,接收該參數的函數就可以在需要的時候通過這個指針調用對應的函數。

1.2 使用方法

以下是使用回調函數的基本步驟:
定義回調函數:首先要定義一個符合特定參數和返回值要求的函數,這個函數將作為回調函數使用。
定義接收回調函數作為參數的函數:該函數需要有一個函數指針類型的參數,用于接收回調函數的地址。
調用接收回調函數的函數:在調用時,將回調函數的名稱作為參數傳遞給接收回調函數的函數。

1.3 優點

靈活性:通過回調函數,可以在不修改接收回調函數的函數的源代碼的情況下,改變其行為。只需要傳遞不同的回調函數,就可以實現不同的功能。
代碼復用:可以將一些通用的邏輯封裝在接收回調函數的函數中,而將具體的處理邏輯放在回調函數中。這樣,不同的回調函數可以復用接收回調函數的函數的代碼。
異步編程:在異步編程中,回調函數非常有用。當某個操作完成時,可以通過回調函數通知調用者進行后續處理。

//使?回調函數改造前
#include <stdio.h>
int add(int a, int b)
{return a + b;
}
int sub(int a, int b)
{return a - b;
}
int mul(int a, int b)
{return a * b;
}
int div(int a, int b)
{return a / b;
}
int main()
{int x, y;int input = 1;int ret = 0;do{printf("*************************\n");printf(" 1:add 2:sub \n");printf(" 3:mul 4:div \n");printf("*************************\n");printf("請選擇:");scanf("%d", &input);switch (input){case 1:printf("輸?操作數:");scanf("%d %d", &x,&y);ret = add(x, y);printf("ret = %d\n",ret);break;case 2:printf("輸?操作數:");scanf("%d %d", &x,&y);ret = sub(x, y);printf("ret = %d\n",ret);break;case 3:printf("輸?操作數:");scanf("%d %d", &x,&y);ret = mul(x, y);printf("ret = %d\n",ret);break;case 4:printf("輸?操作數:");scanf("%d %d", &x,&y);ret = div(x, y);printf("ret = %d\n",ret);break;case 0:printf("退出程序\n");break;default:printf("選擇錯誤\n");break;}} while (input);return 0;

三、qsort 使用舉例

qsort 是 C 標準庫中用于對數組進行快速排序的函數,它基于快速排序算法實現,能對任意類型的數組進行排序。

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

#include <stdio.h>
//qosrt函數的使?者得實現?個?較函數
int int_cmp(const void* p1, const void* p2)
{return (*(int*)p1 - *(int*)p2);
}
int main()
{int arr[] = { 1, 3, 5, 7, 9, 2, 4, 6, 8, 0 };int i = 0;qsort(arr, sizeof(arr) / sizeof(arr[0]), sizeof(int), int_cmp);for (i = 0; i < sizeof(arr) / sizeof(arr[0]); i++){printf("%d ", arr[i]);}printf("\n");return 0;
}

3.2 使用qsort排序結構數據


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;
}
//strcmp - 是庫函數,是專??來?較兩個字符串的??的
//假設按照名字來?較
int cmp_stu_by_name(const void* e1, const void* e2)
{return strcmp(((struct Stu*)e1)->name, ((struct Stu*)e2)->name);
}
//按照年齡來排序
void test2()
{struct Stu s[] = { {"zhangsan", 20}, {"lisi", 30}, {"wangwu", 15} };int sz = sizeof(s) / sizeof(s[0]);qsort(s, sz, sizeof(s[0]), cmp_stu_by_age);
}
//按照名字來排序
void test3()
{struct Stu s[] = { {"zhangsan", 20}, {"lisi", 30}, {"wangwu", 15} };int sz = sizeof(s) / sizeof(s[0]);qsort(s, sz, sizeof(s[0]), cmp_stu_by_name);
}
int main()
{test2();test3();return 0;
}

注意事項
比較函數的實現:比較函數的實現要正確,確保能準確反映元素之間的大小關系。不同的比較函數實現可以實現升序、降序或其他自定義的排序規則。
類型轉換:在比較函數中,由于 qsort 函數的通用性,傳入的參數是 const void *
類型,需要將其轉換為實際的數據類型才能進行比較操作。 穩定性:qsort
是不穩定的排序算法,即相等元素的相對順序在排序后可能會改變。如果需要穩定的排序算法,可以考慮使用其他排序函數或自行實現穩定排序。
性能:qsort 平均時間復雜度為 (O(n log n)),但在最壞情況下時間復雜度為
(O(n^2))。不過在大多數實際應用場景中,它的性能表現良好。

四、結尾

這一課的內容就到這里了,下節課繼續學習指針的其他一些知識
如果內容有什么問題的話歡迎指正,有什么問題也可以問我!
在這里插入圖片描述

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

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

相關文章

使用Jenkins實現鴻蒙HAR應用的自動化構建打包

使用Jenkins實現鴻蒙HAR應用的自動化構建打包 在軟件開發領域&#xff0c;自動化構建是提高開發效率和確保代碼質量的重要手段。特別是在鴻蒙&#xff08;OpenHarmony&#xff09;應用開發中&#xff0c;自動化構建更是不可或缺。本文將詳細介紹如何使用Jenkins命令行工具實現…

漏洞分析 Spring Framework路徑遍歷漏洞(CVE-2024-38816)

漏洞概述 VMware Spring Framework是美國威睿&#xff08;VMware&#xff09;公司的一套開源的Java、JavaEE應用程序框架。該框架可幫助開發人員構建高質量的應用。 近期&#xff0c;監測到Spring Framework在特定條件下&#xff0c;存在目錄遍歷漏洞&#xff08;網宿評分&am…

筆記:理解借貸相等的公式

強烈推薦非會計人士&#xff0c;快速了解會計看這個系列的視頻&#xff0c;其中比較燒腦的“借貸相等”公式&#xff0c;這個視頻講解的不錯&#xff1a; 4.小白財務入門-借貸記賬法_嗶哩嗶哩_bilibili 比如這里&#xff0c;錢在銀行卡重&#xff0c;所以銀行存款就是借方…

Java算法技術文章:深入解析排序、搜索與數據結構

引言 在軟件開發的世界里&#xff0c;算法不僅是程序設計的基礎&#xff0c;更是提升軟件性能、優化用戶體驗的關鍵。Java&#xff0c;作為一種廣泛使用的編程語言&#xff0c;提供了豐富的API和標準庫來支持各種算法的實現。本文將深入探討Java中的排序算法、搜索算法以及一些…

Android15音頻進階之MediaRecorder支持通道(一百零五)

簡介: CSDN博客專家、《Android系統多媒體進階實戰》一書作者 新書發布:《Android系統多媒體進階實戰》?? 優質專欄: Audio工程師進階系列【原創干貨持續更新中……】?? 優質專欄: 多媒體系統工程師系列【原創干貨持續更新中……】?? 優質視頻課程:AAOS車載系統+…

個人 Vite 構建性能分析插件開發實踐

Vite 構建分析插件開發實踐 一、開發背景 在個人項目開發中遇到以下問題&#xff1a; &#x1f552; 構建時間波動大&#xff08;30%&#xff09;&#x1f50d; 難以定位耗時模塊&#x1f4c8; 缺乏構建進度反饋 開發目標&#xff1a; 實現模塊級耗時分析提供實時進度預測識…

【Spring】什么是Spring?

什么是Spring&#xff1f; Spring是一個開源的輕量級框架&#xff0c;是為了簡化企業級開發而設計的。我們通常講的Spring一般指的是Spring Framework。Spring的核心是控制反轉(IoC-Inversion of Control)和面向切面編程(AOP-Aspect-Oriented Programming)。這些功能使得開發者…

學習筆記:機器學習中的數學原理(一)

1. 集合 集合分為有限集和無限集&#xff1b; 對于有限集&#xff0c;兩集合元素數相等即為等勢&#xff1b; 對于無限集&#xff0c;兩集合元素存在一一映射關系即為等勢&#xff1b; 無限集根據是否與正整數集等勢分為可數集和不可數集。 2. sigmoid函數&#xff08;也叫…

【信息系統項目管理師-案例真題】2016下半年案例分析答案和詳解

更多內容請見: 備考信息系統項目管理師-專欄介紹和目錄 文章目錄 試題一【問題1】4 分【問題2】12 分【問題3】3 分【問題4】6 分試題二【問題1】3 分【問題2】4 分【問題3】8 分【問題4】5 分【問題5】5 分試題三【問題1】4 分【問題2】8 分【問題3】5 分【問題4】8 分試題一…

基于javaweb的SpringBoothis智能醫院管理系統(源碼+文檔+部署講解)

&#x1f3ac; 秋野醬&#xff1a;《個人主頁》 &#x1f525; 個人專欄:《Java專欄》《Python專欄》 ??心若有所向往,何懼道阻且長 文章目錄 運行環境開發工具適用功能說明一、項目運行 環境配置&#xff1a; 運行環境 Java≥8、MySQL≥5.7、Node.js≥14 開發工具 后端&…

JS實現燈光閃爍效果

在 JS中&#xff0c;我們可以實現燈光閃爍效果&#xff0c;這里主要用 setInterval 和 clearInterval 兩個重要方法。 效果圖 源代碼 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>燈閃爍效果<…

Linux ltrace跟蹤入門

文章目錄 背景ltrace原理ltrace使用跟蹤程序調用庫函數跟蹤指定pid進程調用 參考 本文介紹ltrace跟蹤 背景 ltrace 會攔截并記錄正在執行的進程所調用的動態庫調用以及該進程接收到的信號&#xff0c;它還可以攔截并打印程序執行的系統調用。 其代碼位置在&#xff1a;https:/…

PCA9685 16路PWM 控制板 STM32F103 驅動

PCA9685 擁有16路PWM&#xff0c;通過 IIC 與 STM32 進行通信&#xff0c;以下驅動代碼已通過測試&#xff0c;你可以進行更多代碼優化 #include "pca9685.h"// 向 PCA9685 寫入一個字節數據 static void PCA9685_write8( uint8_t addr, uint8_t d) {while (I2C_Get…

使用 Apache Spark 進行大數據分析

使用 Apache Spark 進行大數據分析 環境準備 為了能夠在本地環境中運行Spark程序&#xff0c;需要先完成環境搭建。確保已經安裝了Jupyter Notebook和Apache Spark&#xff0c;并完成了兩者之間的集成。 創建 SparkSession 在 Python 中使用 PySpark 時&#xff0c;通常會創…

2025 專業的物聯網軟件開發公司有哪些

物聯網&#xff08;Internet of Things&#xff0c;簡稱IoT&#xff09;具有多個顯著的優勢&#xff0c;主要包括提高效率、節省成本、數據收集與分析、自動化控制、改善用戶體驗、增強決策能力和創新業務模式?。2025&#xff0c;有哪些比較專業的物聯網開發公司呢&#xff1f…

7.PPT:“中國夢”學習實踐活動【20】

目錄 NO1234? NO5678? NO9\10\11 NO1234 考生文件夾下創建一個名為“PPT.pptx”的新演示文稿Word素材文檔的文字&#xff1a;復制/挪動→“PPT.pptx”的新演示文稿&#xff08;藍色、黑色、紅色&#xff09; 視圖→幻燈片母版→重命名&#xff1a;“中國夢母版1”→背景樣…

學習筆記十九:K8S生成pod過程

K8S生成pod過程 流程圖具體生成過程用戶提交 Pod 定義API Server 處理請求調度器分配節點&#xff08;Scheduling&#xff09;目標節點上的 Pod 創建網絡配置狀態上報與監控控制器管理&#xff08;Controller Manager&#xff09;就緒與服務發現 關鍵錯誤場景高級特性 流程圖 具…

封裝descriptions組件,描述,靈活

效果 1、組件1&#xff0c;dade-descriptions.vue <template><table><tbody><slot></slot></tbody> </table> </template><script> </script><style scoped>table {width: 100%;border-collapse: coll…

21.2.6 字體和邊框

版權聲明&#xff1a;本文為博主原創文章&#xff0c;轉載請在顯著位置標明本文出處以及作者網名&#xff0c;未經作者允許不得用于商業目的。 通過設置Rang.Font對象的幾個成員就可以修改字體&#xff0c;設置Range.Borders就可以修改邊框樣式。 【例 21.6】【項目&#xff…

FPGA VGA timing

概念 VGA(Video Graphics Array)時序是控制VGA接口顯示圖像的關鍵參數,它主要包括行時序和場時序兩部分。以下是對VGA時序的詳細解釋: 一、VGA接口簡介 VGA接口是IBM公司在1987年推出的一種使用模擬信號的視頻傳輸標準,具有成本低、結構簡單、應用靈活等優點,至今仍被廣…