內容導讀
- 1.函式的自我概述
- 2.函式的分類
- 2.1庫函式
- 2.2自定義函式
- 3.使用函式的優點
- 4.函式的回傳值
- 5.函式的引數
- 6.函式的呼叫與訪問
- 6.1函式的呼叫
- 6.2函式的訪問
- 7.函式的宣告與定義
- 7.1函式宣告與定義重要性
- 7.2簡單函式的應用
- 7.2.1使用函式判斷閏年
- 7.2.2使用函式判斷素數
- 8.函式的遞回應用
- 8.1函式的遞回
- 8.2函式遞回實體(點擊直達)
前面的話
作者水平很有限,如果發現錯誤,一定要及時告知作者哦!感謝感謝!
博主的碼云gitee,平常博主寫的程式代碼都在里面,
1.函式的自我概述
函式(function),是一種子程式,利用函式名稱,可以接識訓傳值,例如:c = max (a,b);
在計算機科學中,子程式(英語:Subroutine, procedure, function, routine, method, subprogram, callable unit),是一個大型程式中的某部份代碼,由一個或多個陳述句塊組成,它負責完成某項特定任務,而且相較于其他代碼,具備相對的獨立性,
一般會有輸入引數并有回傳值,提供對程序的封裝和細節的隱藏,這些代碼通常被集成為軟體庫,
函式在面向程序的語言中已經出現,是結構(Struct)和類(Class)的前身,本身就是對具有相關性陳述句的歸類和對某程序的抽象,
想更深入了解子程式點這里,百度百科會給你答案
函式在C語言中是非常重要的,可以說一個C程式函式是不可缺少的,具體原因如下:
- 一個C程式由一個或多個程式模塊組成,每一個程式模塊作為一個源程式檔案,較大的程式,可分別放在若干個源檔案中,這樣便于分別撰寫和編譯,提高除錯效率,一個源程式檔案可以為多個C程式共用,
- 一個源程式檔案由一個或多個函式以及其他有關內容(如指令、資料宣告與定義等)組成,一個源程式檔案是一個編譯單位,在程式編譯時是以源程式檔案為單位進行編譯的,而不是以函式為單位進行編譯的,
- C程式的執行是從main函式開始的,如果在main函式中呼叫其他函式,在呼叫后流程回傳到main函式,在main函式中結束整個程式的運行,
- 所有函式都是平行的,地位都是平等的(mian函式有一點點例外),即在定義函式時是分別進行的,是互相獨立的,一個函式并不從屬于另一個函式,即函式不能嵌套定義,函式間可以互相呼叫,但不能呼叫main函式,main函式是被作業系統呼叫的,
2.函式的分類
從用戶使用的角度看,函式有兩種,
① 庫函式,它是由系統提供的,用戶不必自己定義,可直接使用它們,應該說明,不同的C語言編譯系統提供的庫函式的數量和功能會有一些不同,當然許多基本的函式是共同的,
② 用戶自己定義的函式,它是用以解決用戶專門需要的函式,
從函式的形式看,函式分兩類,
① 無參函式,在呼叫無參函式時,主調函式不向被呼叫函式傳遞資料,
② 有參函式,主調函式在呼叫被呼叫函式時,通過引數向被呼叫函式傳遞資料,
b
本文將以用戶的角度,將函式分為庫函式和自定義函式,并做進一步的解釋,
2.1庫函式
庫函式(Library function)是將函式封裝入庫,供用戶使用的一種方式,方法是把一些常用到的函式編完放到一個檔案里,供不同的人進行呼叫,呼叫的時候把它所在的檔案名用#include<>加到里面就可以了,
常見的幾類別庫函式:
(1)I/O 函式,即輸入輸出函式,包括各種控制臺I/O、緩沖型檔案I/O和UNIX式非緩沖型檔案I/O操作,
需要的包含檔案:stdio.h
例如: getchar,putchar,printf,scanf,fopen,fclose,fgetc,fgets,fprintf,fsacnf,fputc,fputs,fseek,fread,fwrite等,
(2)字串、記憶體和字符函式,包括對字串進行各種操作和對字符進行操作的函式,
需要的包含檔案:string.h、mem.h、ctype.h或string.h
例如:用于檢查字符的函式:isalnum,isalpha,isdigit,islower,isspace等,用于字串操作函式:strcat,strchr,strcmp,strcpy,strlen,strstr等,
(3)數學函式,包括各種常用的三角函式、雙曲線函式、指數和對數函式等,
需要的包含檔案:math.h
例如:sin,cos,exp(e的x次方),log,sqrt(開平方),pow(x的y次方)等,
(4)時間、日期和與系統有關的函式,對時間、日期的操作和設定計算機系統狀態等,
需要的包含檔案:time.h
例如:time回傳系統的時間;asctime回傳以字串形式表示的日期和時間,
(5)動態存盤分配,包括"申請分配"和"釋放"記憶體空間的函式,
需要的包含檔案:alloc.h或stdlib.h
例如:calloc,free,malloc,realloc等,
(6)目錄管理,包括磁盤目錄建立、查詢、改變等操作的函式,
(7)程序控制,包括最基本的程序控制函式,
(8)字符螢屏和圖形功能,包括各種繪制點、線、圓、方和填色等的函式,
(9)其它函式,
(摘自百度百科)
C語言庫函式有許多的基礎功能,如輸出printf,輸入scanf,計算次方pow等,像上面我們描述的基礎功能,它們不是業務性的代碼,我們在開發的程序中每個程式員都可能用的到,為了支持可移植性和提高程式的效率,所以C語言的基礎庫中提供了一系列類似的庫函式,方便程式員進行軟體開發,
那如何了解和學習庫函式呢?
可以訪問c語言的官網,查找相關庫函式的資料,閱讀函式的回傳型別,傳參形式,以及函式的功能,
博主推薦一個網站,這個網站上有各種庫函式的介紹:C Library

