# 模組化程式設計

編寫一個規模較大的程式,可以將其依功能劃分為多個獨立的模組。
每個模組由一個函式實現。

好處:

  • 程序開發更容易控制
  • 利於軟體重用
  • 避免重複的程式碼
  • 容易調適及維護

# 主函式 main()

  • C++ 程式僅有一個主函式構成
  • 可以由多個子函式組成
  • 程式的執行順序:總是從 main 函式開始執行,其中可以調用其他的子函式

# 庫函式 (標準函式)

由系統提供,可以直接使用,但需包含相應的頭文件 (Headers)。如:

#include<iostream> // 標準 輸入 / 輸出 函式
#include<cmath> // 數學庫函式
#include<cstring> // 字串處理函式

# 自定義函式

程式的主要邏輯,也就是下半部會介紹到的重要工具!!

# 函式的定義

<函式值型態> <函式名> (<形式參數表>) // 函式頭
{
    <語句序列> // 函數體
}

# 函式值型態

即函式的返回值型態

  • 返回簡單型態,如: intfloatbool
  • 返回結構型態
  • 返回指標型態
  • 返回引用型態

如果沒有任何返回值,返回值型態應標記 voidvoid 型態稱為無型態或空型態。

# 形式參數表

即形參表,函數的參數表用於實現函數間的數據關係。

  • 說明格式: <型態1> <形參1>,<型態2> <形參2>, ... ,<型態n> <形參n>

每個形參必須同時給出形參的型態名稱
如: int max(int a, b) ,做函數首部定義是錯的!!
因為形參 b 缺少了型態說明,即使與 a 型態相同,但作為形參是不可省略的。

  • 定義函式時需考慮設置的形參,形參的個數即型態根據需要設定。
    也可以沒有參數,稱為無參函式。
  • 形參可以接收主調函式傳遞的實參值。
    在函式中對形參進行處理,並將處理結果反回到主調函式。
  • 形參是在函數調用時分配存儲空間,同時接收實參的值。
    當函式執行結束後,系統將自動是放形參分配的存儲空間。
    因此,形參屬於函式的局部變數,只能在該函式中使用。
  • 當形參為引用型態或指標型態時,利用形參不僅可以訪問時參的值,還可以改變實參本身的值。

# 函式體

{ } 刮起來的語句序列構成,是實現函式功能的主體。

  • 函式的編寫過程類似於主函式
  • 在函式中可以調用其他函式
  • 在函式體中,使用 return 返回函式執行的結果。
return <表達式>; // 其中表達式形態需與函式返回值的型態一致
  • 對於無返回的函式,也可以使用 return; 將控制返回主調函式。

在一個函式中允許出現多個 return 語句,但在函式執行期間只能有一個語句起作用。
在函數體的最後一個位置,一個無返回值的 return; 語句可以省略。(有點廢話)

# 函式的宣告

  • 在 C++ 中,程序編譯的單位是源程序文件 (即源文件),一個由多個函式構成的程序可以組織存放在一個或多個源文件中。
  • 在源文件中,函式之間的排列順序沒有固定的要求,但要滿足 先定義後使用 的這個準則。
  • 對於標準庫函式的使用,在程序開頭使用 #include 命令將所需的頭文件包含進來。
  • 對於自訂義的函式,需要在調用之前先定義,不然就是在調用之前做函式宣告
    函式宣告是指在函式被調用前,對函式的型態、名稱以及參數等信息所作說明。
<型態名> <函式名>(<型態1> <形參1>, <型態2> <形參2>,...);
// 或者是
<型態名> <函式名>(<型態1>, <型態2>, ...); // 省略了形參

在形式上就是在函式的首部後加分號 ; 構成。
函式宣告說明了函式所採用的形式,稱為函式原型。

