4.1.
Khái niệm hàm
4.1.1.
Khái niệm và phân loại
- Hàm là một là một đơn vị độc lập của chương trình, mỗi hàm có một chức năng xác định, có thể được gọi thực hiện bởi hàm hoặc chương trình khác.
+ Hàm
chuẩn: là các hàm được xây dựng trong C.
+ Hàm tự
định nghĩa: là hàm do người lập trình tự xây dựng.
Ví dụ 4.1: Hàm hàm số lớn giữa 2 số nguyên a, b.
int max(int a, int b)
{
return (a>b) ? a:b;
}
Ví
dụ 4.2: Chương trình nhập vào 2 số nguyên a,b và in ra
màn hình số lớn nhất trong 2 số.
#include <stdio.h>
#include <conio.h>
int max(int a, int b)
{
return (a>b) ? a:b;
}
int main()
{
int a, b;
printf("\n Nhap vao 2
so a, b: ");
scanf("%d%d",&a,&b);
printf("\n So lon la %d",
max(a, b));
getch();
}
4.1.2.
Quy tắc hoạt động của hàm
- Trong những chương trình lớn, có thể có những
đoạn chương trình viết lặp đi lặp lại nhiều lần, để tránh rườm rà và mất thời
gian khi viết chương trình; người ta thường phân chia chương trình thành nhiều
module, mỗi module giải quyết một câu lệnh nào đó. Các module như vậy gọi là
các chương trình con. Trong C, chương trình con được gọi là hàm.
- Hàm trong C có thể trả về kết quả thông qua
tên hàm hay có thể không trả về kết quả.
- Hàm main() là một hàm đặc biệt của ngôn ngữ lập trình C và là hàm đầu tiên được thực hiện trong chương trình. Khi thực hiện, hàm này sẽ gọi các hàm khác để thực hiện các chức năng riêng rẽ.
v
Câu hỏi:
Câu 1. Khái niệm hàm là
gì? Có mấy loại hàm?
Câu 2. Nêu những quy tắc
hoạt động của hàm?
================================
4.2. Xây dựng hàm
4.2.1. Định nghĩa hàm
Định
nghĩa một hàm được hiểu là việc chỉ rõ các lệnh cần phải thực hiện mỗi khi hàm
đó được gọi đến. Như vậy, có thể nói rằng tất cả các hàm được sử dụng trong một
chương trình đều phải có một định nghĩa tương ứng cho nó.
<Tên kiểu kết quả>
<Tên hàm> ([<kiểu t số> <tham số >][…])
{
[<Khai báo biến cục bộ
và các câu lệnh thực hiện hàm>]
[return <Biểu thức>;]
}
-
Tên kiểu kết quả: là kiểu dữ liệu của
kết quả trả về.
-
Tên_hàm: phải đặt hợp lệ và không
trùng với một biến nào hoặc một từ khoá nào của C.
-
Kiểu tham số: là kiểu dữ liệu của
tham số.
-
Tham số: là tham số truyền dữ liệu
vào cho hàm, một hàm có thể có hoặc không có tham số. Tham số này gọi là tham số
hình thức, khi gọi hàm chúng ta phải truyền cho nó các tham số thực tế. Nếu có
nhiều tham số, mỗi tham số phân cách nhau dấu phẩy (,).
-
Bên trong thân hàm giới hạn bởi cặp dấu {}.
-
return: để trả về kết quả thông qua
tên hàm.
4.2.2. Sử dụng hàm
Cú pháp: <Tên hàm>
([Danh sách các tham số])
Một
hàm khi định nghĩa thì chúng vẫn chưa được thực thi trừ khi ta có một lời gọi đến
hàm đó.
Quá
trình diễn ra khi gọi hàm:
-
Nếu hàm có tham số, trước tiên các tham số sẽ được gán giá trị thực tương ứng.
-
Chương trình sẽ thực hiện tiếp các câu lệnh trong thân hàm.
Ví
dụ 4.3: Chương trình tính luỹ thừa một số
#include<stdio.h>
#include<conio.h>
float
luythua(float x, int k)
{
float r =1;
while(k > 0)
{
r = r*x;
k--;
}
return r;
}
//
Hàm chính
void
main()
{
int k;
float n, nk ;
n =
4; k = 5;
nk =
luythua(n, k);
printf(" luy thua %f", nk);
getch();
}
Chú ý: Trong ngôn ngữ lập trình
C có ba loại biến :
-
Biến toàn cục (global): Là biến khai
báo bên ngoài mọi hàm
-
Biến cục bộ (Local): Là biến khai
báo bên trong một hàm. Biến này chỉ tồn tại khi hàm đang được thực thi.
- Biến tĩnh (static): Khai báo biến với chỉ thị static bên trong một hàm. Biến này vẫn tồn tại sau khi hàm thực thi xong.
v
Thực
hành:
Viết code cho Ví dụ 4.3
Câu 1. Trình bày cú pháp của
hàm tự định nghĩa?
Câu 2. Hãy cho biết cách sử
dụng hàm?
=============================
4.3. Các tham số của hàm
4.3.1. Phân biệt các loại tham số
-
Tham số hình thức: là biến được liệt
kê trong danh sách tham số (thường nằm tại phần đầu của định nghĩa hàm).
-
Tham số thực: là giá trị cụ thể khi
truyền vào tham số hình thức.
4.3.2. Cách truyền tham
số
-
Dữ liệu mà hàm sẽ tác động gọi là tham số (parameter) của hàm.
-
Trong C ta dùng kỹ thuật truyền tham số bằng
trị để không thay đổi giá trị và truyền tham số bằng địa chỉ hoặc tham chiếu để
thay đổi giá trị của tham số.
Ví dụ 4.4: Truyền tham số bằng trị
void swap(int x, int y)
{
int temp = x;
x = y;
y = temp;
}
Ta thực hiện hàm main() như sau:
void
main()
{
int a,b;
a = 10; b = 20;
swap(a,b);
}
Giá
trị của a và b sau khi thực hiện hàm main() là :
a
= 10, b = 20
Ví dụ 4.5: Truyền tham số bằng địa chỉ
void swap(int &x,int &y)
{
int temp = x;
x = y;
y = temp;
}
void main()
{
int a,b;
a = 10; b = 20;
swap(a,b);
}
Giá
trị của a và b sau khi thực hiện hàm main() :
a
= 20, b = 10
v Thực hành:
Bài 1. Viết code cho Ví dụ 4.4
Bài 2. Viết code cho Ví dụ 4.5
v
Bài tập:
Viết chương trình cho phép chọn phép toán (+, - , *,
/) để tính kết quả của 2 số thực nhập từ bàn phím.
=====================================
4.4. Hàm đệ quy
Đệ quy là việc định nghĩa nội dung thông qua
chính bản thân của nó nhưng ở mức độ nhỏ hơn.
Ta xét một ví dụ minh họa phương pháp đệ quy qua
một bài toán tính giai thừa. Ta biết rằng n! được định nghĩa như sau:
1!
= 1
n!
= n*(n-1) !
Áp
dụng định nghĩa trên ta có thể tính 5! như sau :
5!
= 5 * 4!
4! = 4 * 3!
3! = 3 * 2!
2! =
2 * 1!
1
Suy
ra 5! = 5*4*3*2*1 = 120
Vì
vậy, tư tưởng giải bài toán bằng đệ quy là đưa bài toán hiện tại về một bài
toán cùng loại, cùng tính chất nhưng ở cấp độ thấp hơn
- Phần cơ sở:
Là
các trường hợp không cần thực hiện lại thuật toán cũng có nghĩa là khi làm đến
đây sẽ không có việc gọi đệ quy nữa mà ở đây chỉ là một câu lệnh đơn giản dùng
để kết thúc phần đệ quy.
Là
phần trong thuật toán có yêu cầu gọi đệ quy, tức là yêu cầu thực hiện lại thuật
toán nhưng với cấp độ dữ liệu thấp hơn. Phần đệ quy này được dựa trên cơ sở
công thức quy nạp của bài toán.
long
giai_thua(int n)
{
if (n==0) return 1;
return n*giai_thua(n -1);
}
v Thực hành:
Viết chương trình tính
giai thừa của sô nguyên n nhập từ bàn phím.
v
Bài tập:
Viết chương trình tính tổng:
S
= 1! + 2! + 3! + …. + n!, trong đó n nhập từ phím.
======================================