摘要:我們在開發(fā)的過程中每個程序員都可能用的到,為了支持可移植性和提高程序的效率,所以語言的基礎(chǔ)庫中提供了一系列類似的庫函數(shù),方便程序員進(jìn)行軟件開發(fā)。形式參數(shù)當(dāng)函數(shù)調(diào)用完成之后就自動銷毀了。因此形式參數(shù)只在函數(shù)中有效。
?寫在前面
- ?博客主頁:kikoking的江湖背景
- ?歡迎關(guān)注?點(diǎn)贊?收藏??留言?
- ?本文由 kikokingzz 原創(chuàng),CSDN首發(fā)!
- ?首發(fā)時間:?2021年11月21日?
- ?最新更新時間:?2021年11月21日?
- ??堅持和努力一定能換來詩與遠(yuǎn)方!
- ?作者水平很有限,如果發(fā)現(xiàn)錯誤,請留言轟炸哦!萬分感謝感謝感謝!
?:本篇內(nèi)容包含了C語言函數(shù)的全方位理解,同時配備了對應(yīng)的例題理解,后續(xù)還會更新專門的習(xí)題,刷題板塊!
L:大仙,終于來到函數(shù)板塊了嘛!
?:yep!小子,這章內(nèi)容很多,仔細(xì)看哦!
目錄
?自學(xué)案例1-strcpy函數(shù)自學(xué)
?1.寫一個函數(shù)可以找出兩個整數(shù)中的最大值
?2.寫一個函數(shù)可以交換兩個整形變量的內(nèi)容
?3.寫一個函數(shù),實現(xiàn)一個整形有序數(shù)組的二分查找。
?4.寫一個函數(shù),每調(diào)用一次這個函數(shù),就會將num的值增加1
?5. 函數(shù)的嵌套調(diào)用和鏈?zhǔn)皆L問
?練習(xí)1.接收一個整型值(無符號),按照順序打印它的每一位
?練習(xí)2.編寫函數(shù)不允許創(chuàng)建臨時變量,求字符串的長度
?練習(xí)4.求第n個斐波那契數(shù)(不考慮溢出)
?1.函數(shù)是什么??
- 在計算機(jī)科學(xué)中,子程序(英語:Subroutine, procedure, function, routine, method, subprogram, callable unit),是一個大型程序中的某部分代碼, 由一個或多個語句塊組成。它負(fù)責(zé)完成某項特定任務(wù),而且相較于其他代碼,具備相對的獨(dú)立性。
- 一般會有輸入?yún)?shù)并有返回值,提供對過程的封裝和細(xì)節(jié)的隱藏。這些代碼通常被集成為軟件庫
???我是分割線???
?2.1?庫函數(shù)
?2.1.1為什么會有庫函數(shù)?
- ?我們知道在我們學(xué)習(xí)C語言編程的時候,總是在一個代碼編寫完成之后迫不及待的想知道結(jié)果,想把這個結(jié)果打印到我們的屏幕上看看。這個時候我們會頻繁的使用一個功能:將信息按照一定的格 式打印到屏幕上(printf)。
- 在編程的過程中我們會頻繁的做一些字符串的拷貝工作(strcpy)。
·像上面我們描述的基礎(chǔ)功能,它們不是業(yè)務(wù)性的代碼。我們在開發(fā)的過程中每個程序員都可能用的到,為了支持可移植性和提高程序的效率,所以C語言的基礎(chǔ)庫中提供了一系列類似的庫函數(shù),方便程序員進(jìn)行軟件開發(fā)。
?2.1.2如何學(xué)會使用庫函數(shù)?
- 需要學(xué)會查詢工具的使用:
- MSDN(Microsoft Developer Network)
- www.cplusplus.com
- http://en.cppreference.com(英文版)
- http://zh.cppreference.com(中文版)
?自學(xué)案例1-strcpy函數(shù)自學(xué)
·在MSDN中搜索strcpy
·了解函數(shù)的定義方法、返回值、參數(shù)等
#include
#include int main(){ //strlen--string length --字符串長度有關(guān)的 //strcpy--string copy--字符串拷貝 char arr1[] = "bit";//原數(shù)據(jù) char arr2[] = "#########";//目的地字符串 // bit/0 打印時/0是結(jié)束標(biāo)志 strcpy(arr2, arr1); printf("%s/n", arr2); return 0;}
?自學(xué)案例2-memset自學(xué)
·在MSDN中搜索memset
·了解函數(shù)的定義方法、返回值、參數(shù)等
#include
int main(){ char arr[]="hello world"; memset(arr,"*",5); //arr-這個數(shù)組空間的地址 //這里放的"*",因為存進(jìn)去的是ASCII值,也是整型值(int型) printf("%s/n",arr);//%s打印字符串 //***** world return 0;}
?自學(xué)案例3-strlen
?·在www.cplusplus.com中搜索memset
·了解函數(shù)的定義方法、返回值、參數(shù)等
#include
#include int main(){ char arr[] = "abc"; size_t len = strlen(arr); printf("%u/n", len); //%d-有符號 //%u-無符號 return 0;}
???我是分割線????
?2.2自定義函數(shù)
L:庫函數(shù)好好用啊,那是不是咱們只要熟練掌握庫函數(shù)就好啦?
?:如果庫函數(shù)能干所有的事情,那還要程序員干什么?所以更加重要的是自定義函數(shù)!
?2.2.1自定義函數(shù)的組成
·自定義函數(shù)和庫函數(shù)一樣,有函數(shù)名,返回值類型和函數(shù)參數(shù)。但是不一樣的是這些都是我們自己來設(shè)計。這給程序員一個很大的發(fā)揮空間。
?·函數(shù)的組成︰
?
?2.2.2典型案例
?1.寫一個函數(shù)可以找出兩個整數(shù)中的最大值
#include
int getmax(int x, int y){ if (x > y) return x; else return y;}int main(){ int a = 10; int b = 20; //函數(shù)的使用 int max = getmax(a, b); int max1 = getmax(100, 300+1); printf("%d/n", max1); return 0;}
?2.寫一個函數(shù)可以交換兩個整形變量的內(nèi)容
?錯誤示范:
#include
void Swag(int x, int y)//void表示沒有返回值{ int z = x; x = y; y = z;}int main(){ int a = 10; int b = 20; int tmp; printf("a=%d b=%d/n", a, b); Swag(a, b); printf("a=%d b=%d/n", a, b); return 0;} L:為什么這里明明Swag函數(shù)里面兩個值交換了,而最后的結(jié)果沒有交換呢?
?:小子,仔細(xì)看上圖案例,Swag函數(shù)中的 形參x,y 的地址與 實參a、b 的地址不同,我們僅僅只是交換了Swag函數(shù)內(nèi)的兩值,對于a,b其實并未改變
?:也就是說:當(dāng)函數(shù)調(diào)用時候,實參傳給形參,形參其實是實參的一份臨時拷貝;所以對形參的修改,不會影響實參
L:那么如何修改呢?
?:我們只要通過指針將實參a、b 地址傳遞給 形參x,y ,再通過解引用操作就可以成功啦
?正解(傳址):
#include
void Swag(int* pa, int* pb)//void表示沒有返回值{ int tmp = 0; tmp = *pa;//用解引用操作 *pa = *pb; *pb = tmp;}int main(){ int a = 10; int b = 20; int tmp; printf("a=%d b=%d/n", a, b); Swag(&a, &b); printf("a=%d b=%d/n", a, b); return 0;}
???我是分割線???
?3. 函數(shù)的參數(shù)
?3.1 實際參數(shù)(實參)
- 真實傳給函數(shù)的參數(shù),叫實參。
- 實參可以是:常量、變量、表達(dá)式、函數(shù)等。
- 無論實參是何種類型的量,在進(jìn)行函數(shù)調(diào)用時,它們都必須有確定的值,以便把這些值傳送給形參。
?3.2 形式參數(shù)(形參)
- 形式參數(shù)是指函數(shù)名后括號中的變量,因為形式參數(shù)只有在函數(shù)被調(diào)用的過程中才實例化(分配內(nèi)存單元),所以叫形式參數(shù)。
- 形式參數(shù)當(dāng)函數(shù)調(diào)用完成之后就自動銷毀了。因此形式參數(shù)只在函數(shù)中有效。
- 當(dāng)實參傳給形參的時候,形參其實是對實參的一份臨時拷貝,對形參的修改是不會改變實參的(例如交換數(shù)字案例中的錯解)
- 上面 Swap1 和 Swap2 函數(shù)中的參數(shù) x、y、px、py 都是形式參數(shù)。
- 在main函數(shù)中傳給 Swap1 的 num1 、num2 和傳給Swap2 函數(shù)的 &num1 、&num2 是實際參數(shù)。
·這里可以看到 Swap1 函數(shù)在調(diào)用的時候, x 、?y 擁有自己的空間(傳值調(diào)用),同時擁有了和實參一模一樣的內(nèi)容。 所以我們可以簡單的認(rèn)為:形參實例化之后其實相當(dāng)于實參的一份臨時拷貝。
???我是分割線???
?4. 函數(shù)的調(diào)用
?4.1 傳值調(diào)用
- 函數(shù)的形參和實參分別占有不同內(nèi)存塊(內(nèi)存地址不同),對形參的修改不會影響實參。
void Swag(int x, int y)//void表示沒有返回值{ int z = x; x = y; y = z;}
?4.2 傳址調(diào)用
- 傳址調(diào)用是把函數(shù)外部創(chuàng)建變量的內(nèi)存地址傳遞給函數(shù)參數(shù)的一種調(diào)用函數(shù)的方式。
- 這種傳參方式可以讓函數(shù)和函數(shù)外邊的變量建立起真正的聯(lián)系,也就是函數(shù)內(nèi)部可以直接操作函數(shù)外部的變量。
void Swag(int* pa, int* pb)//void表示沒有返回值{ int tmp = 0; tmp = *pa;//用解引用操作 *pa = *pb; *pb = tmp;}
?函數(shù)調(diào)用案例
?1.判斷一個函數(shù)是不是素數(shù)
#include
#include int is_prime(int n)//是素數(shù)返回1.不是素數(shù)返回0{ for (int j = 2; j <= sqrt(n); j++)//寫出優(yōu)化的方式sqrt(n) { if (n % j == 0)//被j整除 return 0; } return 1;}int main(){//打印100-200之間的素數(shù) int i = 0; for (i = 100; i <= 200; i++)//產(chǎn)生100-200的數(shù) { //判斷i是否為素數(shù) if (is_prime(i) == 1) printf("%d/n", i); }}
?2.寫一個函數(shù)判斷是不是閏年
#define _CRT_SECURE_NO_WARNINGS 1#include
//是閏年返回1,不是閏年返回0int is_leap_year(int x){ if(((x % 4 == 0) && (x % 100 != 0))||(x % 400 == 0)) return 1; else return 0;}int main(){ int count = 0; int y = 0; for (y = 1000; y <= 2000; y++) { //判斷y是不是閏年 if (is_leap_year(y)) { count++; printf("%d/n", y); } } printf("%d個閏年/n", count); return 0;}
?3.寫一個函數(shù),實現(xiàn)一個整形有序數(shù)組的二分查找。
重點(diǎn):數(shù)組傳遞到形參時,傳遞的是首元素地址
#define _CRT_SECURE_NO_WARNINGS 1#include
int binary_search(int arr[], int k,int num){ //用折半查找 //int num = sizeof(arr) / sizeof(arr[0]); // 指針大小== 4 / 4 =1 int left = 0; int right = num - 1; do { int mid = (left + right) / 2; if (arr[mid] < k) { left = mid + 1; } else if (arr[mid] > k) { right = mid - 1; } else return mid;//找到了 }while(left<=right); return -1;}//如果找到了就返回下標(biāo)//找不到就返回-1int main(){ int arr[] = { 1,2,3,4,5,6,7,8,9,10 }; int k = 7; int num = sizeof(arr) / sizeof(arr[0]); //數(shù)組arr傳給binary_search函數(shù)的時候,其實傳的是arr首元素的地址 int ret =binary_search(arr,k,num); if (-1 == ret) printf("找不到/n"); else printf("找到了,下標(biāo)是%d", ret); return 0;}
?4.寫一個函數(shù),每調(diào)用一次這個函數(shù),就會將num的值增加1
·法1.需要改變實參——傳址
#define _CRT_SECURE_NO_WARNINGS 1#include
void add(int* p){ ++*p;}int main(){ int num = 0; add(&num); printf("%d", num); add(&num); printf("%d", num); add(&num); printf("%d", num); return 0;} ·法2.不使用傳參,采取頻繁賦值
#define _CRT_SECURE_NO_WARNINGS 1#include
int add(int m){ return m + 1;}int main(){ int num = 0; num=add(num);//頻繁賦值 printf("%d", num); num = add(num); printf("%d", num); num = add(num); printf("%d", num); return 0;}
???我是分割線???
?函數(shù)返回類型
- void-無返回(可以使用return;來結(jié)束void函數(shù))
- char int float-返回值為其對應(yīng)類型
#define _CRT_SECURE_NO_WARNINGS 1#include
void test1(){ int n = 5; printf("hehe/n"); if (n == 5) return;//void里用return;來返回 //可以提前使函數(shù)終止 printf("haha/n");}int test2(){ return 1;}int main(){ test1(); return 0;}
???我是分割線????
?5. 函數(shù)的嵌套調(diào)用和鏈?zhǔn)皆L問
?5.1 嵌套調(diào)用
·函數(shù)可以嵌套調(diào)用;不可以嵌套定義//函數(shù)不能嵌套定義void test1(){ void test2() { }}//但是可以嵌套調(diào)用void test1(){ test2();}
?5.2鏈?zhǔn)皆L問
·把一個函數(shù)的返回值作為另外一個函數(shù)的參數(shù)
int main(){ int len = strlen("abc"); printf("%d/n", len); printf("%d/n", strlen("abc")); //把strlen函數(shù)的返回值作為printf函數(shù)的參數(shù) return 0;}
?3.習(xí)題
·考察鏈?zhǔn)皆L問——把一個函數(shù)的返回值作為另外一個函數(shù)的參數(shù)
int main(){ printf("%d", printf("%d", printf("%d", 43))); //結(jié)果是啥? //注:printf函數(shù)的返回值是打印在屏幕上字符的個數(shù) return 0;}
?前情提要:了解printf函數(shù)的返回值
??6. 函數(shù)的聲明和定義
?6.1函數(shù)定義
·函數(shù)的定義是指函數(shù)的具體實現(xiàn),交待函數(shù)的功能實現(xiàn)。·解決辦法:(添加一個函數(shù)聲明)
ADD(int x, int y);//函數(shù)聲明int main(){ int a = 10; int b = 20; int ret = ADD(a, b); printf("%d", ret); return 0;}int ADD(int x, int y){ int z = x + y; return z;}
?6.2函數(shù)聲明
1.告訴編譯器有一個函數(shù)叫什么,參數(shù)是什么,返回類型是什么。但是具體是不是存在,函數(shù)聲明決定不了。
2.函數(shù)的聲明一般出現(xiàn)在函數(shù)的使用之前。要滿足先聲明后使用。
3.函數(shù)的聲明一般要放在頭文件中(.h文件中)的。
·本質(zhì)上的應(yīng)用:剝離出來
//add.h 放函數(shù)聲明#include
int ADD(int x, int y); //add.c 放函數(shù)定義#include"add.h"int ADD(int x, int y){ int z = x + y; return z;}
//test.c 主函數(shù)#include"add.h"int main(){ int a = 10; int b = 20; int ret = ADD(a, b); printf("%d", ret); return 0;}
上述中把 add.c 和 add.h 合在一起合稱加法模塊
?公司寫代碼,會不會把所有代碼都寫在test.c中呢?
1.分函數(shù)模塊來寫!效率大大提高
2.可以使用靜態(tài)庫,出售函數(shù)
#define _CRT_SECURE_NO_WARNINGS 1#include"add.h"#include
#pragma comment(lib,"add.lib")//使用靜態(tài)庫int main(){ int a = 10; int b = 20; printf("%d", ADD(10, 20)); return 0;}
???我是分割線????
?7. 函數(shù)遞歸
?7.1 什么是遞歸?
·程序調(diào)用自身的編程技巧稱為遞歸( recursion)
·函數(shù)遞歸:函數(shù)自己調(diào)用自己
·遞歸做為一種算法在程序設(shè)計語言中廣泛應(yīng)用。 一個過程或函數(shù)在其定義或說明中有直接或間接調(diào)用自身的一種方法,它通常把一個大型復(fù)雜的問題層層轉(zhuǎn)化為一個與原問題相似的規(guī)模較小的問題來求解
·遞歸策略只需少量的程序就可描述出解題過程所需要的多次重復(fù)計算,大大地減少了程序的代碼量。
遞歸的主要思考方式在于:把大事化小
?練習(xí)1.接收一個整型值(無符號),按照順序打印它的每一位
·例如: 輸入:1234? ;輸出 1 2 3 4
#define _CRT_SECURE_NO_WARNINGS 1#include
Print(unsigned int n){ if (n > 9) { Print(n / 10);//Print(123) 1 2 3 } printf("%d/t", n % 10);//}int main(){ unsigned int num = 0; scanf("%d", &num);//順序打印每一位 Print(num);} ?作圖理解:
??7.2 遞歸的兩個必要條件
1.存在限制條件,當(dāng)滿足這個限制條件的時候,遞歸便不再繼續(xù)。
2.每次遞歸調(diào)用之后越來越接近這個限制條件。
?Tip1.每一次函數(shù)調(diào)用都會在內(nèi)存的棧區(qū)申請一塊內(nèi)存空間
·系統(tǒng)分配給程序的棧空間是有限的,但是如果出現(xiàn)了死循環(huán),或者(死遞歸),這樣有可能導(dǎo)致一 直開辟棧空間,最終產(chǎn)生棧空間耗盡的情況,這樣的現(xiàn)象我們稱為棧溢出
??Tip2.stackoverflow-程序員版的知乎
?練習(xí)2.編寫函數(shù)不允許創(chuàng)建臨時變量,求字符串的長度
·解法1.使用臨時變量(不滿足本題要求)
int my_strlen(char* s)//s相當(dāng)于指向字符串中的 a{ int count = 0;//臨時變量 while (*s != "/0") { count++; s++;//char* 的指針是一個字節(jié) //地址序列+1就可以跳到下一個字符 //如果是一個int型的指針 跳到下一個字符要+4 } return count;}int main(){ //求字符串長度 char arr[] = "abc"; int len = my_strlen(arr); //arr里放著 a b c /0 //arr是數(shù)組名 數(shù)組名是數(shù)組首元素的地址 printf("%d", len); return 0;}
·解法2.使用函數(shù)遞歸
思路:my_strelen("abc");1+my_strelen("bc");1+1+my_strelen("c");1+1+1+my_strelen("/0");1+1+1+0=3
int my_strlen(char* s)//s相當(dāng)于指向字符串中的 a{ int count = 0; while (*s != "/0") { count++; s++;//char* 的指針是一個字節(jié) //地址序列加1就可以變到下一個字符 } return count;}int my_strlen(char* s)//s里面放的是a的地址{ if (*s == "/0") return 0; else return 1 + my_strlen(s + 1);//s+1就是b的地址
筆記理解:
?練習(xí)3.?求n的階乘(不考慮溢出)
·解法1.循環(huán)解法
int main(){ int n = 0; int ret = 1; scanf("%d", &n); for (int i = 1; i <= n; ++i) { ret *= i; } printf("%d", ret); return 0;}
·解法2.遞歸法
int fac(int n){ if (n <= 1) return 1; else return n * fac(n - 1);}int main(){ int n = 0; scanf("%d", &n); int ret = fac(n); printf("%d", ret); return 0;}
?練習(xí)4.求第n個斐波那契數(shù)(不考慮溢出)
·解法1.遞歸
int count = 0;int fib(int x){ if (x == 3)//看看計算3這步需要多少次 count++; if (x <= 2) return 1; else return fib(x - 1) + fib(x - 2);}int main(){ int n = 0; scanf("%d", &n); int ret = fib(n); printf("第%d個斐波那契數(shù)是%d/n", n,ret); return 0;}
?·解法2.循環(huán)方法(從前往后)
int fib(int x){ int a = 1; int b = 1; int c = 1; while (x>2) { c = a + b; a = b; b = c; x--; } return c;}int main(){ int n = 0; scanf("%d", &n); int ret = fib(n); printf("第%d個斐波那契數(shù)是%d/n", n,ret); return 0;}
??Tip3.補(bǔ)碼數(shù)的正溢出
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/124092.html
摘要:作為當(dāng)下最熱門的話題,等巨頭都圍繞深度學(xué)習(xí)重點(diǎn)投資了一系列新興項目,他們也一直在支持一些開源深度學(xué)習(xí)框架。八來自一個日本的深度學(xué)習(xí)創(chuàng)業(yè)公司,今年月發(fā)布的一個框架。 深度學(xué)習(xí)(Deep Learning)是機(jī)器學(xué)習(xí)中一種基于對數(shù)據(jù)進(jìn)行表征學(xué)習(xí)的方法,深度學(xué)習(xí)的好處是用 非 監(jiān)督式或半監(jiān)督式 的特征學(xué)習(xí)、分層特征提取高效算法來替代手工獲取特征(feature)。作為當(dāng)下最熱門的話題,Google...
摘要:神經(jīng)網(wǎng)絡(luò)在自然語言處理方面,未來有巨大的應(yīng)用潛力。講座學(xué)者之一與深度學(xué)習(xí)大神蒙特利爾大學(xué)學(xué)者在大會上發(fā)表了論文,進(jìn)一步展現(xiàn)神經(jīng)機(jī)器翻譯的研究結(jié)果。那些指令的語義就是習(xí)得的進(jìn)入嵌入中,來較大化翻譯質(zhì)量,或者模型的對數(shù)似然函數(shù)。 在 8月7日在德國柏林召開的2016 計算語言學(xué)(ACL)大會上,學(xué)者Thang Luong、Kyunghyun Cho 和 Christopher D. Mannin...
摘要:一維卷積常用于序列模型,自然語言處理領(lǐng)域。三維卷積這里采用代數(shù)的方式對三維卷積進(jìn)行介紹,具體思想與一維卷積二維卷積相同。 由于計算機(jī)視覺的大紅大紫,二維卷積的用處范圍最廣。因此本文首先介紹二維卷積,之后再介紹一維卷積與三維卷積的具體流程,并描述其各自的具體應(yīng)用。1、二維卷積?? ? 圖中的輸入的數(shù)據(jù)維度為 14 × 14 ,過濾器大小為 5 × 5,二者做卷積,輸出的數(shù)據(jù)維度為 10 × 1...
閱讀 4369·2021-11-22 09:34
閱讀 2695·2021-11-12 10:36
閱讀 746·2021-08-18 10:23
閱讀 2640·2019-08-30 15:55
閱讀 3119·2019-08-30 15:53
閱讀 2086·2019-08-30 15:44
閱讀 1366·2019-08-29 15:37
閱讀 1411·2019-08-29 13:04