#include <iostream>
#include <cmath>
using namespace std;
int main()
{
	double Area(double a, double b, double c);
	// 或者
	// double Area(double, double, double);
	double a,b,c;
	cout<<"請輸入邊長:"<<endl;
	cin>>a>>b>>c;
	cout<<"面積為:"<<Area(a,b,c)<<endl;
	return 0;
}
double Area(double a, double b, double c)
{
	double p,s;
	
    s=(a+b+c)/2;
	p=sqrt(s*(s-a)*(s-b)*(s-c));
	return p; // 返回函式的值
}

# 函式的調用

函式定義後,並不能自行執行,必須通過函式調用來實現函式的功能。
函式調用,即控制執行某個函式。
C++ 中,主函式可以調用其他子函式,而其他函式之間也可以相互調用。

# 一般格式

<函式名>(<實際參數表>) // 有參調用
// 或
<函式名>() // 無參調用
  • <函式名> 為要使用的函式的名字
  • <實際參數表> 是以逗號分隔的實參數列表,必須方在括號中間。
  • <實參表><形參表> 中的個數、型態需保持一致。
  • 當調用無參函式時,函式名面的括號不可以省

# 實參的幾種形式

形參為簡單型態變數,對應的實參可以是 常數、變數及表達式。
形參為陣列,對應的實參為陣列 (名)。
形參為結構型態,對應的實參為結構型態變數。

調用以之三邊長求三角形面積的函式 Area

double Area(double,double,double); // 變數宣告
cout<<Area(4.0,5.0,6.0)<<endl; // 常數作實參
cout<<Area(a,b,c)<<endl; // 變數作實參
cout<<Area(a+1,b+1,c+2)<<endl; // 表達式作實參

函式調用出現在表達式中 (適於有反為值得函式調用形式)
如:函式 max() 求兩數的最大值。函式的原型為:

float max(float x,float y);

該函式友返回值,調用時應出現在表達式中。

c=max(a,b); // 函式調用出現在賦值運算子的右表達式中
d=max(c,max(a,b));// 函式調用同時出現在實參表達式中
cout<<max(a,b)<<endl;// 輸出一個函式值

# 參數的傳遞

# 值傳遞

調用時,將實參的值傳遞給對應的形參
在傳遞過程中,改變形參的不會改變實參的值。

  • 好處:
    減少函數之間的數據依賴,增強了函式自身的獨立性。
  • 注意:
    函數的形參宣告為簡單型態或結構型態變數,實參與形參將採用值方式傳遞。
void swap(int x, int y)
{
	int tmp;
	tmp = x;
	x = y;
	y = tmp;
}
int main()
{
	int a = 1, b = 2;
	cout << "Before exchange:a= " << a << ",b= " << b << endl;
	// a=1, b=2
	swap(a, b); // 獨立語句調用
	cout << "After exchange:a= " << a << ",b= " << b << endl;
	//a=1, b=2 (沒有交換)
	return 0;
}

調用前實參 a、b 有自己的儲存空間,並有初值。
調用函式時,為形參的 x、y 分配儲存空間,並接收實參的值。
返回到主函式,這時實參 a 和 b 的值沒有改變。
函式中,是對 x、y 值進行交換
執行結束後,x、y 值會自然釋放。

# 引用傳遞

引用是一種特殊的變數,他被認為是一個變數的別名

# 引用的定義

<資料型態> &<引用名> = <目標變數名>;

& 為引用 (變數) 的標誌符號, <引用名> 是一個標識符。
<資料型態><目標變數> 的型態

int a , &b = a;
//a 是一個整數型變數,b 是一個整數型變數 a 的引用
// 即 b 是 a 變數的別名
// 這時,使用 a 與使用 b 是等價的

# 使用說明

  • 定義一個引用,其實是為目標變數起一個別名。
  • 引用並不分配獨立空間出來,他與目標變數共用其內存空間。
  • 定義一個引用 (變數) 時,如果該引用不是用作函式的參數或返回值,則必須提供該引用初值 (即必須提供引用的目標變數名)
  • 使用引用與使用目標變數效果是一樣的。