2.2自定義函式
如果庫函式所有的功能都能實作,那這個世界上可能不會有程式員的存在,所謂自定義函式,就是通過自己撰寫實作相關功能的函式,自定義函式和庫函式一樣,有函式名,回傳值型別和函式引數,
函式定義形式:
型別名 函式名(形式引數)
{
函式體
}
比如,寫一個函式求兩個整數的最大值,
int my_max(int a, int b)
{
if (a > b)
return a;
else
return b;
}
3.使用函式的優點
- 使用函式可使程式清晰、精煉、簡單、靈活,能夠實作“封裝”,
- 函式就是功能,每一個函式用來實作一個特定的功能,函式名應反映其代表的功能,
- 在設計較大程式時,往往把它分為若干個程式模塊,每一個模塊包括一個或多個函式,每個函式實作一個特定的功能,
- 一個C程式可由一個主函式和若干個其他函式構成,由主函式呼叫其他函式,其他函式也可以互相呼叫,
4.函式的回傳值
通常,希望通過函式呼叫使主調函式能得到一個確定的值,這就是函式值(函式的回傳值),
函式的回傳值是通過函式中的return陳述句獲得的,一個函式中可以有一個以上的return陳述句,執行到哪一個return陳述句,哪一個return陳述句就起作用,有回傳值的函式至多只會執行一次return陳述句,return后面的值可以是一個運算式,
函式值的型別,函式值的型別在定義函式時指定,
在定義函式時指定的函式型別一般應該和return陳述句中的運算式型別一致,
如果函式值的型別和return陳述句中運算式的值不一致,則以函式型別為準,對數值型資料,可以自動進行型別轉換,即函式型別決定回傳值的型別,
對于不帶回值的函式,應當用定義函式為“void型別”(或稱“空型別”),這樣,系統就保證不使函式帶回任何值,即禁止在呼叫函式中使用被呼叫函式的回傳值,此時在函式體中也沒有return陳述句,
int max (float x,float y) //函式值為整型
char letter (char c1,char c2) //函式值為字符型
double min (int x,int y) //函式值為雙精度型
5.函式的引數
函式的引數包括形式引數和實際引數,
在呼叫有參函式時,主調函式和被呼叫函式之間有資料傳遞關系,
在定義函式時函式名后面括號中的變數名稱為“形式引數”(簡稱“形參”)或“虛擬引數”,
在主調函式中呼叫一個函式時,函式名后面括號中的引數稱為“實際引數”(簡稱“實參”), 實際引數可以是常量、變數或運算式,但要求它們有確定的值,
實參與形參的型別應相同或賦值兼容,賦值兼容是指實參與形參型別不同時能按不同型別數值的賦值規則進行轉換,
例如,上面所舉例的,使用函式求兩個整數的最大值,
#include <stdio.h>
int my_max(int a, int b)
{
return a > b ? a : b;
}
int main()
{
int m = 0;
int n = 0;
int c = 0;
printf("請輸入兩個整數:"); //提示輸入資料
scanf("%d%d",&m,&n); //輸入兩個整數
c = my_max(m, n); //呼叫my_max函式,有兩個實參,大數賦給變數c
printf("max is %d\n",c); //輸出大數c
return 0;
}

