Slide bài giảng Lập trình C++ - Lương Trần Hy Hiến - Hàm lập trình cấu trúc
Nội dung
Khái niệm hàm và lập trình cấu trúc
Khai báo và Định nghĩa một hàm trong C++
Lời gọi hàm
Tham sốcủa hàm
Tham sốcủa hàm
Định nghĩa chồng các hàm
Hàm toán tử
Định nghĩa chồng các toán tử
Đệquy
Tổchức chương trình dạng đơn thể
= 3.5;
luong = heso * LCB;
HIENLTH, C++ - 2010 24
heso = 1.92;
tinhLuong(thamnien) tinhLuong(30)
Tính lương cho một nhân viên
nào đó có thâm niên nào đó
Tính lương cho nhân viên có
thâm niên công tác 30 tháng
Trả về: lương của nhân viên
(chưa xác định)
Trả về lương của nhân viên
(2.34 * 540000)
return luong;
}
Tiến trình thi hành một lời gọi hàm
Luồng điều khiển được tạm thời chuyển sang
cho hàm được gọi.
Thực hiện các lệnh nằm trong thân hàm được
gọi.
HIENLTH, C++ - 2010
Nếu gặp câu lệnh return thì kết thúc hàm được
gọi; chuyển quyền điều khiển lại cho nơi gọi
hàm; trả về kết quả cho lời gọi hàm.
Nếu không có giá trị trả về thì đến khi kết thúc tất
cả các lệnh trong thân hàm được gọi sẽ chuyển
quyền điều khiển cho nơi gọi hàm.
25
void nhapPhanSo(int& tuso,
int& mauso)
{
cout << “Nhập vào tử số và
mẫu số: “;
cin >> tuso >> mauso;
int main()
{
int a, b;
HIENLTH, C++ - 2010
}
void xuatPhanSo(int tuso, int
mauso)
{
cout << tuso << “/” <<
mauso;
}
26
nhapPhanSo(a, b);
xuatPhanSo(a, b);
return 0;
}
Tham số của hàm
Có 3 dạng:
Tham trị - call by value
Con trỏ - call by address
Tham chiếu - call by reference
Tham trị
Quan hệ giữa tham số th c và tham số hình thức trong
HIENLTH, C++ - 2010
ự
định nghĩa hàm là quan hệ giá trị.
Khi có một lời gọi hàm, các tham số hình thức sẽ được cấp
phát vùng nhớ.
Giá trị của tham số hình thức sẽ được gán bởi giá trị của
các tham số thực.
Tham số hình thức và tham số thực trở nên hoàn toàn độc
lập. Thay đổi trên tham số hình thức không ảnh hưởng đến
tham số thực.
27
Tham số của hàm (tt)
Con trỏ: (*)
Một trường hợp đặc biệt của tham trị
Giá trị ở đây là giá trị địa chỉ do con trỏ (tham
HIENLTH, C++ - 2010
số thực) đang lưu.
Hoạt động theo tính chất của con trỏ.
(Sẽ được học kỹ hơn trong phần Con trỏ)
28
Tham số của hàm (tt)
Tham chiếu (&)
Quan hệ giữa tham số hình thức và tham số
thực là quan hệ “bí danh”: một vùng nhớ được
đặt theo 2 tên khác nhau; cả 2 tên đều cùng
HIENLTH, C++ - 2010
chỉ đến một vùng nhớ.
Khi có một lời gọi hàm, tham số thực truyền
theo kiểu tham chiếu sẽ được đặt thêm một
tên mới, chính là tên của tham số hình thức.
Mọi thay đổi trên tham số hình thức cũng tức
là thay đổi trên tham số thực.
29
Truyền giá trị - ví dụ
#include
using namespace std;
void change(int v);
int main()
{
hàm change
không thay đổi
giá trị của “var”
HIENLTH, C++ - 2010
int var = 5;
change(var);
cout<<"main: var = “<<var);
return 0;
}
void change(int v)
{
v *= 100;
cout<<"change: v = “<<v);
}
change: v = 500
main: var = 5
Ví dụ tham trị: nhập a=4, b=5
void nhapPhanSo(int& tuso, int& mauso)
{
cout << “Nhập vào tử số và mẫu số: “;
cin >> tuso >> mauso;
}
void main()
{
int a, b;
HIENLTH, C++ - 2010
void xuatPhanSo(int tuso, int mauso)
{
cout << tuso << “/” << mauso;
}
31
nhapPhanSo(a, b);
xuatPhanSo(a, b);
}
4 5
a b
4 5
tuso mauso
Ví dụ tham chiếu: nhập a=4, b=5
void nhapPhanSo(int& tuso, int&
mauso)
{
cout << “Nhập vào tử số và
mẫu số: “;
void main()
{
int a, b;
HIENLTH, C++ - 2010
cin >> tuso >> mauso;
}
void xuatPhanSo(int tuso, int
mauso)
{
cout << tuso << “/” << mauso;
}
32
nhapPhanSo(a, b);
xuatPhanSo(a, b);
}
4 5
a, tuso b, mau
Tham số mặc định
Công dụng
Cho phép truyền tham số một cách linh họat
Nếu có truyền thì lấy giá trị truyền vào
Nếu không có truyền thì lấy giá trị mặc định
Cú pháp:
HIENLTH, C++ - 2010
Khai báo hàm:
(kiểu tham_số_1 =
giá_trị[,kiểu tham_số_1 = giá_trị]);
Lưu ý:
Định nghĩa hàm vẫn như bình thường
Tham số mặc định bắt buộc phải đi từ phải qua trái,
không có tham số không mặc định chèn ở giữa
33
Ví dụ 1
// khai báo hàm
void xuatPhanSo(int tuso = 0, int mauso = 1);
…
// định nghĩa hàm
void xuatPhanSo(int tuso, int mauso)
// Sử dụng hàm
void main()
HIENLTH, C++ - 2010
{
cout << tuso << “/” << mauso;
}
…
34
{
xuatPhanSo();
xuatPhanSo(4);
xuatPhanSo(2, 5);
}
Ví dụ 2
// khai báo hàm
void xuatPhanSo(int tuso, int mauso = 1);
…
// định nghĩa hàm
void xuatPhanSo(int tuso, int mauso)
// Sử dụng hàm
void main()
HIENLTH, C++ - 2010
{
cout << tuso << “/” << mauso;
}
…
35
{
xuatPhanSo();
xuatPhanSo(4);
xuatPhanSo(2, 5);
}
Ví dụ 3
// khai báo hàm
void xuatPhanSo(int tuso = 1, int mauso);
…
// định nghĩa hàm
void xuatPhanSo(int tuso, int mauso)
// Sử dụng hàm
void main()
HIENLTH, C++ - 2010
{
cout << tuso << “/” << mauso;
}
…
36
{
xuatPhanSo();
xuatPhanSo(4);
xuatPhanSo(2, 5);
}
Quá tải hàm
Dấu hiệu của hàm (signature)
Dùng để phân biệt các hàm với nhau. Mỗi hàm
trong chương trình phải có một dấu hiệu duy
nhất.
HIENLTH, C++ - 2010
Bao gồm:
Tên hàm
Kiểu tham số của hàm
Số tham số của hàm
void xuatPhanSo(int tuso, int mauso);
Có kí hiệu là xuatPhanSo_int_int
37
Quá tải hàm (tt)
void xuatPhanSo(double tuso, double mauso);
Có kí hiệu là xuatPhanSo_double_double
Quá tải hàm
Hai hàm có cùng tên, có cùng số tham số và tồn tại
ít nhất một tham số khác nhau thì khác nhau
HIENLTH, C++ - 2010
Ví dụ: void xuatPhanSo(int tuso, int mauso);
Khác với
void xuatPhanSo(double tuso, double mauso);
Hai hàm có cùng tên, khác số tham số thì khác nhau
Ví dụ: void xuatPhanSo(int tuso, int mauso);
Khác với
void xuatPhanSo(int tuso);
38
Ví dụ 1
void main()
{
xuatPhanSo(1, 2);
xuatPhanSo(1.0, 2.0);
void xuatPhanSo(int tuso, int mauso)
{
cout << tuso << “/” << mauso;
}
HIENLTH, C++ - 2010 39
double a, b;
cin >> a >> b;
xuatPhanSo(a, b);
}
void xuatPhanSo(double tuso, double
mauso)
{
cout << tuso << “/” << mauso;
}
Ví dụ 2
void main()
{
int a, b;
void xuatPhanSo(int tuso, int mauso)
{
cout << tuso << “/” << mauso;
}
HIENLTH, C++ - 2010 40
nhapPhanSo(a, b);
xuatPhanSo(a, b);
xuatPhanSo(a);
}
void xuatPhanSo(int tuso)
{
cout << tuso;
}
Quá tải toán tử
Một toán tử (phép toán) thực chất là một hàm có
dạng như sau:
operator <kí hiệu phép
toán> ( );
HIENLTH, C++ - 2010
Trong đó danh sách các tham số là các toán
hạng
Ví dụ:
3+4: là phép toán + có hai toán hạng là hai số nguyên;
kết quả trả về một số nguyên
int operator + (int a, int b)
41
Quá tải toán tử (tt)
Chính nhờ kí hiệu của hàm bao gồm tên hàm và
các tham số mà ta có thể quá tải toán tử. Bởi vì
các toán tử cùng chung kí hiệu đều có cùng tên
hàm là
HIENLTH, C++ - 2010
operator
Ứng dụng:
Dùng tóan tử xuất, nhập trên các đối tượng
một cách bình thường.
42
Ví dụ 1
class A{
public:
int a;
A():a(0){};
};
class B{
void main()
{
A a;
B b;
//int c = a+b;
HIENLTH, C++ - 2010
public:
int b;
B():b(10){};
};
int operator + (A aObj, B bObj)
{
return aObj.a+bObj.b;
}
43
int c = b+a;
cout << c;
cin.get();
}
Ví dụ 2
class A{
public:
int a;
A():a(0){};
};
void main()
{
A a;
B b;
HIENLTH, C++ - 2010
ostream& operator << (ostream& out, A aObj)
{
return out << aObj.a;
}
44
int c = a+b;
cout << c;
cout << a;
cin.get();
}
Lưu ý:
Môn này không cung cấp các kiến thức chuyên
sâu về OOP (lập trình hướng đối tượng),
operator overloading (quá tải toán tử),… SV tự
tìm hiểu + được học ở môn học kế tiếp OOP
HIENLTH, C++ - 2010 45
Bài đọc thêm: tổ chức dữ liệu
Dữ liệu trong chương trình được lưu trữ trong các biến.
Khi hàm được gọi thực hiện, các biến cục bộ sẽ được
khởi tạo trên vùng nhớ stack và tự động bị hủy khi hàm
kết thúc.
Các biến toàn cục sẽ được tạo trên vùng nhớ phân
Heap
Data
segment
HIENLTH, C++ - 2010
đoạn dữ liệu (data segment) khi chương trình được gọi
thực hiện, tự động bị hủy khi chương trình kết thúc.
Có thể sử dụng các từ khóa để chỉ định vị trí của biến:
auto - stack (default)
static - data segment
register - thanh ghi của CPU
Dữ liệu còn có thể được đặt trong vùng nhớ heap.
Stack
Đệ quy
Cấu trúc đệ quy
Tự định nghĩa qua chính nó
Có cấu trúc nguyên thủy
HIENLTH, C++ - 2010
Hàm đệ quy
Gọi lại chính nó (trực tiếp hay gián tiếp)
Có điểm dừng
47
Ví dụ: Hàm tính số Fn dãy Fibonaci
int Fibo(int n)
{
if (n < 1) return 0;
HIENLTH, C++ - 2010
if (1 == n) return 1;
return Fibo (n-1) + Fibo (n-2);
}
48
Ví dụ: Hàm tính số n!
int Factor(int n)
{
if (n <= 1) return 1;
HIENLTH, C++ - 2010
return Factor (n-1) * n;
}
49
Ứng dụng đệ quy
Bài toán có cấu trúc đệ quy
Thuật toán chia để trị
Tìm kiếm quay lui
HIENLTH, C++ - 2010
…
50
Đệ quy và lặp
Đệ quy
Súc tích, dễ hiểu
Có thể không hiệu quả
HIENLTH, C++ - 2010
Phí tổn cho lời gọi hàm
Lặp lại các kết quả đã có
Nên chuyển thành chương trình lặp (nếu có thể)
Giai thừa, Fibonaci
51
Tổ chức chương trình dạng đơn thể
Phân thành các hàm, module
Tổ chức chương trình thành Header file (*.h) và
Source Code (*.cpp)
HIENLTH, C++ - 2010
File *.h:
chỉ chứa khai báo thư viện
Khai báo các hàm dạng nguyên mẫu(prototype)
File *.cpp:
Chèn file header đã khai báo
Cài đặt các hàm đã khai báo nguyên mẫu ở file *.h
52
Ví dụ
//File Vidu.h
#include
using namespace std;
//File Vidu.cpp
#include “Vidu.h”
HIENLTH, C++ - 2010
long tinhGiaiThua(int n);
void nhapThongTin();
53
long tinhGiaiThua(int n){
//…….
}
void nhapThongTin(){
//……
}
Thư viện cmath
Khai báo sử dụng thư viện
#include
Một số hàm cơ bản
HIENLTH, C++ - 2010
Tên Hàm toán Tên Hàm toán Tên Hàm toán
asin arcsin(x) sin sin(x) abs |x|:int
acos arccos(x) cos cos(x) ceil cận trên
atan arctan(x) tan tan(x) floor cận dưới
log ln(x) pow x
a
fabs |x|:double
sqrt x
1/2
exp e
x
labs |x|:long
54
Câu hỏi và thảo luận
HIENLTH, C++ - 2010 55
File đính kèm:
Slide bài giảng Lập trình C++ - Lương Trần Hy Hiến - Hàm lập trình cấu trúc.pdf

