CHƯƠNG 6: HÀM FUNCTION Mục tiêu Giới thiệu các kiến thức về hàm: khái niệm, cách khai báo và định nghĩa hàm, cách truyền tham số; hàm đệ quy, ..... -Khái niệm -Khai báo và định nghĩa
Trang 1CHƯƠNG 6: HÀM (FUNCTION)
Mục tiêu
Giới thiệu các kiến thức về hàm: khái niệm, cách khai báo và định nghĩa hàm, cách truyền tham số; hàm đệ quy,
Trang 2-Khái niệm -Khai báo và định nghĩa -Lời gọi và sử dụng hàm -Biến và truyền tham số -Khai báo hàm trùng tên
6.1 Hàm
Trang 3- Hàm là một chương trình con, hàm có thể trả về hay không trả về giá trị; truyền hay không truyền các tham số.
- Một chương trình trong C++ có thể gồm nhiều hàm
Nhưng có một hàm chính với tên gọi là hàm main()
- Khi thực thi chương trình, nó luôn bắt đầu từ hàm main()
- Hàm giúp cho việc phân đoạn chương trình một cách riêng rẽ Hàm có thể được sử dụng nhiều lần trong một chương trình hoặc sử dụng ở nhiều chương trình khác nhau
Khái niệm
Trang 4- Nằm trong hoặc ngoài chương trình có lời gọi đến hàm Trong một chương trình có thể chứa nhiều hàm.
- Một hàm có thể được gọi từ hàm main(), từ một hàm khác hay được gọi bởi chính nó (trường hợp đệ quy)
- Không có hàm lồng nhau
- Có 3 cách truyền tham số cho hàm:
• Truyền theo tham biến
Khái niệm
Trang 5Hàm được chia làm 2 loại:
+ Hàm định nghĩa sẵn+ Hàm do người lập trình tự định nghĩa
Khai báo và định nghĩa hàm
Trang 6Khai báo hàm:
Hàm định nghĩa sẵn: có trong tệp thư viện *.h Để sử dụng được các hàm này ta cần phải khai báo tệp tiêu đề theo cú pháp #include<Tentaptinthuvien>
Ví dụ: #include<iostream>
#include<cmath>
Khai báo và định nghĩa hàm
Trang 7Hàm do người lập trình tự định nghĩa: có thể được khai báo ở đầu chương trình theo cú pháp:
Kieu_du_lieu Ten_ham(Danh_sach_kieu_doi_so);
Trong đó:
Kieu_du_lieu: là kiểu trả về của hàm int, float, char, Trường hợp hàm không trả về giá trị thì khai báo kiểu void Trường hợp
không chỉ rõ kieu_tra_ve thì ngầm định là kiểu int.
Ten_ham: được đặt theo quy tắc đặt tên.
Danh_sach_kieu_doi_so: có thể có hoặc không Trường hợp
Khai báo và định nghĩa hàm
Trang 8Khai báo các biến cục bộ;
Khai báo và định nghĩa hàm
Trang 9double kq = 1 ; // kq để lưu kết quả
for (i=1; i<=n; i++)
return kq;
Khai báo và định nghĩa hàm
Trang 10* Hàm không trả về giá trị:
Nếu hàm không trả về giá trị (còn gọi là hàm kiểu void):
- kieudulieu : Sử dụng từ khóa void
- Trong thân hàm có thể có khoặc không câu lệnh return
Nhưng nếu có thì sau return không có biểu thức.
Ví dụ: Viết hàm xóa màn hình 100 lần
void ClearSrceen()
{
int i;
for (i=1; i<=100; i++)
Khai báo và định nghĩa hàm
Trang 11- Khái niệm:
Gọi hàm là việc chuyển quyền điều khiển từ hàm đang gọi đến hàm được gọi.
Hàm có thể được gọi từ hàm khác hoặc từ chính bản thân nó.
- Gọi hàm: Để thực hiện việc gọi hàm, sử dụng tên của hàm được
gọi và theo sau là các tham số thực tế được đặt trong cặp dấu ngoặc đơn ( ).
Cú pháp: Ten_ham(Ds_tham_so_thuc_te);
Trong đó: Ds_tham_so_thuc_te phân tách nhau bởi dấu phẩy (,)
Lời gọi và sử dụng hàm
Trang 13- Phân loại biến:
+ Biến thường+ Biến con trỏ (với dấu * trước tên biến)
+ Biến tham chiếu: Thực chất là một bí danh được gán cho một biến nào đó Lúc này, chỗ nào xuất hiện biến thì cũng tương đương dùng bí danh và ngược lại
- Cú pháp khai báo biến tham chiếu:
Kieudulieu &ten_bien_tham_chieu=ten_bien_duoc_tham_chieu;
Biến và truyền tham số
Trang 14Ví dụ:
int a, b;
int &a1=a, &b1=b;
a=2; b=3;
cout<<"a= "<<a<<" b= "<<b<<endl;
cout<<"a1= "<<a1<<" b1= "<<b1<<endl;
Trang 15Lưu ý:
- Biến tham chiếu phải được khởi tạo khi khai báo
- Mặc dù giống con trỏ nhưng không dùng được các phép toán trên con trỏ cho biến tham chiếu Nói chung, chỉ nên dùng trong truyền tham số cho hàm
Biến và truyền tham số
Trang 16- Truyền tham số: Có 3 cách truyền
+ Truyền theo tham trị
+ Truyền theo tham biến
+ Truyền theo tham trỏ
Biến và truyền tham số
Trang 17+ Truyền theo tham trị:
- Trong phương pháp này:
+ Các TSHT (đối số) chỉ nhận giá trị vào cho chương trình con từ TSTT mà không trả kết quả về cho TSTT
+ TSHT được xem như là một biến cục bộ của chương trình con và được cấp phát ô nhớ riêng
+ Các TSTT là một biểu thức (một biến, một hằng, một hàm, một biểu thức thực sự)
Biến và truyền tham số
Trang 18- Các bước thực hiện:
+ Tại thời điểm gọi: Giá trị của TSTT được sao chép vào trong ô nhớ của TSHT
+ Trong quá trình thực hiện: Mọi thao tác trên TSHT là
sự thao tác trên ô nhớ riêng của nó
+ Khi kết thúc: Sự thay đổi giá trị của TSHT không làm ảnh hưởng đến giá trị của TSTT
Biến và truyền tham số
Trang 19Ví dụ: Cho hàm: luythua(float x, int n) tính x n Giả sử trong chương trình chính ta có các biến a, b có giá trị a=2, b=3 và
biến f chưa có giá trị Để tính a b và gán giá trị tính được cho f,
ta có thể gọi f = luythua(a,b) Khi gặp lời gọi này, chương trình
- Tiến hành tính toán (gán lại kết quả cho kq)
- Cuối cùng lấy kết quả trong kq gán cho ô nhớ f
- Kết thúc hàm quay về chương trình gọi
Biến và truyền tham số
Trang 21+ Truyền theo tham biến:
- Trong phương pháp này:
+ TSHT là tham số vào ra, do đó nó sẽ nhận giá trị vào từ TSTT và trả về kết quả lại cho TSTT
+ TSHT là một biến tham chiếu và TSTT phải là một biến
+ Khi kết thúc: Mọi thay đổi giá trị của TSHT đều làm giá trị của TSTT thay đổi theo
Biến và truyền tham số
Trang 22+ Truyền theo tham biến:
Ví dụ: Đổi giá trị 2 biến
void Hoanvi( int &x, int &y)
Trang 23+ Truyền theo tham trỏ:
Trong phương pháp này:
- TSHT là tham số vào ra, do đó nó sẽ nhận giá trị vào từ TSTT
và trả kết quả lại cho TSTT.
- TSHT là một con trỏ và TSTT phải là một biến.
Trang 24+ Truyền theo tham trỏ:
Ví dụ: Viết hàm đổi giá trị 2 biến
void Hoanvi( int *p, int *q)
{
int t; // khai báo biến tạm t
t = *p ; // đặt giá trị của t bằng nội dung nơi p trỏ tới
*p = *q ; // thay nội dung nơi p trỏ bằng nội dung nơi q trỏ
*q = t ; // thay nội dung nơi q trỏ tới bằng nội dung của t
}
- Như vậy, nếu ta cho p trỏ tới biến x và q trỏ tới biến y thì hàm
Biến và truyền tham số
Trang 25- Hàm trùng tên hay còn gọi là hàm chồng (overload) Đây là một kỹ thuật cho phép sử dụng cùng tên gọi cho các hàm “giống nhau” nhưng xử lý trên các kiểu dữ liệu khác nhau hoặc trên số lượng dữ liệu khác nhau.
Ví dụ: để tìm max 2 số ta có các hàm:
int max( int a, int b) { return (a > b) ? a: b ; }
float max( float a, float b) { return (a > b) ? a: b ; } char
max( char a, char b) { return (a > b) ? a: b ; }
Khi đó, tùy thuộc vào giá trị của đối số trong lời gọi hàm để chạy hàm thích hợp Chẳng hạn, max(3, 5), max(3.0, 5.0),
Khai báo hàm trùng tên
Trang 26- Như vậy, đặc điểm của các hàm trùng tên là trong danh sách đối của chúng phải có ít nhất một cặp đối khác kiểu nhau, hoặc
số lượng các đối khác nhau.
- Tóm lại, điều kiện để các hàm có thể định nghĩa chồng là:
+ Số lượng các đối trong hàm là khác nhau + Hoặc có ít nhất 1 đối có kiểu khác nhau giữa các hàm
Kỹ thuật chồng tên còn có thể áp dụng cả cho các toán tử: +, -,
Khai báo hàm trùng tên
Trang 27- Hàm làm việc với mảng cần có 2 thông tin
+ Điạ chỉ bắt đầu của mảng (địa chỉ cơ sở) + Số phần tử xử lý trong mảng
- Truyền mảng một chiều cho hàm
- Truyền mảng hai chiều cho hàm
6.2 Hàm và mảng dữ liệu
Trang 28- Khi đó, TSHT của hàm sẽ là các mảng dữ liệu và số phần
tử của mảng
- Ta có 2 cách khai báo TSHT
Cách 1: Đối số được khai báo bình thường như khai báo biến mảng nhưng không chỉ ra số phần tử Chẳng hạn, int x[]; float A[];
Cách 2: Đối số được khai báo như con trỏ kiểu mảng,
Hàm và mảng một chiều
Trang 29Ví dụ 1: Hàm nhập và hiển thị ra màn hình giá trị mảng một chiều
void nhap( int x[], int n) // n: số phần tử
{ int a[100] ; // mảng a chứa tối đa 100 phần tử
nhap(a,7); // vào 7 phần tử đầu tiên cho a in(a,3); // ra 3 phần tử đầu tiên của a
Hàm và mảng một chiều
Trang 30- Đối với mảng 2 chiều, việc khai báo cũng như lời gọi phức tạp hơn so với mảng một chiều.
Trang 31Ví dụ: hàm tính tổng các số hạng trong ma trận
float tong( float x[][100], int m, int n) // hoặc float
tong( float (*x)[100], int m, int n)
Trang 32Đối số của hàm là cấu trúc:
Một cấu trúc có thể được sử dụng để làm đối số của hàm dưới các dạng sau đây:
- Là một biến cấu trúc, khi đó đối số là một cấu trúc
- Là một con trỏ cấu trúc, đối số là địa chỉ của một cấu trúc
- Là một tham chiếu cấu trúc, đối số là một cấu trúc
- Là một mảng cấu trúc hoặc con trỏ mảng, đối số là tên mảng cấu trúc
6.3 Hàm và cấu trúc
Trang 33- Giá trị của hàm là cấu trúc:
Cũng tương tự như các kiểu dữ liệu cơ bản, giá trị trả lại của một hàm cũng có thể là các cấu trúc dưới các dạng sau:
- Là một biến cấu trúc
- Là một con trỏ cấu trúc
- Là một tham chiếu cấu trúc
6.3 Hàm và cấu trúc
Trang 34Giá trị của hàm là cấu trúc:
Ví dụ : Cộng, trừ hai số phức
Hàm cộng 2 số phức, trả lại một số phức
Sophuc Cong(Sophuc x, Sophuc y) {
float thuc;
float ao;
};
6.3 Hàm và cấu trúc
Trang 36Hàm chính
void main()
{
Sophuc x, y, kq ; cout << "x = " ; cin >> x.thuc >> x.ao ; cout << "y = " ; cin >> y.thuc >> y.ao ; cout << "x + y = " ;
kq=cong(x,y);
In(kq);
6.3 Hàm và cấu trúc
Trang 37-Khái niệm -Đặc điểm
6.4 Đệ quy
Trang 38- Đệ quy là một kỹ thuật cho phép trong thân một hàm nào
đó có lời gọi đến chính nó
- Cần phải tránh trường hợp trình tự vô hạn của việc gọi hàm (đệ quy vô hạn)
Khái niệm
Trang 39- Giải bài toán bằng thuật toán đệ 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
Trang 40- Đệ quy có sự liên hệ rất chặt chẽ với quy nạp toán học
- Đệ quy mạnh ở điểm nó có thể định nghĩa một tập vô hạn các đối tượng chỉ bằng một số hữu hạn các mệnh đề
- Ưu thế của thuật toán đệ quy: chỉ cần giải bài toán tại một
số trường hợp đặc biệt nào đó, các trường hợp khác được xác định thông qua trường hợp đặc biệt
* Mọi thuật toán đệ quy đều gồm hai phần:
- Phần cơ sở (trường hợp suy biến): Là các trường hợp không cần thực hiện lại thuật toán
Đặc điểm
Trang 43Ví dụ 3:
int Luythua( int x, int n)
Trang 44Ví dụ 4: Viết hàm tính số Fibonaci bằng đệ quy với f(1)=f(2)=1 và f(n) = f(n-1) + f(n-2) khi n>=3
int Fibo( int n)
Trang 45 Các loại biến và tác dụng của nó:
+ Biến cục bộ (local variable): là các biến được khai báo trong thân của hàm và nó chỉ có tác dụng trong hàm chứa nó Kể cả các biến được khai báp trong hàm main() thì cũng chỉ có tác dụng trong hàm đó mà thôi.
- Biến cục bộ chỉ tồn tại trong thời gian hàm chứa nó còn thực thi Nghĩa là được cấp phát khi hàm chứa nó được gọi tới (hoạt động) và hủy bỏ khi hàm kết thúc.
- Đối số của các hàm cũng được xem như là biến cục bộ.
- Ta có thể khai báo các biến giống nhau ở các hàm khác nhau.
Tổ chức chương trình
Trang 46 Các loại biến và tác dụng của nó:
+ Biến toàn cục (global variable): là các biến được khai báo bên ngoài tất cả các hàm Nó thường được khai báo ở đầu chương trình (trước hàm main)
- Biến toàn cục tồn tại trong suốt quá trình thực thi chương trình
- Tất cả các hàm đều sử dụng được các biến này nếu trong hàm đó không có biến khai báo trùng tên
- Một hàm nếu có biến trùng tên với biến ngoài thì biến ngoài bị che
Tổ chức chương trình
Trang 47 Các loại biến và tác dụng của nó:
+ Một số nguyên tắc sử dụng biến:
- Nếu một biến chỉ sử dụng vì mục đích riêng của một hàm thì nên khai báo biến đó như biến cục bộ trong hàm
- Với các biến mang tính chất sử dụng chung rõ nét mà nhiều hàm
cùng sử dụng chúng với mục đích giống nhau thì nên khai báo chúng như biến ngoài
Tóm lại, nguyên tắc tổng quát nhất là cố gắng tạo hàm một cách độc lập, khép kín, không chịu ảnh hưởng của các hàm khác và không gây ảnh hưởng đến hoạt động của các hàm khác đến mức có thể
Tổ chức chương trình
Trang 49 Các chỉ thị tiền xử lý:
- Chỉ thị macro #define:
Cú pháp: #define macroName StringValue
Tác dụng: trước khi dịch, bộ tiền xử lý sẽ tìm trong chương trình và thay thế bất kỳ vị trí xuất hiện nào của macroName bởi StringName
Macro thường được sử dụng để định nghĩa các hằng hoặc thay cụm từ này thành một cụm từ khác dễ nhớ hơn
Tổ chức chương trình
Trang 50- Max sẽ được thay bởi 10
- true sẽ được thay bởi 1
Trang 51Ví dụ : Để tìm số lớn nhất giữa 2 số ta cũng có thể viết như sau:
#define Max(a, b) ((a)>(b)? (a): (b))
Khi đó, nếu chương trình có câu lệnh: kq = Max(x, y) thì nó sẽ được thay bởi kq = ((a)>(b) ? (a) : (b))
Tổ chức chương trình
Trang 521 Sử dụng hàm, viết chương trình tìm giá trị lớn nhất và giá trị nhỏ nhất của 3 số bất kỳ được nhập vào từ bàn phím.
2 Sử dụng hàm, viết chương trình kiểm tra một số bất kỳ nhập vào từ bàn phím có phải là số nguyên tố hay không? Sau đó hiển thị lên màn hình tất cả các số nguyên tố <= 3000
3 Sử dụng hàm, viết chương trình kiểm tra một năm nhập vào có phải là năm nhuận hay không? Sau đó hiển thị lên màn hình tất cả các năm nhuận nằm trong đoạn [1000,
BÀI TẬP THỰC HÀNH
Trang 535 Sử dụng hàm, viết chương trình kiểm tra một số bất kỳ nhập vào từ bàn phím có phải là số hoàn hảo hay không? Sau
đó hiển tìm và hiển thị lên màn hình tất cả các số hoàn hảo
<= n Với n bất kỳ được nhập vào từ bàn phím Trong đó, số hoàn hảo là số bằng tổng tất cả các ước của nó trừ chính nó Chẳng hạn, số 6 là số hoàn hảo vì 6 = 1 + 2 + 3.
6 Sử dụng hàm, viết chương trình kiểm tra một số bất kỳ nhập vào từ bàn phím có phải là số chính phương hay không? Sau đó tìm và hiển thị ra tất cả các số chính phương <= 1000.
7 Viết chương trình tính và xuất kết quả ra màn hình tổng của n số nguyên tố đầu tiên Với n nguyên dương bất kỳ được
BÀI TẬP THỰC HÀNH
Trang 548 Viết chương trình nhập giá trị cho n (n nguyên dương) sau đó biểu diễn n thành tích các thừa số nguyên tố
9 Sử dụng hàm đệ quy, viết chương trình tính số Fibonacci thứ n Sau đó tính và hiển thị kết quả tổng m số Fibonacci đầu tiên Với m nguyên dương được nhập vào từ bàn phím Trong đó, số Fibonacci được định nghĩa như sau:
1 nếu n = 1 hoặc n = 2 Fibonaci(n) =
Fibonaci(n-1) + Fibonaci(n-2) nếu n>2
10 Sử dụng hàm đệ quy, viết chương trình tìm ƯCLN của 2 số
BÀI TẬP THỰC HÀNH
Trang 5511 Sử dụng hàm đệ quy, viết chương trình tìm ƯCLN của
2 số nguyên dương x, y theo công thức sau:
UCLN(x,y) = x nếu y = 0
UCLN(y, x%y) nếu y khác 0
12 Viết chương trình nhập vào một số bất kỳ rồi hiển thị ra màn hình theo thứ tự ngược lại Chẳng hạn, số nhập vào là
1234 thì kết quả xuất ra là 4321
13 Sử dụng hàm đệ quy, viết chương trình tính x lũy thừa
n Với x là số thực, n là số nguyên được nhập vào từ bàn phím
14 Xây dựng hàm đệ quy tính S(n) = (2n)! với n được
BÀI TẬP THỰC HÀNH
Trang 5615 Sử dụng hàm đệ quy, viết chương trình tính tổng P(n) =
13 + 23 + … + n3 với n được nhập vào từ bàn phím
16 Viết chương trình tính tổ hợp chập k của n với k, n nguyên dương được nhập vào từ bàn phím theo công thức sau: n!/(k!*(n-k)!)
17 Xây dựng hàm đệ quy đếm số chữ số có trong một số nguyên bất kỳ được nhập vào từ bàn phím
18 Viết chương trình tìm tất cả các số tự nhiên có 4 chữ số
mà trong đó mỗi số không có 2 chữ số nào giống nhau
BÀI TẬP THỰC HÀNH