定義函式,名為my_max,函式型別為int,指定兩個形參a和b,形參的型別為int,
主函式中包含了一個函式呼叫my_max(m,n),my_max后面括號內的m和n是實參,m和n是在main函式中定義的變數,a和b是函式my_max的形式引數,
注意:形式引數與實際引數使用的并不是一塊空間,
簡單說,形參實體化之后其實相當于實參的一份臨時拷貝,
6.函式的呼叫與訪問
- 函式呼叫陳述句
把函式呼叫單獨作為一個陳述句,如printf_star();
這時不要求函式帶回值,只要求函式完成一定的操作, - 函式運算式
函式呼叫出現在另一個運算式中,如c=max(a,b);
這時要求函式帶回一個確定的值以參加運算式的運算, - 函式引數
函式呼叫作為另一個函式呼叫時的實參,如m=max(a,max(b,c));,又如:printf (″%d″, max (a,b));
6.1函式的呼叫
函式呼叫有傳值呼叫和傳址呼叫,其中傳值呼叫中函式的形參和實參分別占有不同記憶體塊,對形參的修改不會影響實參的改變,而傳址呼叫可以讓函式和函式外邊的變數建立起真正的聯系,也就是函式內部可以直接操作函式外部的變數,
函式在呼叫程序中的注意事項:
(1) 在定義函式中指定的形參,在未出現函式呼叫時,它們并不占記憶體中的存盤單元,在發生函式呼叫時,函式的形參才被臨時分配記憶體單元,
(2) 將實參的值傳遞給對應形參,
(3) 在執行函式期間,由于形參已經有值,就可以利用形參進行有關的運算,
(4) 通過return陳述句將函式值帶回到主調函式,應當注意回傳值的型別與函式型別一致,如果函式不需要回傳值,則不需要return陳述句,這時函式的型別應定義為void型別,
(5) 呼叫結束,形參單元被釋放,注意: 實參單元仍保留并維持原值,沒有改變,如果在執行一個被呼叫函式時,形參的值發生改變,不會改變主調函式的實參的值,因為實參與形參是兩個不同的存盤單元,
6.2函式的訪問
函式的訪問可以通過嵌套呼叫訪問函式也可以通過鏈式訪問,
嵌套呼叫簡單說就是在一個函式內部使用另一個函式,而鏈式訪問就是把一個函式的回傳值作為另外一個函式的引數,
#include <stdio.h>
void new_line()
{
printf("hehe\n");
}
void three_line()
{
int i = 0;
for(i=0; i<3; i++)
{
new_line();//嵌套訪問
}
}
int main()
{
three_line();
return 0;
}
#include <stdio.h>
int main()
{
printf("%d", printf("%d", printf("%d", 43)));//鏈式訪問
//注:printf函式的回傳值是列印在螢屏上字符的個數
//4321
return 0;
}
函式可以嵌套呼叫,但不能嵌套定義,
7.函式的宣告與定義
7.1函式宣告與定義重要性
//函式宣告
型別名 函式名(形式引數);
//函式定義
型別名 函式名(形式引數)
{
函式體
}
如果想在一個函式中呼叫另一個函式(即被呼叫函式),具體要符合以下幾個條件:
(1) 被呼叫的函式必須是已經定義的函式(是庫函式或用戶自己定義的函式),
//函式定義
int my_max(int a, int b)
{
return a > b ? a : b;
}
(2) 如果使用庫函式,應該在本程式開頭用#include指令將呼叫有關庫函式時所需用到的資訊“包含”到本程式中來,
//如使用printf和scanf函式需包括<stdio.h>頭檔案
#include <stdio.h>
(3) 如果使用用戶自己定義的函式,使用該函式前可以作宣告也可以不做宣告,但是使用的函式必須被定義,宣告的作用是把函式名、函式引數的個數和引數型別等資訊通知編譯系統,以便在遇到函式呼叫時,編譯系統能正確識別函式并檢查呼叫是否合法,如果函式定義在主調函式之后,必須在主調函式之前添加宣告,
#include <stdio.h>
int my_max(int a, int b);//函式宣告
int main()
{
int m = 0;
int n = 0;
int c = 0;
printf("請輸入兩個整數:"); //提示輸入資料
scanf("%d%d",&m,&n); //輸入兩個整數
c = my_max(m, n); //呼叫my_max函式,有兩個實參,大數賦給變數c
printf("max is %d\n",c); //輸出大數c
return 0;
}
int my_max(int a, int b)//函式定義
{
return a > b ? a : b;
}
(4)函式的宣告一般要放在頭檔案中,
一句話總結,呼叫函式時應做到先宣告,再使用,所以說函式宣告定義是使用函式的前提條件,
7.2簡單函式的應用
7.2.1使用函式判斷閏年
要求:判斷某年到某年間閏年有哪些,
比如,2000年到2100年有哪些年是閏年,
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
//判斷是否是閏年條件:
//1.能被4整除但不能被100整除,
//2.能被100整除且能被400整除,
int is_leap_year(int year)//函式定義
{
if ((year % 4 == 0) && (year % 100 != 0) || (year % 400 == 0))
{
return 1;
}
else
{
return 0;
}
}
int main()
{
int y = 0;
int start = 0;
int end = 0;
scanf("%d%d",&start,&end);//輸入 2000 2100
for (y = start; y <= end; y++)
{
//判斷y是否為閏年
//函式
//是閏年,回傳1
//不是閏年,回傳0
if (is_leap_year(y))//函式呼叫
{
printf("%d ", y);
}
}
return 0;
}

