3. Khái niệm hàm
• Trong khi lập trình, ta thấy có những đoạn
mã lặp đi lặp lại nhiều lần để thực hiện
một công việc nào đó. Ta có thể tách đoạn
mã đó thành một module cụ thể. Sau đó
thay cho việc viết lặp đi lặp lại đoạn mã,
ta chỉ cần thực hiện module nhiều lần.
4. Khái niệm hàm
• Ví dụ: Trong một bài toán ta cần phải thực
hiện 10 lần tính n!. Thay cho việc viết 10
lần lặp đi lặp lại các đoạn mã tính n!. Ta
chỉ cần viết một module tính n!, sau đó gọi
module này ra 10 lần. Rõ ràng sau khi
module hóa, chương trình của ta xây
dựng ngắn và đơn giản hơn rất nhiều.
5. Khái niệm hàm
• Hàm chính là các module mang một đoạn
chương trình. Một hàm mà thực hiện một
nhiệm vụ nào đó chỉ cần viết một lần và
sau đó ta có thể sử dụng lại hàm đó nhiều
lần tại bất kỳ nơi nào trong chương trình.
6. Ưu điểm của việc sử dụng hàm
• Các công việc để giải bài toán được phân chia một
cách rõ ràng.
• Chương trình sáng sủa, dễ đọc, dễ sửa lỗi.
• Trừu tượng hoá thủ tục: Khi một hàm được xây
dựng và kiểm tra xong, ta không cần quan tâm đến
nội dung của hàm.
• Hàm giúp che giấu thông tin.
• Hàm có thể được sử dụng lại nhiều lần.
7. Các thư viện hàm trong C++
• Thư viện hàm trong C++ là nơi lưu giữ các
hàm được xây dựng sẵn nhằm mang lại
sự tiện dụng cho người lập trình. Ví dụ:
Khi cần tính cos(x) ta chỉ cần sử dụng
hàm cos trong thư viện math.h mà không
cần quan tâm hàm cos đó được lập trình
như thế nào.
Ví dụ: y = cox(x);
8. Các thư viện hàm trong C++
• Một số thư viện hàm cần quan tâm:
– iostream: Là thư viện hướng đối tượng cung
cấp các chức năng nhập / xuất dữ liệu.
– math: Là thư viện chứa các hàm toán học
– time: Là thư viện chuyên xử lý về thời gian
– stdlib: Thư viện này bao gồm các chức năng
liên quan đến việc cấp phát, giải phóng bộ
nhớ; Chuyển đổi các kiểu dữ liệu; Điều khiển
tiến trình; Sắp xếp và tìm kiếm dữ liệu; Một số
phép tính toán học.
9. Các thư viện hàm trong C++
• Để sử dụng hàm trong một thư viện nào
đó, ta cần phải khai báo thư viện ở phía
trên cùng của chương trình theo cú pháp
sau:
#include <tên thư viện.h>
– Ví dụ: Ta muốn sử dụng hàm tính căn (sqrt),
hàm này nằm ở thư viện math. Vậy ta cần
phai báo thư viện ở đầu chương trình như
sau:
#include <math.h>
10. Cú pháp hàm
• Ngoài việc sử dụng các hàm có sẵn trong các thư viện,
ta có thể tự xây dựng các hàm ở bên trong chương
trình.
• Hàm không có giá trị trả về:
void <tên hàm>(tham số hình thức)
{
Nội dung hàm
}
tham số hình thức: Chứa giá trị đầu vào của hàm. Tham số này
có thể có hoặc không có. Nếu có nhiều hơn một tham số thì các
tham số cách nhau bởi dấu phảy.
11. Cú pháp hàm
– Ví dụ:
• Hàm viết chữ “DAI HOC THANG LONG” lên màn hình
void DHTL()
{
cout << “DAI HOC THANG LONG” << endl;
}
• Hàm viết n chữ số tự nhiên đầu tiên lên màn hình, mỗi số
cách nhau bởi một dấu trống
void vietSo(int n)
{
for (int i = 0; i < n; i++)
cout << i << “ “;
cout << endl;
}
12. Cú pháp hàm
• Hàm có giá trị trả về:
<kiểu giá trị trả về> <tên hàm>(tham số hình thức)
{
Nội dung hàm
return <giá trị trả về>;
}
tham số hình thức: Chứa giá trị đầu vào của hàm. Tham số này có thể có
hoặc không có. Nếu có nhiều hơn một tham số thì các tham số cách
nhau bởi dấu phảy.
giá trị trả về: Là giá trị mà hàm sẽ nhận được sau khi thực hiện xong. Giá
trị trả về có thể là một biến số hoặc hằng số hoặc một giá trị cụ thể. Tuy
nhiên giá trị trả về phải cùng kiểu giá trị với kiểu giá trị trả về.
return: Hàm kết thúc ngay sau câu lệnh return. Các câu lệnh sau lệnh return
không được thực hiện.
13. Cú pháp hàm
– Ví dụ:
• Hàm tính diện tích của hình chữ nhật
int dienTichHCN(int a, int b)
{
int dientich;
dientich = a * b;
return dientich;
}
• Hàm tính diện tích của hình tròn
float dienTichHT(float r)
{
return (float) 3.14 * r * r;
}
14. Thực hiện hàm (gọi hàm)
• Tại một vị trí trong chương trình, khi cần sử dụng một
hàm nào đó, ta cần phải gọi hàm theo cú pháp sau:
– Đối với hàm không có giá trị trả về:
<tên hàm> (các tham số thực);
Các tham số thực: Có thể có hoặc không. Nếu có sẽ chứa dữ liệu
đầu vào của hàm.
Ví dụ:
void main()
{
int x = 12;
DHTL();
vietSo(8);
vietSo(x);
}
15. Thực hiện hàm (gọi hàm)
– Đối với hàm có giá trị trả về: Về cú pháp gọi
hàm cũng giống như hàm không có giá trị trả
về, tuy nhiên hàm có giá trị trả về có thể được
ghép chung vào với các biểu thức hoặc phép
gán, …
• Ví dụ:
– Biểu thức:
• y = a*a + b*b*b + 5
• Ta có thể viết với hàm pow như sau:
y = pow(a, 2) + pow(b, 3) + 5
16. Thực hiện hàm (gọi hàm)
• Ví dụ:
int main()
{
int x = 5, y = 9;
int dtHCN = dienTichHCN(x, y);
cout << “DT Hinh chu nhat la: “ << dtHCN << endl;
float dtHT = dienTichHT(sqrt(pow(x,2) + pow(y,2)));
cout << “DT Hinh tron la: “ << dtHT << endl;
}
17. Nguyên mẫu hàm
• Nguyên mẫu hàm được dùng để khai báo
với trình biên dịch các hàm sẽ được sử
dụng trong chương trình.
• Nguyên mẫu hàm thường được đặt ở đầu
chương trình, phía dưới phần khai báo thư
viện.
18. Nguyên mẫu hàm
• Cú pháp:
<kiểu giá trị trả về> <tên hàm> (các tham số);
Các tham số:
– Số lượng tham số của nguyên mẫu hàm phụ
thuộc vào số lượng tham số hình thức của
hàm.
19. Nguyên mẫu hàm
• Ví dụ:
#include <iostream.h>
int tinhTong(int, int, int); // Nguyên mẫu hàm
void main()
{
cout << tinhTong(3, 5, 8) << endl;
}
int tinhTong(int x, int y, int z)
{
return x + y + z;
}
20. Nguyên mẫu hàm
• Chú ý:
– Trong nguyên mẫu hàm ta có thể lược bớt
phần tên của tham số và chỉ quan tâm đến
phần kiểu dữ liệu của tham số.
– Nếu khai báo hàm nằm phía trên hàm main()
thì ta có thể không cần khai báo Nguyên mẫu
hàm. Nếu khai báo hàm nằm phía dưới hàm
main() thì ta buộc phải sử dụng Nguyên mẫu
hàm
21. Biến toàn cục và biến cục bộ
• Biến toàn cục: Là biến có thể được sử dụng ở bất kỳ nơi nào trong
chương trình. Biến toàn cục được khai báo ở bên ngoài hàm và
thường nằm phía dưới khai báo thư viện.
– Ví dụ:
#include <iostream.h>
int x;
void main()
{
cout << x << endl;
tangX();
cout << x << endl;
}
void tangX()
{
x = x + 1;
}
22. Biến toàn cục và biến cục bộ
• Biến cục bộ được khai báo ở bên trong một khối lệnh và
chỉ có ý nghĩa ở trong khối lệnh đó.
– Ví dụ:
#include <iostream.h>
void main()
{
{
int x = 9;
cout << x << endl;
x = x + 1;
}
cout << x << endl;
}
23. Biến toàn cục và biến cục bộ
• Nếu biến cục bộ được khai báo ở bên trong một hàm thì nó chỉ có ý nghĩa ở
trong hàm đó.
– Ví dụ:
#include <iostream.h>
void main()
{
int x = 25;
cout << x << endl;
tangX();
cout << x << endl;
}
void tangX()
{
int x = 20;
x = x + 1;
cout << “x trong ham tangX: “ << x << endl;
}
24. Tham số của hàm
• Như ta đã biết tham số của hàm sẽ mang
các giá trị đầu vào cho hàm.
• Các tham số của hàm mang ý nghĩa là
biến cục bộ ở trong hàm đó.
• Mỗi khi tham số hình thức đại diện cho
một tham số thực nào đó, thì giá trị của
tham số thực sẽ được truyền vào cho
tham số hình thức để thực hiện làm đầu
vào cho hàm.
25. Tham số của hàm
• Ví dụ:
#include <iostream.h>
void thamso(int x)
{
cout << quot;x tham so truoc = quot; << x << endl;
x = x + 25;
cout << quot;x tham so sau = quot; << x << endl;
}
void main()
{
int x = 10;
cout << x << endl;
thamso(x);
cout << x << endl;
}
26. Hàm gọi hàm
• Ta có thể thực hiện việc gọi hàm từ một
hàm khác.
• Ví dụ:
– Viết hàm tính chuỗi:
S = 12 / 1! + 22 / 2! + 32 / 3! + … + n2 / n!
Hàm tính chuỗi gọi đến 2 hàm tính bình phương và
tính giai thừa.
27. Thiết kế top-down
• Chia bài toán ban đầu thành các bài toán nhỏ hơn
• Xử lý các bài toán nhỏ
• Kết hợp lời giải của các bài toán nhỏ để giải bài
toán lớn
• Lời giải của mỗi bài toán nhỏ có thể được cài đặt
bởi một hàm
28. Case Study: Vẽ hình
1. Phân tích bài toán
– Bạn muốn vẽ hình một em bé như dưới đây
*
* *
* *
/
/
/
--------------
/
/
/
– Input: Không có gì
– Output: Hình em bé
– Nhận xét: Hình em bé có thể được vẽ dựa trên các hình đơn giản như
hình tròn, hai đường giao nhau, đường nằm ngang.
29. Case Study: Vẽ hình
1. Thiết kế thuật toán
1. Vẽ một hình tròn
2. Vẽ một hình tam giác
3. Vẽ hai đường giao nhau
Làm mịn (refine) thuật toán
1. Vẽ một hình tam giác
1. Vẽ hai đường giao nhau
2. Vẽ đường ngang
30. Case Study: Vẽ hình
• Sơ đồ cấu trúc của bài toán
Vẽ hình em bé
Vẽ hình tròn Vẽ hình tam giác Vẽ hai đường giao nhau
Vẽ hai đường giao nhau Vẽ đường ngang
31. Case Study: Vẽ hình
1. Cài đặt
#include <iostream.h>
// Cac nguyen mau ham
void ve_hinh_tron();
void ve_hinh_tam_giac();
void ve_hai_duong_giao();
void ve_duong_ngang();
// Ham chinh
void main()
{
ve_hinh_tron();
ve_hinh_tam_giac();
ve_hai_duong_giao();
}
32. Case Study: Vẽ hình
1. Cài đặt
// Ham ve hinh tron
void ve_hinh_tron()
{
cout<<quot; * quot;<<endl;
cout<<quot; * *quot;<<endl;
cout<<quot; * * quot;<<endl;
}
// Ham ve hinh tam giac
void ve_hinh_tam_giac()
{
ve_hai_duong_giao();
ve_duong_ngang();
}
33. Case Study: Vẽ hình
1. Cài đặt
// Ham ve hai duong giao nhau
void ve_hai_duong_giao()
{
cout<<quot; / quot;<<endl;
cout<<quot; / quot;<<endl;
cout<<quot; / quot;<<endl;
}
// Ham ve duong nam ngang
void ve_duong_ngang()
{
cout<<quot; -------quot;<<endl;
}
34. Case Study: Vẽ hình
1. Kiểm tra chương trình
*
* *
* *
/
/
/
--------------
/
/
/
35. Giải thích
• Nguyên mẫu hàm (prototype)
– <kiểu giá trị trả về> <tên hàm>(<danh sách đối số>)
– Đặt trước hàm main
• Lời gọi hàm
– Các câu lệnh trong hàm được thực thi
– Hàm được gọi trong hàm main hoặc các hàm khác
• Định nghĩa hàm
– Chỉ rõ các câu lệnh trong hàm
– Định nghĩa hàm được đặt sau hàm main
36. Hàm trong chương trình
1. #include <iostream.h>
1. // Các nguyên mẫu hàm đặt ở đây
1. void main()
2. {
3. // Các lời gọi hàm
4. }
1. // Các định nghĩa hàm đặt ở đây
37. Mở rộng bài toán
• Thay đổi hàm vẽ hình tròn
// Ham ve hinh tron
void ve_hinh_tron()
{
const char kitu_dau = ‘@’;
cout<<quot; quot;<<kitu_dau<<endl;
cout<<quot; quot;<<kitu_dau<<quot; “<<kitu_dau<<endl;
cout<<quot; “<<kitu_dau<<“ “<<kitu_dau<<endl;
}
=> kitu_dau là hằng cục bộ của hàm ve_hinh_tron, nó chỉ
được hiểu trong hàm này
38. Hàm không có đối số
• Giới thiệu chương trình
void gioi_thieu()
{
cout<<“Chuong trinh nay duoc viet boi TM17”<<endl;
cout<<“Ban quyen 2004”<<endl;
cout<<“Phien ban 2.3”<<endl;
}
• Hướng dẫn dùng chương trình
void huong_dan()
{
cout<<“Chuong trinh tinh chu vi va dien tich hinh tron”<<endl;
cout<<“Sau loi thong bao, ban hay nhap vao ban kinh hinh tron,”;
cout<<“sau do chuong trinh se in ra ket qua”<<endl;
}
39. Bài tập: Vẽ hình ngôi nhà
1. Phân tích bài toán
– Bạn muốn vẽ hình một ngôi nhà như dưới đây
/
/
/
------------
| |
| |
| |
------------
– Input: Không có gì
– Output: Hình ngôi nhà
– Nhận xét: Hình ngôi nhà có thể được vẽ bởi các đường giao nhau,
đường nằm ngang và các đường song song.
40. Bài tập: Vẽ hình ngôi nhà
1. Thiết kế thuật toán
1. Vẽ hình tam giác
2. Vẽ hai đường song song
3. Vẽ đường ngang
Làm mịn (refine) thuật toán
1. Vẽ hình tam giác
Vẽ hai đường giao nhau
Vẽ đường ngang
41. Bài tập: Vẽ hình ngôi nhà
• Sơ đồ cấu trúc của bài toán
Vẽ hình ngôi nhà
Vẽ hình tam giác Vẽ hai đường song song Vẽ đường ngang
Vẽ hai đường giao nhau Vẽ đường ngang
42. Bài tập: Vẽ hình ngôi nhà
1. Cài đặt
#include <iostream.h>
// Cac nguyen mau ham
void ve_hinh_tam_giac();
void ve_hai_duong_ss();
void ve_hai_duong_giao();
void ve_duong_ngang();
// Ham chinh
void main()
{
ve_hinh_tam_giac();
ve_hai_duong_ss();
ve_duong_ngang();
}
43. Bài tập: Vẽ hình ngôi nhà
1. Cài đặt
// Ham ve hinh tam giac
void ve_hinh_tam_giac()
{
ve_hai_duong_giao();
ve_duong_ngang();
}
// Ham ve hai duong song song
void ve_hai_duong_ss()
{
cout<<quot; | |quot;<<endl;
cout<<quot; | |quot;<<endl;
cout<<quot; | |quot;<<endl;
}
44. Bài tập: Vẽ hình ngôi nhà
1. Cài đặt
// Ham ve hai duong giao nhau
void ve_hai_duong_giao()
{
cout<<quot; / quot;<<endl;
cout<<quot; / quot;<<endl;
cout<<quot; / quot;<<endl;
}
// Ham ve duong nam ngang
void ve_duong_ngang()
{
cout<<quot; -------quot;<<endl;
}
45. Bài tập: Vẽ hình ngôi nhà
1. Kiểm tra chương trình
/
/
/
------------
| |
| |
| |
------------
46. Bài tập về nhà
1. Vẽ hình tàu vũ trụ
/
/
/
------------
| |
| |
| |
------------
| |
| |
| |
------------
| |
| |
| |
------------
/
/
/
2. Viết chữ HELLO bằng các khối kí tự