Chương 3 Hàm (Function) Lập trình đơn thể M ỗ i module có d ữ li ệ u riêng độ c l ậ p v ớ i module khác Main Program(Also a module) Data Module 1 + Data Data 1 Procedure 1 Module 2 + Data Data 2 Procedure 2 Procedure 3 Lập trình đơn thể (tt) “Chia để trị”: phân rã bài toán thành các bài toán con cho đến khi “bài toán con” nhận được “đủ nhỏ”. Mỗi “bài toán con” được giải quyết bằng một module, độc lập với các module khác. Trong C mỗi module chính là 1 hàm. Phân tích: top down. Thiết kế: bottom up. Lập trình đơn thể (tt) Bài toán ban đầu module1 module2 module11 module12 modulek phân tích thiết kế Ưu điểm của phương pháp lập trình đơn thể? Cú pháp của hàm <type_function> f_name(parameters) { /* các khai báo cục bộ */ /* các câu lệnh */ [return <Exp>;] /* có thể có hoặc không*/ } Cú pháp của hàm (tt) Ví d ụ 1: void chao() { printf(“\nxin chao”); } Ví d ụ 2: int tong(int n) { int i,t=0; for(i=1;i<=n;++i)t=t+i; return t; } Cú pháp của hàm (tt) Ví dụ 3: int ucln(int x, int y) { while(x*y) if(x>y)x=x%y; else y=y%x; return (x+y); } Lời gọi hàm Ví dụ: chao(); kq1=tong(12); kq2=tong(kq1); kq3=ucln(kq1,15); Có thể không có <tên_hàm>([danh sách tham số thực]) Các bước thực hiện lời gọi hàm Giả sử int a, b, kq; là các biến toàn cục và a=6; b=8; Xét lời gọi hàm: kq = ucln(a,b); (*) Khi đó các bước sau đây được thực hiện: B1: Lưu địa chỉ của câu lệnh kế tiếp sau lời gọi hàm (*) làm địa chỉ quay về sau khi kết thúc hàm. B2: Cấp phát vùng nhớ cho các tham số và các biến cục bộ. Các bước thực hiện lời gọi hàm (tt) 6 8 a b Data Segment Stack Segment x y kq (bước 2) Các bước thực hiện lời gọi hàm (tt) B3: Sao chép giá trị của tham số thực cho tham số hình thức 6 8 a b 6 8 x y kq Các bước thực hiện lời gọi hàm (tt) B4: Thực hiện các câu lệnh trong thân hàm. 6 8 a b 0 2 x y kq Các bước thực hiện lời gọi hàm (tt) B5: Trả lại kết quả bởi lệnh return. 6 8 a b 0 2 x y kq 2 Các bước thực hiện lời gọi hàm (tt) B6: Giải phóng các vùng nhớ đã cấp phát ở B2, lấy địa chỉ đã lưu ở B1 thực hiện tiếp chương trình. 6 8 a b 2 kq Cơ chế truyền tham trị Giá trị của tham số thực được sao chép cho tham số hình thức. Tham số thực luôn luôn được bảo toàn. Như ở ví dụ trên giá trị của a và b sau khi thực hiện (*) vẫn không thay đổi (trong khi x và y đã thay đổi). Con trỏ (pointer) và cơ chế truyền địa chỉ Định nghĩa: con trỏ là biến dùng để chứa địa chỉ của biến khác. Khai báo: Ví dụ: <kiểu_ct> *<tên_ct>; int *p; Khai báo con trỏ kiểu nguyên int Cách sử dụng con trỏ Dùng tên con tr ỏ , gi ố ng nh ư m ộ t bi ế n bình th ườ ng. Dùng d ạ ng khai báo *<tên_ct>, cho k ế t qu ả là d ữ li ệ u mà con tr ỏ đang “tr ỏ ” t ớ i. Có th ể dùng các phép toán đố i v ớ i con tr ỏ (ph ầ n sau) Ví d ụ : int x=13, *p; p=&x; //p tr ỏ t ớ i x. printf(“\n%d duoc luu tai dia chi %p”,x,p); printf(“\np dang tro toi du lieu la %d”,*p); Cách sử dụng con trỏ (tt) 13 &x x=*p p Truyền địa chỉ Trong những trường hợp cần làm cho tham số thực bị thay đổi thì phương pháp truyền tham trị không đáp ứng được. Vậy cần có một phương pháp khác, đó là: Tham số hình thức nhận địa chỉ của tham số thực (nên tham số hình thức phải là một con trỏ). Truyền địa chỉ Ví dụ: void hoan_vi(int *x, int *y) { int t=*x; *x=*y; *y=t; } Giả sử int a,b là các biến toàn cục và a=5; b=7; Xét lời gọi hàm: hoan_vi(&a,&b); khi đó: Truyền địa chỉ (tt) 8 6 a b &a &b x y 6 t 6 8 a b x y t Hàm đệ quy Đối tượng đệ quy: là đối tượng được xây dựng thông qua chính nó. (đối tượng có thể là: bài toán, hàm, kiểu dữ liệu ) Ví dụ: xét bài toán P(n) = 1+2+ +n. Bài toán này có lời giải (đệ quy như sau): >+−= = )0()1()( 0)0( nnnpnp p Hàm đệ quy (tt) Hàm đệ quy là hàm mà trong thân của nó chứa lời gọi đến chính nó. Ví dụ 1: hàm tính p(n) int p(int n) { if(n==0)return 0; else return p(n-1)+n; } Phần neo Phần đệ quy Hàm đệ quy (tt) Ví dụ 2: tính F(n) biết −+−= == )2()1()( 1)2()1( nfnfnf ff với n>2 int F(int n) { if(n==1||n==2) return 1; else return F(n-1)+F(n-2); } Phân tích hàm đệ quy Xét lời gọi hàm t=F(4); Số hàm được gọi chính là số nút trên cây. Do đó với kích thước tham số lớn hàm đệ quy tiêu tốn nhiều thời gian và bộ nhớ. t=F(4) F(3) F(2) F(2) F(1) + || 1 || 1 || 1 + Hỏi đáp . y kq (bư c 2) C c bư c th c hiện lời gọi hàm (tt) B3: Sao chép giá trị c a tham số th c cho tham số hình th c 6 8 a b 6 8 x y kq C c bư c th c hiện lời gọi hàm (tt) B4: Th c hiện c c câu lệnh trong. th c] ) C c bư c th c hiện lời gọi hàm Giả sử int a, b, kq; là c c biến toàn c c và a=6; b=8; Xét lời gọi hàm: kq = ucln(a,b); (*) Khi đó c c bư c sau đây đư c th c hiện: B1: Lưu địa chỉ c a c u. sau lời gọi hàm (*) làm địa chỉ quay về sau khi kết th c hàm. B2: C p phát vùng nhớ cho c c tham số và c c biến c c bộ. C c bư c th c hiện lời gọi hàm (tt) 6 8 a b Data Segment Stack Segment x