Tải bản đầy đủ (.pdf) (14 trang)

CPP4 ham

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (456.99 KB, 14 trang )

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
Đị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ể
HIENLTH, C++ - 2010

HIENLTH, C++ - 2010

2

Hàm thư viện

Khái niệm hàm và lập trình cấu trúc

Hàm đã được chuẩn hóa, sẵn sàng cho dùng lại.
Toán học (cmath)
Xử lý xâu ký tự (cstring)
Hàm nhập/xuất (cin/cout)

Tư tưởng chính
Chia bài toán lớn thành các bài toán nhỏ, hoặc phân
rã quá trình giải bài toán thành một số hữu hạn các
bước.
Với mỗi bài toán con hoặc một bước giải bài toán, xây
dựng một (hoặc nhiều) hàm (thủ tục) giải quyết.



Mỗi hàm (thủ tục) là một đơn vị hoàn chỉnh, độc
lập về đoạn mã và dữ liệu nhằm thi hành một tác
vụ nào đó.
Mỗi hàm (thủ tục) nên được thiết kế chỉ để thi
hành một và chỉ một tác vụ duy nhất.
HIENLTH, C++ - 2010

3

HIENLTH, C++ - 2010

4


Một số nguyên tắc
Các hàm trong C++ đều ngang cấp với nhau:
Hàm không được khai báo lồng nhau.
Thứ tự khai báo không quan trọng.
Hàm có thể nhận và xử lý nhiều tham số hoặc
không có tham số nào
Hàm có thể trả về một giá trị hoặc không.
Biến khai báo trong hàm F chỉ có giá trị trong F,
không sử dụng được biến này trong các hàm
khác được.

Ví dụ: hàm tính xn

double
Power(double x, int n)

{
double result;
for(result = 1; n; n--)
result *= x;
return result;
}
giá trị được trả về qua lệnh return

HIENLTH, C++ - 2010

Ví dụ: gọi thực hiện hàm Power

HIENLTH, C++ - 2010

Một số lỗi thường gặp

Chỉ thị cho chương trình biết prototype của hàm Power

#include <iostream>
using namespace std;
double Power(double, int);
int
{

Compiler không hiểu được hàm Power

#include <iostream>
using namespace std;
int
{


main()
double m = Power(2, 3);
cout<<“3.5 ^ 4 = ”<return 0;

nhận vào 2 tham số khi được gọi

kiểu của giá trị trả về

hàm Power thiếu tham số

main()

int m = Power(2, 3);
cout<<“3.5 ^ 4 = ”<return 1.0;
}

}
3.5 và 4: 2 tham số thực sự
HIENLTH, C++ - 2010

giá trị trả về không khớp kiểu
HIENLTH, C++ - 2010


Khai báo hàm dạng nguyên mẫu
(prototype)


Ví dụ:

Mục đích:

void xuatPhanSo(int, int);

Chỉ ra prototype của hàm bao gồm: tên hàm, kiểu các
tham số và kiểu trả về.
Báo cho trình biên dịch biết rằng có một hàm như vậy

hàm có tên là xuatPhanSo
có hai tham số; cả hai đều có kiểu là số nguyên (int)
không có giá trị trả về

Cú pháp:

void xuatPhanSo(PhanSo);
void nhapPhanSo(int&, int&);

<kiểu trả về> <tên hàm> ( các tham số> );

Trong đó:

Hàm có tên là nhapPhanSo
Có hai tham số; cả hai đều có kiểu tham chiếu đến số
nguyên (int&)
Không có giá trị trả về

<kiểu trả về>: là một kiểu do C++ hỗ trợ hoặc do

người dùng tạo ra
<tên hàm>: tên của hàm
<danh sách kiểu các tham số>: chỉ ra kiểu của
các tham số của hàm
HIENLTH, C++ - 2010

void nhapPhanSo(PhanSo&);
9

Ví dụ:

HIENLTH, C++ - 2010

10

Khai báo một hàm (tt)
Có thể đưa vào tên của tham số (không chỉ kiểu
của tham số)
Ví dụ:
void xuatPhanSo(int tuso, int mauso);
void nhapPhanSo(int& tuso, int& mauso);
double tinhLuong(double thamnien);
void thongbaoLoi();

double tinhLuong(double);
Hàm có tên là: tinhLuong
Có một tham số, có kiểu là số thực (double)
Có giá trị trả về là số thực
void thongbaoLoi();
Hàm có tên là: thongbaoLoi

Không có tham số
Không có giá trị trả về
HIENLTH, C++ - 2010

11