int main()
{
	int a=2,&b=a;
	cout<<&a<<" "<<&b<<endl;// 輸出變數的地址 // 0x61fe14 0x61fe14 
	cout<<a<<" "<<b<<endl;  // 輸出變數的值  // 2 2
	return 0;
}

# 引用的傳遞

  • 為了要實現引用傳遞,這時函數的形參定義為引用類型變數,而對應的實參應為變數名,該變數將作為飲用的目標變數名。
  • 函式調用時,作為形參的引用變數並不分配新的內存空間,它將作為實參變數的別名與其共用內存。
  • 使用引用參數可以直接操作實參變變數,從而能夠實現通過修改形參的值而達到修改對應實參值的目的。
  • 注意:引用作為函式形參,其引用的目標變數默認為調用該函式時對應的實參變數名,所以,在定義函式時,對於引用類型參數不必提供引用的初值。
//x,y 为引用參數,x 引用 a,y 引用 b
void swap(int &x, int &y)
{
	int tmp;
	tmp = x;
	x = y;
	y = tmp;
	// 交換 x,y 就是交換 a,b
}
int main()
{
	int a = 1, b = 2;
	cout << "Before exchange:a= " << a << ",b= " << b << endl;
	// a=1, b=2
	swap(a, b); // 獨立語句調用
	cout << "After exchange:a= " << a << ",b= " << b << endl;
	// a=2, b=1
	return 0;
}

# 指標傳遞

指標是一個特殊的變數,負責指向值的地址

現在在這裡僅大略寫出其傳遞方式以及比較
後續,會再有一篇專講指標的文章!!敬請期待

# 指標定義

<資料型態> *<指標名> = &<目標變數名>;

* 是指標 (變數) 標識符, <指標名> 是一個標識符。
& 在這裡是位址運算子, <資料型態><目標變數> 的型態

int a , *b = &a;
//a 是一個整數型變數,b 是一個指標其指向 a 所在的位置
// 這時,使用 a 與使用 *b 是等價的

# 使用說明 (簡易版)

指標指向一塊內存,它的內容是所指內存的地址

int main()
{
	int a=2,*b = &a;
	cout<<&a<<" "<<b<<endl;  // 輸出變數的地址 // 0x61fe14 0x61fe14
	cout<<a<<" "<<*b<<endl;  // 輸出變數的值  // 2 2
	return 0;
}

# 指標的傳遞

  • 形參為指向實參地址的指標,當對形參的指向操作時,就相當於對實參本身進行的操作
  • 注意:使用指標傳遞時,傳入的實參必須是其地址,之後再用指標當作形參去做使用
void swap(int *x, int *y)
{
	int tmp;
	tmp = *x;
	*x = *y;
	*y = tmp;
}
int main()
{
	int a = 1, b = 2;
	cout << "Before exchange a= " << a << ",b= " << b << endl;
	swap(&a, &b);
	cout << "After exchange a= " << a << ",b= " << b << endl;
	return 0;
}

# 指標和引用的異同

  • 指標是一個實體,而引用僅是個別名。
  • 引用只能在定義時被初始化一次,之後不可變;指標可變;引用 “從一而終”,指標可以 “見異思遷”。
  • 引用沒有 const,指針有 const,const 的指針不可變。
  • 引用不能為空,必須在定義的時候同時進行初始化。指針可以為空,任何時候初始化都可。
  • 指標和引用的自增 (++) 運算意義不一樣。
  • 引用是類型安全的,而指標不是 (引用比指針多了類型檢查)

# 為形參加入默認值

C++ 語言允許在函數定義時為形參指定默認參數值。
這樣,在函數調用時,如果沒有提供實參,則形參自動使用其默認值。

void f(int x=0,int y=0); // 形参的默認值為 0
f();// 為提供實參,形參 x,y 使用默認值 0
f(2,4);// 形參 x,y 将使用實參的值 2 和 4
f(1);// 形參 x 接收 1,而 y 使用 0

可以從右至左的連續若干個形參設置默認值