7.2.2使用函式判斷素數
要求:判斷一個區間的素數有哪些,
判斷是否是素數條件:
1.如果一個數除以2到這個數開平方整數部分,這個數就是一個素數,
2.如果一個數為偶數,這個數不可能是素數,
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <math.h>
//使用函式判斷素數
int is_prime(int x)
{
int i = 0;
for (i = 2; i <= sqrt(x); i++)
{
if (x % i == 0)
{
return 0;
}
}
return 1;
}
int main()
{
int a = 0;
int b = 0;
int cnt = 0;//一段區間內素數個數
int i = 0;
scanf("%d %d", &a, &b);//輸入區間a到b
int c = a;
if (a % 2 == 0)//排除偶數,因為偶數不可能是素數
a += 1;
for (i = a; i < b; i += 2)
{
if (is_prime(i))
{
printf("%d ", i);
cnt++;
}
}
printf("\n在%d-%d的素數有%d個,\n",c,b,cnt);
return 0;
}
8.函式的遞回應用
8.1函式的遞回
在呼叫一個函式的程序中又出現直接或間接地呼叫該函式本身,稱為函式的遞回呼叫,

它通常把一個大型復雜的問題層層轉化為一個與原問題相似的規模較小的問題來求解,遞回策略只需少量的程式就可描述出解題程序所需要的多次重復計算,大大地減少了程式的代碼量,
遞回的主要思考方式在于:把大事化小,
遞回有優點也有缺點,優點是遞回為某些編程問題提供了簡單的解決方案,缺點是一些遞回演算法會快速消耗計算機記憶體資源,如果遞回次數過多或者進入了死遞回,程式將會崩潰,因為遞回次數太多占用了大量的記憶體,會使它所在的堆疊空間記憶體不足,導致堆疊溢位,此外,遞回不方便閱讀和維護,
程式中不應出現無終止的遞回呼叫,而只應出現有限次數的、有終止的遞回呼叫,這可以用if陳述句來控制,只有在某一條件成立時才繼續執行遞回呼叫;否則就不再繼續,
舉一個簡單的例子:斐波拉契數列
f(1)=f(2)=1
f(n)=f(n-1)+f(n-2)
如果n稍微大一點,運行程式就會發現遞回方式實作斐波拉契數列,會比迭代方式實作斐波拉契數列慢很多,
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
//斐波拉契數列
//1.fib_1()遞回
//2.fib_2()非遞回
int fib_1(int n);
int fib_2(int n);
int main()
{
int n = 0;
scanf("%d", &n);
int a = fib_1(n);
int b = fib_2(n);
printf("%d %d\n", a, b);
return 0;
}
int fib_1(int n)
{
if (n > 2)
{
return fib_1(n - 1) + fib_1(n - 2);
}
else
{
return 1;
}
}
int fib_2(int n)
{
int a1 = 1;
int a2 = 1;
int m = 1;
while (n > 2)
{
m = a1 + a2;
a1 = a2;
a2 = m;
n--;
}
return m;
}
8.2函式遞回實體(點擊直達)
1.漢諾塔問題
2.青蛙跳臺階問題
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/291235.html
標籤:其他
上一篇:??「 選擇排序 」??
下一篇:剖析整型在記憶體中的存盤