HIENLTH, C++ - 2010

12


Định nghĩa một hàm

Định nghĩa một hàm

Mục đích:

Lưu ý:

Chỉ rõ cụ thể việc cài đặt của hàm
Các công việc mà hàm sẽ làm
Dữ liệu và đoạn mã của hàm sử dụng

Danh sách tham số phải có kiểu trùng với danh sách
kiểu tham số đã được khai báo trước đó.
Trong danh sách các tham số phải có tên tham số
Kết thúc hàm và trả về giá trị cho lời gọi hàm:
return <giá trị trả về>;

Cú pháp:

kiểu trả về tên hàm(danh sách tham số hình thức)
{
//khai báo các biến của hàm
//các lệnh thực thi
return giá trị trả về; //hàm void không có giá trị trả về
}
HIENLTH, C++ - 2010

13

HIENLTH, C++ - 2010

Ví dụ

Ví dụ

Khai báo hàm:
void xuatPhanSo(PhanSo);
Định nghĩa hàm:
void xuatPhanSo(PhanSo ps)
{
cout << ps.tu << “/ “ << ps.mau;
}

// khai báo hàm
void xuatPhanSo(int, int);

// định nghĩa hàm
void xuatPhanSo(int tuso, int mauso)
{

cout << tuso << “/” << mauso;
}

HIENLTH, C++ - 2010

15

HIENLTH, C++ - 2010

14

Thân hàm

16


Ví dụ

Ví dụ
// khai báo hàm
void nhapPhanSo(int&, int&);

// định
nh nghĩa
ngh a hàm
void nhapPhanSo(int& tuso, int& mauso)
{
cout << “Nhập vào tử số và mẫu số: “;
cin >> tuso >> mauso;
}

Thân hàm

Khai báo hàm:
void nhapPhanSo(PhanSo&);
Định nghĩa hàm
void nhapPhanSo(PhanSo& ps)
{
cout << “Nhập vào tử và mẫu: “;
cin >> ps.tu >> ps.mau;
}
HIENLTH, C++ - 2010

17

Ví dụ

HIENLTH, C++ - 2010

18

Lời gọi hàm

// khai báo hàm
double tinhLuong(double);

// định nghĩa hàm
double tinhLuong(double thamnien)
{
Thân hàm
const double LCB = 540000;

double heso, luong;
if (thamnien < 12)
heso = 1.92;
else if (thamnien < 36)
heso = 2.34;
else
heso = 3.5;
Kết thúc hàm và trả về giá
luong = heso * LCB;
trị cho lời gọi hàm
return luong;
}

HIENLTH, C++ - 2010

Mục đích:
“Gọi” một hàm đã được khai báo và định nghĩa
Trả về giá trị sau khi hàm được gọi thi hành xong

Cú pháp:
<tên hàm> (<các tham số thật sự>)

Trong đó:

<tên hàm>: tên của hàm muốn gọi. Hàm đó phải
được khai báo trước đó.
<các tham số thật sự>: các tham số thật sự cho
lời gọi hàm này.

19


HIENLTH, C++ - 2010

20


Ý nghĩa của định nghĩa hàm và lời gọi
hàm

Ví dụ
int main()
{
int a, b;
nhapPhanSo(a, b);
xuatPhanSo(a, b);
return 0;
}

void xuatPhanSo(int tuso, int mauso)
{
cout << tuso << “/” << mauso;
}

Gọi hàm nhapPhanSo với tham
số thực là biến a và biến b

xuatPhanSo(tuso, mauso)

Gọi hàm xuatPhanSo với tham
số thực là giá trị của a và giá trị

của b

HIENLTH, C++ - 2010

Xuất ra màn hình một Xuất ra màn hình một
phân số có tử và mẫu phân số có tử là 4 và
mẫu là 5
là số nguyên
21

Ý nghĩa của định nghĩa hàm và lời gọi
hàm

nhapPhanSo(a, b)

Nhập vào giá trị cho tử
số và mẫu số của một
phân số nào đó

Nhập vào giá trị cho tử
số a và mẫu số b

HIENLTH, C++ - 2010

HIENLTH, C++ - 2010

22

Ý nghĩa của định nghĩa hàm và lời gọi
hàm

double tinhLuong(double thamnien)
{
const double LCB = 54000;
double heso, luong;
if (thamnien < 12)
heso = 1.92;

void nhapPhanSo(int& tuso, int& mauso)
{
cout << “Nhập vào ttử ssố và m
mẫu
u ssố:: “;
cin >> tuso >> mauso;
}
nhapPhanSo(tuso, mauso)

xuatPhanSo(4, 5)

else if (thamnien < 36)
heso = 2.34;
else
heso = 3.5;
luong = heso * LCB;
return luong;
}

