C語言 ——— 函數

目錄

函數是什么

庫函數

學習使用 strcpy 庫函數

自定義函數

寫一個函數能找出兩個整數中的最大值?

寫一個函數交換兩個整型變量的內容

牛刀小試

寫一個函數判斷一個整數是否是素數

寫一個函數判斷某一年是否是閏年

寫一個函數,實現一個整型有序數組的二分查找

函數的嵌套調用

函數的鏈式訪問

一段有趣的代碼

函數的聲明、調用和定義

函數的定義

函數調用

函數聲明?

函數遞歸?

什么是遞歸

遞歸的兩個必要條件?

一個簡單的遞歸

牛刀小試

要求使用函數遞歸實現:接受一個無符號整型值,按照順序打印他的每一位

要求寫一個函數:能實現求字符串的長度?

編寫函數,不允許創建臨時變量,求字符串的長度


函數是什么

在 C 語言里,函數和數學中的函數有相似之處

以數學函數?f(x)=2x+1?為例,當?x?取值不同時,函數會有不同的結果。比如?x=2?時,將?x=2?代入函數可得?f(2)=2×2+1=5;當?x=3?時,代入后得到?f(3)=2×3+1=7

同樣,這個數學函數也能用 C 語言中的函數來表示。我們可以定義一個 C 語言函數,讓它接收一個參數,在函數內部按照?2x+1?的規則進行計算并返回結果,從而實現與這個數學函數相同的功能

代碼演示:

int f(int x)
{return 2*x + 1;
}int main()
{int x = 0;scanf("%d", &x);printf("%d\n", f(x));return 0;
}

庫函數

在 C 語言里,為了方便使用常用功能,會將這些功能封裝成一個個函數,這些函數被稱為庫函數,像?printf?函數、scanf?函數、strlen?函數等都屬于庫函數

需要注意的是,C 語言本身并沒有直接實現這些庫函數,而是制定了 C 語言的標準以及庫函數的約定。比如對于?scanf?函數,C 語言標準規定了它的功能、函數名、參數和返回值等

而庫函數的具體實現通常由編譯器來完成,常見的編譯器如 VS2022 編譯器、gcc 編譯器等,它們會依據 C 語言標準對庫函數進行具體的編碼實現,這樣開發者就能在編程時直接使用這些庫函數了

學習使用 strcpy 庫函數

C/C++ 中的庫函數信息,都可以在?cplusplus.com?網站?上查詢到

如果想學習或了解某個庫函數的用法、參數含義及功能,直接在這個網站搜索對應的函數名即可,它是編程中查閱庫函數的實用資源

strcpy 庫函數

“destination” 代表目的地字符串,“source” 代表源頭字符串。當一個函數的返回值類型為?char*?時,意味著該函數返回的是目的地字符串的首地址

strcpy?是一個庫函數,從其文檔可知,它的功能是進行字符串拷貝。具體來說,就是把源頭字符串的數據復制到目的地字符串,并且會覆蓋目的地字符串原有的內容,同時還會將源頭字符串末尾的結束符?'\0'?也一同復制過去

若要在代碼中使用?strcpy?函數,需要包含相應的頭文件,頭文件代碼如下:

#include<string.h>

代碼演示:

char source[] =  "hello world";
char destination[] =  "xxxxxxxxxxxxxxxx";strcpy(destination, source);printf("%s\n", destination);

代碼驗證:


自定義函數