void f(int i,int j=2,int k=3);// 正確
void f(int i,int j,int k=3); // 正確
void f(int i=1,int j,int k=3);// 錯誤
void f(int i=1,int j,int k);// 錯誤

# 陣列做為函式參數

# 一維陣列傳遞

<型態> <陣列名>[]
  • 其中, [] 中可以省略陣列的長度值。 (可認為形參陣列與實參陣列長度相同)
  • 對應的實參應為同型態的一維數組名。 (僅用數組名)
  • 為了使函式知道需要處理的陣列元素的個數,通常給函數再傳遞一個表示元素個數的整數形。

# 例子:元素和

一維陣列名作為函數的參數。編寫函數,計算一個整型數組中從第 m 個元素(m 從 0 開始)開始的 n 個元素之和。

  • 函式設計:

    • 函數原型: int fun (int b [],int m,int n);
    • 功能:計算數組 b 中從第 m 個元素開始的 n 個元素之和。
  • 主函數設計:
    定義並初始化一個整型數組 a。

    • 測試 1: fun (a,0,10);// 求從第 0 個元素開始的 10 個元素之和
    • 測試 2: fun (a,3,5); // 求從第 3 個元素開始的 5 個元素之和
int fun(int b[],int m,int n)
{
	int i,s=0;
	for(i=m;i<m+n;i++)
	s=s+b[i];
	return s;
}
int main()
{
	int x,a[]={0,1,2,3,4,5,6,7,8,9};
	x=fun(a,0,10);
	cout<<x<<endl;
	x=fun(a,3,5);
	cout<<x<<endl;
	return 0;
}

# 二維陣列傳遞

<資料型態> <陣列名>[][<列名>]

其中, <列數> 為常數,不能省略行數可缺省
調用時的實參應為同形態的二維陣列名
且用作時參的二維陣列,其列數跟形參中的 <列數> 須一致

# 例子:矩陣轉置

二維陣列名作參數。編寫一個函數,將 N 階方陣轉置(N<10)

  • 函數設計
void transmat(int a[][10],int n);
// 對 a 數組中前 n 行 n 列矩陣元素轉置
  • 主函數設計
    • 定義一個 10 行 10 列的大數組 x,元素類型為整型;
    • 鍵盤輸入一個整數 n (n<10);
    • 鍵盤輸入一個 n×n 的方陣數據,並存放到 x 數組的前 n 行 n 列元素中。
    • 函數調用語句為: transmat (x,n);
    • 按 n 行 n 列輸出轉置矩陣。
void tranmat (int a[][10],int n)
{
	int t;
	for(int i=0;i<n-1;i++) {
		for(int j=i;j<n;j++)
		{
			t=a[i][j];
			a[i][j]=a[j][i];
			a[j][i]=t;
		}
	}
}
int main() {
	int x[10][10],n;
	cout<<"輸入n(n<10):";
	cin>>n;
	cout<<"輸入"<<n<<"行"<<n<<"列元素:"<<endl;
	for(int i=0;i<n;i++) {
		for(int j=0;j<n;j++) {
			cin>>x[i][j];
		}
	}
	tranmat(x,n);
	cout<<"轉置置矩阵结果如下:"<<endl;
	for(int i=0;i<n;i++) {
		for(int j=0;j<n;j++) {
			cout<<x[i][j]<<" ";
		}
		cout<<endl;
	}
}

# 結構變數做函式參數

實參為結構類型變數
行參為同類型的結構變數
傳遞方式為值傳遞

// 定義一個結構型態
struct student
{
	int stno;
	char name[20];
	int age;
};
void print(student s) // 輸出
{
	cout<<s.stno<<endl;
	cout<<s.name<<endl;
	cout<<s.age<<endl;
}
// 主函式
int main()
{
	student stu={1001, "Li" ,19};
	print(stu); // 實參為結構型態
	return 0;
}
更新於 閱讀次數

用實際行動犒賞爆肝的我😀

Zrn Ye LinePay

LinePay