23

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)

HIENLTH, C++ - 2010

24


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.
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.

HIENLTH, C++ - 2010

25

Tham số của hàm

void nhapPhanSo(int& tuso,
int& mauso)
{
cout << “Nhập vào tử số và
mẫu số: “;
cin >> tuso >> mauso;
}
void xuatPhanSo(int tuso, int
mauso)
{
cout << tuso << “/” <<
mauso;
}

HIENLTH, C++ - 2010

26

Tham số của hàm (tt)

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
th c và tham số hình thức trong
đị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.
HIENLTH, C++ - 2010

int main()
{
int a, b;
nhapPhanSo(a, b);
xuatPhanSo(a, b);
return 0;
}

27

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
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ỏ)


HIENLTH, C++ - 2010

28


Truyền giá trị - ví dụ

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
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

HIENLTH, C++ - 2010

#include <iostream>
using namespace std;
void change(int v);

hàm change
không thay đổi
giá trị của “var”


int main()
{
int var = 5;
change(var);
cout<<"main: var = “<return 0;
change: v = 500
}
main: var = 5
void change(int v)
{
v *= 100;
cout<<"change: v = “<}
HIENLTH, C++ - 2010

Ví dụ tham trị: nhập a=4, b=5

Ví dụ tham chiếu: nhập a=4, b=5

void main()
{
int a, b;
nhapPhanSo(a, b);
xuatPhanSo(a, b);
}

void main()
{

int a, b;
nhapPhanSo(a, b);
xuatPhanSo(a, b);
}

a

b
4

void nhapPhanSo(int& tuso, int& mauso)
{
cout << “Nhập vào tử số và mẫu số: “;
cin >> tuso >> mauso;
}
void xuatPhanSo(int tuso, int mauso)
{
cout << tuso << “/” << mauso;
}
tuso

5

4

HIENLTH, C++ - 2010

a, tuso

mauso


4

5

31

b, mau
5

void nhapPhanSo(int& tuso, int&
mauso)
{
cout << “Nhập vào tử số và
mẫu số: “;
cin >> tuso >> mauso;
}
void xuatPhanSo(int tuso, int
mauso)
{
cout << tuso << “/” << mauso;
}

HIENLTH, C++ - 2010

32


Tham số mặc định


Ví dụ 1
// khai báo hàm
void xuatPhanSo(int tuso = 0, int mauso = 1);

// Sử dụng hàm
// định nghĩa hàm
void main()
void xuatPhanSo(int tuso, int mauso)
{
{
xuatPhanSo();
cout << tuso << “/” << mauso;
xuatPhanSo(4);
}
xuatPhanSo(2, 5);


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:
Khai báo hàm:
<kiểu trả về> <tên 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

trái,
không có tham số không mặc định chèn ở giữa
HIENLTH, C++ - 2010

}

33

HIENLTH, C++ - 2010

Ví dụ 2

Ví dụ 3

// khai báo hàm
void xuatPhanSo(int tuso, int mauso = 1);

// Sử dụng hàm
// định nghĩa hàm
void main()
void xuatPhanSo(int tuso, int mauso)
{
{
xuatPhanSo();
cout << tuso << “/” << mauso;
xuatPhanSo(4);
}
xuatPhanSo(2, 5);

}


// khai báo hàm
void xuatPhanSo(int tuso = 1, int mauso);

// Sử dụng hàm
// định nghĩa hàm
void xuatPhanSo(int tuso, int mauso) void main()
{
{
xuatPhanSo();
cout << tuso << “/” << mauso;
xuatPhanSo(4);
}
xuatPhanSo(2, 5);


HIENLTH, C++ - 2010

35

34

}

HIENLTH, C++ - 2010

36


Quá tải hàm


Quá tải hàm (tt)

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.
Bao gồm:
Tên hàm
Kiểu tham số của hàm
Số tham số của hàm

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
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ụ:
Khác với

void xuatPhanSo(int tuso, int mauso);
Có kí hiệu là xuatPhanSo_int_int
HIENLTH, C++ - 2010


void xuatPhanSo(int tuso, int mauso);
void xuatPhanSo(int tuso);

37

Ví dụ 1

HIENLTH, C++ - 2010

38

Ví dụ 2

void main()
{
xuatPhanSo(1, 2);
xuatPhanSo(1.0, 2.0);
double a, b;
cin >> a >> b;
xuatPhanSo(a, b);
}

void xuatPhanSo(int tuso, int mauso)
{
cout << tuso << “/” << mauso;
}

void xuatPhanSo(double tuso, double
mauso)
{

cout << tuso << “/” << mauso;
}

HIENLTH, C++ - 2010

39

void main()
{
int a, b;
nhapPhanSo(a, b);
xuatPhanSo(a, b);
xuatPhanSo(a);
}

void xuatPhanSo(int tuso, int mauso)
{
cout << tuso << “/” << mauso;
}
void xuatPhanSo(int tuso)
{
cout << tuso;
}

HIENLTH, C++ - 2010

40


Quá tải toán tử


Quá tải toán tử (tt)

Một toán tử (phép toán) thực chất là một hàm có
dạng như sau:

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à
operator <kí hiệu phép toán>

<kiểu trả về> operator toán> ( <danh sách các tham số> );
;

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)