在編程中,自定義函數指的是開發者根據實際需求自己編寫的函數。它和 C 語言中的庫函數(如printfstrlen)一樣,都遵循相同的基本結構,包括:

  • 返回類型:函數執行完畢后輸出的數據類型(如intchar*);
  • 參數:函數執行時需要的輸入信息(可以沒有參數,也可以有多個);
  • 返回值:通過return語句返回的結果(若無需返回結果,返回類型為void

寫一個函數能找出兩個整數中的最大值?

代碼演示:?

int get_max(int a, int b)
{return a > b ? a : b;
}int main()
{int a = 0;int b = 0;scanf("%d %d", &a, &b);int max = get_max(a, b);printf("%d\n", max);return 0;
}

寫一個函數交換兩個整型變量的內容

代碼演示:

void Swap(int* a, int* b)
{int tmp = *a;*a = *b;*b = tmp;
}int main()
{int a = 0;int b = 0;scanf("%d %d", &a, &b);printf("交換前:a = %d;b = %d\n", a, b);Swap(&a, &b);printf("交換后:a = %d;b = %d\n", a, b);return 0;
}

在編寫函數交換兩個整型變量的值時,不能直接傳遞實參。這是因為在函數調用時,實參的值會被復制給形參,實參和形參分別占用不同的內存空間,也就是各自獨立的空間。在函數內部對形參進行操作,只會改變形參的值,而不會影響到實參原本的值

為了真正實現交換兩個實參的值,我們需要傳遞實參的地址。由于實參是?int?類型,所以函數的形參要使用?int*?類型來接收這些地址。int*?類型的變量可以存儲整型變量的地址。在函數內部,通過?*?這個解引用關鍵字,我們可以根據存儲的地址找到對應的實參,進而對實參的值進行修改,這樣就能實現兩個實參值的交換


牛刀小試

寫一個函數判斷一個整數是否是素數

代碼演示:

int is_prime(int tmp)
{if (tmp <= 1)return 0;for (int i = 2; i <= sqrt(tmp); i++){if (tmp % i == 0)return 0;}return 1;
}int main()
{int input = 0;scanf("%d", &input);if (is_prime(input))printf("is prime\n");elseprintf("not is prime\n");return 0;
}

代碼解析:

我們要編寫一個函數來判斷一個整數是否為素數。素數是指大于 1 且只能被 1 和自身整除的正整數。所以在判斷之前,首先要排除小于等于 0 的整數,因為它們顯然不符合素數的定義

該函數的返回規則是:返回 0 表示這個數不是素數,返回 1 表示這個數是素數

對于輸入的變量?input,我們需要判斷它是否為素數。判斷的方法是,用?input?對 2 到?input - 1?之間的數進行取模運算。可以使用?for?循環來遍歷這個區間內的所有數。如果在遍歷過程中,input?對某個數取模的結果為 0,那就說明?input?除了 1 和它本身之外,還能被其他數整除,那么它就不是素數,此時函數直接返回 0

不過,其實并不需要從 2 遍歷到?input - 1,只需要遍歷 2 到?sqrt(input)sqrt?是開平方函數)之間的數即可。這是因為如果一個數?input?不是素數,那么它一定可以分解為兩個因數?m?和?n,即?input = m * n,其中?m?和?n?中至少有一個小于等于?sqrt(input)。所以,只要檢查到?sqrt(input)?就可以判斷?input?是否為素數了

如果?for?循環執行完畢都沒有找到能整除?input?的數,那就說明?input?只能被 1 和它本身整除,即?input?是素數,此時函數返回 1

寫一個函數判斷某一年是否是閏年

代碼演示:

int is_leap_year(int year)
{if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0))return 1;elsereturn 0;
}int main()
{ int year = 0;scanf("%d", &year);is_leap_year(year);if (is_leap_year(year))printf("is leap year\n");elseprintf("not is leap year\n");return 0;
}

代碼解析:

閏年的判斷規則是能被 4 整除但不能被 100 整除,或能被 400 整除的年份

根據以上的規則編寫出對應的邏輯代碼,就能判斷某一年是否是潤年

寫一個函數,實現一個整型有序數組的二分查找

代碼演示:

int binary_search(int* parr, int size, int number)
{int left = 0;int right = size - 1;while (left <= right){int mid = (left + right) / 2;if (parr[mid] < number){left = mid + 1;}else if(parr[mid] > number){right = mid - 1;}else{return mid;}}return -1;
}int main()
{int arr[] = { 1,2,4,6,7,9,12,32,45,77,90 };int size = sizeof(arr) / sizeof(arr[0]);int input = 0;scanf("%d", &input);int ret = binary_search(arr, size, input);if (ret == -1)printf("number not found\n");elseprintf("number index is: %d\n", ret);return 0;
}

