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