Ứ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.

41

HIENLTH, C++ - 2010


Ví dụ 1

42

HIENLTH, C++ - 2010

Ví dụ 2
void main()
{
A a;
B b;
//int c = a+b;
int c = b+a;
cout << c;
cin.get();
}

class A{
public:
int a;
A():a(0){};
};
class B{
public:
int b;
B():b(10){};
};
int operator + (A aObj, B bObj)
{

return aObj.a+bObj.b;
}

HIENLTH, C++ - 2010

class A{
public:
int a;
A():a(0){};
};
ostream& operator << (ostream& out, A aObj)
{
return out << aObj.a;
}

43

HIENLTH, C++ - 2010

void main()
{
A a;
B b;
int c = a+b;
cout << c;
cout << a;
cin.get();
}

44



Bài đọc thêm: tổ chức dữ liệu

Lư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
đ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

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

Heap
Data
segment
Stack


Dữ liệu còn có thể được đặt trong vùng nhớ heap.

HIENLTH, C++ - 2010

45

Đệ quy

HIENLTH, C++ - 2010

Ví dụ: Hàm tính số Fn dãy Fibonaci

Cấu trúc đệ quy
Tự định nghĩa qua chính nó
Có cấu trúc nguyên thủy
Hàm đệ quy
Gọi lại chính nó (trực tiếp hay gián tiếp)
Có điểm dừng

HIENLTH, C++ - 2010

int Fibo(int n)
{

if (n < 1) return 0;
if (1 == n) return 1;
return Fibo (n-1) + Fibo (n-2);
}


47

HIENLTH, C++ - 2010

48


Ứng dụng đệ quy

Ví dụ: Hàm tính số n!

Bài toán có cấu trúc đệ quy
Thuật toán chia để trị
Tìm kiếm quay lui


int Factor(int n)
{

if (n <= 1) return 1;
return Factor (n-1) * n;
}

HIENLTH, C++ - 2010

49

Đệ quy và lặp

HIENLTH, C++ - 2010


50

Tổ chức chương trình dạng đơn thể

Đệ quy
Súc tích, dễ hiểu
Có thể không hiệu quả

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)
File *.h:

Phí tổn cho lời gọi hàm
Lặp lại các kết quả đã có

chỉ chứa khai báo thư viện
Khai báo các hàm dạng nguyên mẫu(prototype)

Nên chuyển thành chương trình lặp (nếu có thể)
Giai thừa, Fibonaci

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

HIENLTH, C++ - 2010

51


HIENLTH, C++ - 2010

52


Ví dụ

Thư viện cmath
Khai báo sử dụng thư viện

//File Vidu.cpp

//File Vidu.h

#include <cmath>
#include <iostream>
using namespace std;
long tinhGiaiThua(int n);
void nhapThongTin();

#include “Vidu.h”

Một số hàm cơ bản

long tinhGiaiThua(int n){
//…….
}
void nhapThongTin(){
//……

}

HIENLTH, C++ - 2010

53

55

Hàm toán

Tên

Hàm toán Tên

Hàm toán

asin
acos
atan

arcsin(x)
arccos(x)
arctan(x)

sin
cos
tan

sin(x)
cos(x)

tan(x)

log
sqrt

ln(x)
x1/2

pow
exp

xa
ex

abs
ceil
floor
fabs

|x|:int
cận trên
cận dưới
|x|:double

labs

|x|:long

HIENLTH, C++ - 2010


Câu hỏi và thảo luận

HIENLTH, C++ - 2010

Tên

͡͡

54



Tài liệu bạn tìm kiếm đã sẵn sàng tải về

Tải bản đầy đủ ngay
×