代碼解析:

我們要實現一個二分查找函數,二分查找是一種高效的查找算法,它的前提是數組必須是有序的。在函數調用時,需要傳遞三個參數:數組的指針?arr,用于訪問數組元素;數組的元素個數?size,這樣能確定查找范圍;要查找的整數?input,即我們要在數組中找到的目標值

函數的返回值規則是:如果在數組中找到了目標值?input,就返回該值在數組中的下標;如果沒有找到,就返回 -1,因為數組的下標最小是從 0 開始的, -1 可以作為一個明確的未找到的標識

  1. 初始化查找范圍:定義兩個變量,left?作為左下標,初始值設為 0,它指向數組的起始位置;right?作為右下標,初始值設為?size - 1,它指向數組的末尾位置
  2. 開始循環查找:使用?while?循環來進行查找,循環的條件是?left <= right。只要滿足這個條件,就說明還有元素沒有被檢查過,查找過程可以繼續
  3. 計算中間下標:在每次循環內部,計算中間元素的下標?mid,計算公式為?mid = (left + right) / 2。通過這個中間下標,我們可以將數組分成兩部分
  4. 比較中間元素與目標值
    • 如果?input?大于中間元素?arr[mid],說明目標值在數組的右半部分,此時更新?left?為?mid + 1,縮小查找范圍到右半部分
    • 如果?input?小于中間元素?arr[mid],說明目標值在數組的左半部分,此時更新?right?為?mid - 1,縮小查找范圍到左半部分
    • 如果?input?等于中間元素?arr[mid],說明已經找到了目標值,直接返回?mid,也就是目標值在數組中的下標
  5. 未找到目標值:如果?while?循環結束后還沒有找到目標值,說明目標值不在數組中,此時返回 -1 即可

函數的嵌套調用

在編程中,當我們定義了多個函數后,有時會需要在一個函數的執行過程中,調用另一個函數來完成特定任務。這種?在一個函數內部調用另一個函數的方式,就是函數的嵌套調用

代碼演示:

void print()
{printf("hello world\n");
}void three_print()
{for (int i = 0; i < 3; i++){print();}
}int main()
{three_print();return 0;
}

在 three_print 函數中調用了 print 函數,這就是函數的嵌套調用?


函數的鏈式訪問

函數的鏈式訪問是一種編程技巧,它指的是將一個函數的返回值直接作為另一個函數的參數來使用

代碼演示:

printf("%d\n", strlen("abcdef"));

把 strlen 函數的返回值作為 printf 函數的參數,這就是函數的鏈式訪問?

函數的鏈式訪問可以讓代碼更加簡潔和緊湊,避免創建中間變量。不過,在使用鏈式訪問時也要注意代碼的可讀性,如果鏈式訪問的函數過多,可能會讓代碼變得難以理解和調試。所以,在實際編程中要根據具體情況合理使用函數的鏈式訪問?

一段有趣的代碼

代碼演示:

printf("%d", printf("%d", printf("%d", 43)));

問:最后在控制臺上輸出的結果是多少?

需明確?printf?函數的返回值為其輸出的字符個數:

如:printf("%d", 1); 的返回值就是 1,printf("%d", 123); 的返回值就是 3

具體執行過程如下:

  1. 執行最內層?printf("%d", 43),會先在控制臺輸出?43(共 2 個字符),返回值為?2
  2. 中間層?printf("%d", 2)?接收內層返回值,輸出?2(1 個字符),返回值為?1
  3. 最外層?printf("%d", 1)?接收中間層返回值,輸出?1(1 個字符)

綜上,控制臺輸出結果為?4321

代碼驗證:


函數的聲明、調用和定義

函數的定義

int Add(int a, int b)
{return a + b;
}

函數 Add 的功能為計算兩個整數的和,其定義是實現該功能的具體代碼邏輯,即通過設定參數接收兩個整數輸入,在函數體內執行加法運算,并將運算結果作為返回值輸出,從而完成兩個整數相加功能的程序實現

函數調用

int main()
{int a = 0;int b = 0;scanf("%d %d", &a, &b);int sum = Add(a, b);printf("%d\n", sum);return 0;
}

在 main 函數里使用 Add 函數的操作,在編程中被稱作函數調用,此操作可觸發 Add 函數執行其預設功能

函數聲明?

// 函數聲明
int Add(int a, int b);int main()
{int a = 0;int b = 0;scanf("%d %d", &a, &b);// 函數調用int sum = Add(a, b);printf("%d\n", sum);return 0;
}// 函數定義
int Add(int a, int b)
{return a + b;
}

在 C 程序設計中,若自定義函數的定義位于 main 函數之后,則需在 main 函數執行前進行函數聲明

這是由于程序遵循從上至下的執行邏輯,編譯器在處理 main 函數時若未預先知曉自定義函數的存在,會因無法識別函數名稱而報錯

按照模塊化編程規范,函數聲明通常被放置在頭文件(.h)中,用于告知編譯器函數的參數類型和返回值類型;而函數的具體實現(定義)則集中存儲在對應的源文件(.c)中,這種分離式設計有助于代碼的組織、維護及復用,確保程序在編譯階段能夠正確解析函數調用關系


函數遞歸?

什么是遞歸

遞歸是函數直接或間接調用自身的編程方式。需定義基線條件(終止遞歸的條件)和遞歸條件(逐步逼近基線的邏輯),通過重復調用解決可分解為相似子問題的任務

遞歸的核心思維在于:把大事化小

遞歸的兩個必要條件?

  1. 基線條件(終止條件):必須存在至少一個無需遞歸調用的終止條件,用于退出遞歸過程,避免無限循環;
  2. 遞歸條件:函數需通過自身調用逐步分解問題,且每次遞歸調用必須更接近基線條件,確保問題規模遞減直至滿足終止條件

一個簡單的遞歸

int main()
{printf("hello\n");main();return 0;
}

若 main 函數直接調用自身,構成直接遞歸。由于該遞歸未設置基線條件(終止條件),程序會無限次遞歸調用自身,導致調用棧不斷增長

當棧空間被耗盡時,將引發棧溢出錯誤,造成程序異常終止。這一現象體現了遞歸中終止條件的必要性 —— 缺少該條件會破壞遞歸的收斂性,最終導致內存資源耗盡

牛刀小試

要求使用函數遞歸實現:接受一個無符號整型值,按照順序打印他的每一位

例如:

輸入:1234 ;輸入:1 2 3 4?

代碼演示:

void print_every_one(int n)
{if (n > 9){print_every_one(n / 10);}printf("%d ", n % 10);
}

代碼解析:

該函數實現按順序打印無符號整數每一位的功能,核心通過數學運算?%10(取個位)和?/10(去除個位)分解數字,并結合遞歸逐層處理

算法思路:

數字分解原理

  1. 對于任意整數?nn % 10?可獲取其個位數字(如?123 % 10 = 3
  2. n / 10?可去除個位,得到高位數字(如?123 / 10 = 12

通過重復這兩步,可逐位拆解整數的每一位

遞歸過程分析(以?n = 123?為例):

首次調用與遞歸展開

  • 初始調用?print_every_one(123),因?123 > 9,觸發遞歸調用?print_every_one(123 / 10 = 12)
  • 第二次調用?print_every_one(12),因?12 > 9,繼續遞歸調用?print_every_one(12 / 10 = 1)

基線條件觸發(遞歸終止)

  • 第三次調用?print_every_one(1),此時?1 <= 9,不滿足遞歸條件,跳過?if?語句,直接執行?printf("%d ", 1 % 10),輸出?1

逐層返回與后續打印

  • 返回上一層(第二次調用,n = 12),執行?printf("%d ", 12 % 10),輸出?2
  • 再返回初始層(首次調用,n = 123),執行?printf("%d ", 123 % 10),輸出?3

最終輸出結果

控制臺按遞歸返回順序打印?1 2 3,實現從高位到低位的順序輸出

核心邏輯總結:

  • 遞歸特性:通過不斷將問題規模縮小(n / 10),直至滿足基線條件(n <= 9)時終止遞歸,再逐層返回處理當前層的打印邏輯
  • 執行順序:遞歸調用時先處理高位(通過不斷剝離個位),返回時再依次打印低位,利用調用棧的后進先出特性,自然實現從高位到低位的順序輸出

要求寫一個函數:能實現求字符串的長度?

代碼演示:

int my_strlen(const char* s)
{int count = 0;while (*s != '\0'){count++;s++;}return count;
}

代碼解析:

此函數?my_strlen?用于計算字符串的長度。參數?s?是一個指向字符串首字符的指針

在 C 語言里,字符串以?'\0'?作為結束標志。函數利用?while?循環來遍歷字符串,只要當前指針?s?所指向的字符不是?'\0',就表明還有字符需要統計

在循環內部,count?變量用于統計字符串中字符的數量,每統計一個字符,count?的值就加 1。同時,指針?s?通過?s++?操作指向下一個字符,從而實現對字符串的逐字符遍歷

當?s?指向?'\0'?時,意味著已經遍歷完整個字符串,此時循環結束,count?變量中存儲的數值就是字符串中字符的總個數,也就是該字符串的長度,最后將其作為函數的返回值返回

編寫函數,不允許創建臨時變量,求字符串的長度

代碼演示:

int my_strlen(const char* s)
{if (*s == '\0')return 0;return 1 + my_strlen(s+1);
}

代碼解析:

函數參數與返回值

該函數接受一個指向?const char?類型的指針?s?作為參數,const?表明此指針指向的字符串內容不能被修改。函數返回一個?int?類型的值,即字符串的長度

遞歸終止條件

在函數內部,首先會檢查指針?s?所指向的字符是否為?'\0'。在 C 語言中,字符串以?'\0'?作為結束標志。如果當前字符是?'\0',則意味著已經到達字符串的末尾,此時函數將返回 0。這是遞歸的終止條件,它確保了遞歸調用不會無限進行下去,避免出現棧溢出的錯誤

遞歸調用邏輯

若當前字符不是?'\0',說明還未遍歷完整個字符串。函數會將指針?s?向后移動一位(s + 1),使其指向下一個字符,然后再次調用?my_strlen?函數,以計算從下一個字符開始的子字符串的長度。由于當前字符也是字符串的一部分,所以在遞歸調用返回的結果上加 1,表示當前字符的長度。最終將這個累加后的結果作為當前字符串的長度返回

遞歸調用示例

假設傳入的字符串為?"abc",遞歸調用過程如下:

  • 第一次調用?my_strlen("abc"),當前字符為?'a',不是?'\0',則進行遞歸調用?1 + my_strlen("bc")
  • 第二次調用?my_strlen("bc"),當前字符為?'b',不是?'\0',繼續遞歸調用?1 + my_strlen("c")
  • 第三次調用?my_strlen("c"),當前字符為?'c',不是?'\0',再次遞歸調用?1 + my_strlen("")
  • 第四次調用?my_strlen(""),此時當前字符為?'\0',滿足終止條件,返回 0
  • 返回到第三次調用,my_strlen("c")?返回?1 + 0 = 1
  • 返回到第二次調用,my_strlen("bc")?返回?1 + 1 = 2
  • 返回到第一次調用,my_strlen("abc")?返回?1 + 2 = 3

通過這種遞歸的方式,函數逐步縮小問題規模,直到滿足終止條件,最終計算出整個字符串的長度

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

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

相關文章

筆記本電腦升級計劃(2017———2025)

ThinkPad T470 (2017) vs ThinkBook 16 (2025) 完整性能對比報告 一、核心硬件性能對比 1. CPU性能對比&#xff08;i5-7200U vs Ultra9-285H&#xff09; 參數i5-7200U (2017)Ultra9-285H (2025)提升百分比核心架構2核4線程 (Skylake)16核16線程 (6P8E2LPE)700%核心數制程工…

具身系列——PPO算法實現CartPole游戲(強化學習)

完整代碼參考&#xff1a; https://gitee.com/chencib/ailib/blob/master/rl/ppo_cartpole.py 執行結果&#xff1a; 部分訓練得分&#xff1a; (sd) D:\Dev\traditional_nn\feiai\test\rl>python ppo_cartpole_v2_succeed.py Ep: 0 | Reward: 23.0 | Running: 2…

Python項目源碼60:電影院選票系統1.0(tkinter)

1.功能特點&#xff1a;通常選票系統應該允許用戶選擇電影、場次、座位&#xff0c;然后顯示總價和生成票據。好的&#xff0c;我得先規劃一下界面布局。 首先&#xff0c;應該有一個電影選擇的列表&#xff0c;可能用下拉菜單Combobox來實現。然后場次時間&#xff0c;可能用…

【全隊項目】智能學術海報生成系統PosterGenius--圖片布局生成模型LayoutPrompt(2)

&#x1f308; 個人主頁&#xff1a;十二月的貓-CSDN博客 &#x1f525; 系列專欄&#xff1a; &#x1f3c0;大模型實戰訓練營_十二月的貓的博客-CSDN博客 &#x1f4aa;&#x1f3fb; 十二月的寒冬阻擋不了春天的腳步&#xff0c;十二點的黑夜遮蔽不住黎明的曙光 目錄 1. 前…

Linux的時間同步服務器(附加詳細實驗案例)

一、計時方式的發展 1.古代計時方式? 公元前約 2000 年&#xff1a;古埃及人利用光線留下的影子計時&#xff0c;他們修建高聳的大型方尖碑&#xff0c;通過追蹤方尖碑影子的移動判斷時間&#xff0c;這是早期利用自然現象計時的典型方式 。?商朝時期&#xff1a;人們開發并…

【無需docker】mac本地部署dify

環境安裝準備 #安裝 postgresql13 brew install postgresql13 #使用zsh的在全局添加postgresql命令集 echo export PATH"/usr/local/opt/postgresql13/bin:$PATH" >> ~/.zshrc # 使得zsh的配置修改生效 source ~/.zshrc # 啟動postgresql brew services star…

(5)概述 QT 的元對象系統里的類的調用與聯系,及訪問接口

&#xff08;1&#xff09; QT 的元對象系統&#xff0c;這幾個字大家都知道&#xff0c;那么 QT 的元對象系統里都包含哪些內容呢&#xff0c;其訪問接口是如何呢&#xff1f; 從 QObject 類的實現里&#xff0c;從其數據成員里就可以看出來&#xff1a; QT 里父容器可以釋放其…

打包 Python 項目為 Windows 可執行文件:高效部署指南

Hypackpy 是一款由白月黑羽開發的 Python 項目打包工具&#xff0c;它與 PyInstaller 等傳統工具不同&#xff0c;通過直接打包解釋器環境和項目代碼&#xff0c;并允許開發者修改配置文件以排除不需要的內容&#xff0c;從而創建方便用戶一鍵運行的可執行程序。以下是使用 Hyp…

MySQL JOIN詳解:掌握數據關聯的核心技能

一、為什么需要JOIN&#xff1f; 在關系型數據庫中&#xff0c;數據通常被拆分到不同的表中以提高存儲效率。當我們需要從多個表中組合數據時&#xff0c;JOIN操作就成為了最關鍵的技能。通過本文&#xff0c;您將全面掌握MySQL中7種JOIN操作&#xff0c;并學會如何在實際場景中…

Kdump 收集器及使用方式

以下是 Linux 系統中 Kdump 轉儲收集器的詳細說明及其使用方法&#xff0c;涵蓋核心工具、配置方法及實際示例&#xff1a; 一、Kdump 收集器分類及作用 Kdump 的核心功能是通過 捕獲內核 生成內存轉儲文件&#xff08;vmcore&#xff09;&#xff0c;其核心收集器包括&#…

Error: error:0308010C:digital envelope routines::unsupported 高版本node啟動低版本項目運行報錯

我的問題就是高版本node啟動舊版本項目引起的問題&#xff0c;單獨在配置 package.json文件中配置并運行就可以&#xff0c;大概意思就是設置node的openssl "scripts": {"dev": "SET NODE_OPTIONS--openssl-legacy-provider && vue-cli-servi…

松下機器人快速入門指南(2025年更新版)

松下機器人快速入門指南&#xff08;2025年更新版&#xff09; 松下機器人以其高精度、穩定性和易用性在工業自動化領域廣泛應用。本文將從硬件配置、參數設置、手動操作、編程基礎到維護保養&#xff0c;全面講解松下機器人的快速入門方法&#xff0c;幫助新手快速掌握核心操…

【CISCO】Se2/0, Se3/0:串行口(Serial) 這里串口的2/0 和 3/0分別都是什么?

在 Cisco IOS 設備上&#xff0c;接口名稱通常遵循這樣一個格式&#xff1a; <類型><槽號>/<端口號>類型&#xff08;Type&#xff09;&#xff1a;表示接口的物理或邏輯類型&#xff0c;比如 Serial&#xff08;串行&#xff09;、FastEthernet、GigabitEt…

開源無人機地面站QGroundControl安卓界面美化與邏輯優化實戰

QGroundControl作為開源無人機地面站軟件,其安卓客戶端界面美化與邏輯優化是提升用戶體驗的重要工程。 通過Qt框架的界面重構和代碼邏輯優化,可以實現視覺升級與性能提升的雙重目標。本文將系統講解QGC安卓客戶端的二次開發全流程,包括開發環境搭建、界面視覺升級、多分辨率…

基于DDPG的自動駕駛小車繞圈任務

1.任務介紹 任務來源: DQN: Deep Q Learning &#xff5c;自動駕駛入門&#xff08;&#xff1f;&#xff09; &#xff5c;算法與實現 任務原始代碼: self-driving car 在上一篇使用了DQN算法完成自動駕駛小車繞圈任務之后&#xff0c;學習了DDPG算法&#xf…

緩存置換:用c++實現最近最少使用(LRU)算法

在計算機的世界里&#xff0c;緩存就像一個“快速倉庫”&#xff0c;它存儲著我們頻繁訪問的數據&#xff0c;大大提升了數據的讀取速度。但這個 “倉庫” 空間有限&#xff0c;當它被裝滿時&#xff0c;就得決定舍棄一些數據&#xff0c;為新數據騰出位置&#xff0c;這個決策…

【YOLO11改進】改進Conv、頸部網絡STFEN、以及引入PIOU用于小目標檢測!

改進后的整體網絡架構 改進一:RFD模塊(Conv) YOLOv11模型的跨步卷積下采樣雖然快速聚合了局部特征,并且實現了較高的計算效率,但其固有的信息壓縮機制會導致細粒度特征的不可逆丟失。針對特征保留與計算效率的平衡問題,本文采用RFD模塊替換跨步卷積下采樣模塊。RFD模塊通…

設計模式每日硬核訓練 Day 18:備忘錄模式(Memento Pattern)完整講解與實戰應用

&#x1f504; 回顧 Day 17&#xff1a;中介者模式小結 在 Day 17 中&#xff0c;我們學習了中介者模式&#xff08;Mediator Pattern&#xff09;&#xff1a; 用一個中介者集中管理對象之間的通信。降低對象之間的耦合&#xff0c;適用于聊天系統、GUI 控件聯動、塔臺調度等…

java單元測試代碼

import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.*; import java.util.List;public class UserServiceTest {Testpublic void testSearchUserByTags() {// 模擬標簽列表List<String> tagNameList List.of("tag1", "…

前端面經-VUE3篇(一)--vue3基礎知識- 插值表達式、ref、reactive

目錄 一、 插值表達式 1、插值表達式 ({{}}) 的本質與作用&#xff1a; 2、與 Vue 響應式系統關系&#xff1a; 二、指令 1、什么是 Vue 指令&#xff1f; 2、指令的分類 1、內置指令 ① 內容綁定&#xff1a;v-text 和 v-html ② 屬性綁定&#xff1a;v-bind ③ 事件綁定…