Tài liệu Kỹ thuật lập trình đơn thể ppt

15 970 4
Tài liệu Kỹ thuật lập trình đơn thể ppt

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

Thông tin tài liệu

Chơng III. Kỹ thuật lập trình đơn thể I. Định nghĩa và sử dụng đơn thể 1. Khái niệm phân loại Khái niệm: Đơn thể (hay Module) là một đoạn chơng trình đợc viết theo một cấu trúc nào đó, giải quyết một vấn đề tơng đối độc lập của bài toán. Khi viết một chơng trình, chúng ta có thể triển khai theo hai cách: Cách 1: Toàn bộ các lệnh của chơng trình đợc viết trong hàm main(). Các lệnh đợc viết theo trình tự để giải quyết bài toán đặt ra. Cách 2: Chơng trình đợc tạo thành từ nhiều đơn thể khác nhau. Các đơn thể thực hiện những nhiệm vụ tơng đối độc lập và đợc lắp ghép lại thành ch- ơng trình thông qua những lời gọi đơn thể trong hàm main(). u nhợc điểm: - Với cách 1: sẽ thích hợp khi viết những chơng trình có kích thớc nhỏ. Toàn bộ thuật toán đợc thể hiện trong một đoạn mã từ trên xuống dới. Tuy nhiên, cách này không phù hợp với các chơng trình lớn do: + Kích thớc chơng trình cồng kềnh, khó kiểm soát, chỉnh sửa. + Các đoạn mã có thể lặp đi lặp lại, chơng trình dài không cần thiết. - Với cách 2: Chơng trình đợc chia nhỏ thành các đơn thể khắc phục đợc hai nhợc điểm cơ bản trên. Đặc biệt phù hợp với các chơng trình có kích thớc lớn. Trong C++, ta có hai loại đơn thể sau: [1]. Các lớp đối tợng: Chơng trình bao gồm một số đoạn mã mô tả các lớp các đối tợng nào đó sẽ sử dụng trong chơng trình chính. Loại đơn thể này đ- ợc nghiên cứu trong nội dung môn học Lập trình hớng đối tợng. [2]. Các hàm: Chơng trình đợc cấu tạo từ các hàm. Mỗi hàm thực thi một nhiệm vụ tơng đối độc lập, trong đó có một hàm main đóng vai trò nh chơng trình chính để sử dụng các hàm khác. Trong phạm vi môn học, ta chỉ xem xét các đơn thể dới dạng các hàm. 2. Các đặc trng của hàm Một hàm trong C++ có các đặc trng sau: [1]. Tên hàm: do ngời lập trình tự đặt và có những đặc điểm sau: + Tên hàm thờng mang tính đại diện cho công việc mà hàm sẽ đảm nhiệm. + Tên hàm đợc đặt tuỳ ý nhng tuân theo quy ớc đặt tên trong C++. [2]. Kiểu giá trị trả về của hàm: Nếu hàm trả về một giá trị thì giá trị đó phải thuộc một kiểu dữ liệu nào đó; ta gọi là kiểu giá trị trả về của hàm. Kiểu giá trị trả về của hàm có thể là các kiểu dữ liệu chuẩn. Đề cơng chi tiết Kỹ thuật lập trình [3]. Các đối của hàm: Nếu hàm sử dụng các đối thì các đối phải thuộc một kiểu dữ liệu nào đó. Khi thiết lập một hàm, ta cần chỉ ra danh sách các đối của hàm và kiểu dữ liệu của mỗi đối. [4]. Thân hàm: là nội dung chính của hàm, chứa toàn bộ các lệnh của hàm. 3. Phân loại hàm Tùy theo nguồn gốc của hàm ta phân ra: - Các hàm có sẵn: Là các hàm chứa trong các th viện của C++, đã đợc định nghĩa từ trớc. Các hàm này đợc đặt trong các th viện .h. Ngời lập trình chỉ việc sử dụng chúng thông qua các chỉ thị: #include <Tên th viện chứa hàm> mà không cần định nghĩa hàm. VD: Các hàm sqrt(); sin(); cos(); gets(); puts() .v.v - Các hàm tự định nghĩa: Là các hàm mà trớc khi dùng chúng ta phải định nghĩa chúng. Các hàm này cũng có thể đợc tập hợp lại trong một file .h để dùng nh một th viện có sẵn. Tuỳ theo kiểu của giá trị trả về của hàm ta phân ra: - Hàm không có giá trị trả về: Là hàm chỉ có chức năng thực hiện một công việc nào đó mà ta không quan tâm tới giá trị trả về của hàm. Các giá trị tính toán đợc trong thân hàm thờng đợc kết xuất lên màn hình. - Hàm có giá trị trả về: Ngoài việc thực hiện một công việc nào đó, hàm này còn trả về một giá trị thông qua tên hàm. Giá trị này có thể đợc dùng trong những đoạn trình tiếp theo sau lời gọi hàm. Nhận xét: - Trong pascal, ta có hai loại chơng trình con: thủ tục (procedure) và hàm (function). Trong C++, chúng ta có duy nhất một loại chơng trình con (mà ta gọi là đơn thể), đó là hàm. - Một chơng trình trong C++ đợc cấu tạo từ các hàm, trong đó hàm main là hàm bắt buộc phải có, đóng vai trò nh chơng trình chính. 4. Định nghĩa và sử dụng hàm a. Cấu trúc một hàm: Một hàm thờng có cấu trúc nh sau: - Hàm không có giá trị trả về (hàm void): - Hàm có giá trị trả về: Biên soạn: Nguyễn Mạnh Cờng Trang 2 <Kiểu hàm> <Tên hàm> <([<kiểu đối> <tên đối>])> { //Các lệnh trong thân hàm; } Đề cơng chi tiết Kỹ thuật lập trình Trong đó: - <Kiểu hàm>: là kiểu giá trị trả về của hàm. Nếu hàm không có giá trị trả về, ta dùng kiểu void. Ngợc lại, ta thờng sử dụng các kiểu chuẩn nh int, float, double, char - <Tên hàm>: do ngời dùng tự định nghĩa. - [<kiểu đối> <tên đối>]: liệt kê danh sách các đối của hàm và kiểu dữ liệu của đối (nếu hàm có đối). VD1: hàm tính n! đợc viết theo 2 dạng: có và không có giá trị trả về: Nhận xét: - Hai điểm khác nhau cơ bản giữa hai loại hàm này là: Kiểu trả về (long và void) và câu lệnh cuối hàm (return kq; và cout<<kq;) - Nếu hàm có giá trị trả về thì trong thân hàm thờng dùng lệnh: return <Giá trị trả về>; Khi đó, giá trị trả về sẽ đợc gán vào tên hàm. Bên ngoài hàm ta sử dụng giá trị trả về này thông qua tên hàm. - <Giá trị trả về> có thể là hằng, biến hoặc hàm. VD2: Viết hàm tính giá trị biểu thức Biên soạn: Nguyễn Mạnh Cờng Trang 3 void <Tên hàm> <([<kiểu đối> <tên đối>])> { //Các lệnh trong thân hàm; } long GT(int n) { long kq=1; for (int i=1; i<=n; i++) kq *=i; return kq; } void GT(int n) { long kq=1; for (int i=1; i<=n; i++) kq *=i; cout<<kq; } Cách 1: Hàm có giá trị trả về Cách 2: Hàm không có giá trị trả về Đề cơng chi tiết Kỹ thuật lập trình F = + +++++ lẻ n nếu chẵn n nếu 1 2 1 2 1 2 1 2 1 1 2 32 n n Một vấn đề đặt ra là: khi nào thì viết hàm dới dạng có giá trị trả về, khi nào thì viết hàm không có giá trị trả về? Nói chung, tuỳ thuộc vào bài toán cụ thể ta có thể quyết định điều này, tuy nhiên: - Nếu ta chỉ dùng hàm để thực thi một công việc nào đó mà kết quả của nó chỉ cần đợc kết xuất ra màn hình là đủ thì hàm thờng đợc viết dới dạng không có giá trị trả về. - Nếu kết quả trả về của hàm có thể đợc dùng trong những công việc tiếp theo (tức ta còn sử dụng chúng sau này) thì hàm thờng đợc viết dới dạng có giá trị trả về. b. Cách tổ chức các hàm Cách 1: Các hàm đặt trong cùng một tệp với hàm main(). Chơng trình ngoài hàm main() còn có các hàm khác thì đợc viết theo cấu trúc sau: Dạng 1: Hàm đặt trớc hàm main() Dạng 2: Hàm đặt sau hàm main() Biên soạn: Nguyễn Mạnh Cờng Trang 4 float F(int n) { float kq; if (n%2==1) kq=sqrt(n*n+1); else { kq=1; int Mau = 1; for(int i=1; i<=n; i++) { Mau *=2; kq+=1/Mau; } return kq; } void F(int n) { float kq; if (n%2==1) kq=sqrt(n*n+1); else { kq=1; int Mau = 1; for(int i=1; i<=n; i++) { Mau *=2; kq+=1/Mau; } cout<<kq; } #include . //Các hàm đặt ở đây void main() { Thân hàm main; } #include . //Nguyên mẫu của hàm đặt ở đây void main() { Thân hàm main; } //Các hàm đặt ở đây Đề cơng chi tiết Kỹ thuật lập trình Cách 2: Các hàm đặt trong th viên: B1: Viết các hàm (trừ hàm main()) trong một file sau đó lu dới định dạng .h. File này thờng đợc gọi là file th viện. (để thuận tiện cho việc soát lỗi, tốt nhất trớc tiên nên tổ chức các hàm nh cách 1, sau đó di chuyển toàn bộ các hàm (trừ hàm main() sang một file .h và lu lại) B2: Mở một tệp mới và viết hàm main() trong một tệp này. Để hàm main() có thể sử dụng các hàm viết trong file th viện đã tạo trong B1, cần thêm chỉ thị: #include <[ đờng dẫn] <Tên th viện.h> Chú ý: nếu đặt file th viện trên trong th mục TC\ Include thì trong chỉ thị #include không cần thêm đờng dẫn. Ngợc lại, cần thêm đầy đủ đờng dẫn tới file th viện nói trên. VD: Tạo file th viện TV.h với nội dung sau: int NT(int n) { if (n ==1 || n ==2) return =1; else {Check =1; for (int i=2; i<n; i++) if (n%i==0) Check =0; return Check; } } long GT(int n) {long kq=1; if (n==0 || n==1) kq=1; else for (int i=1; i<=n; i++) kq *=i; return kq; } Mở một file (.CPP) mới và viết hàm main(): #include <conio.h> #include <stdio.h> #include <iostream.h> #include <C:\TC\BIN\ TV.h void main() { int a; cout<< Nhập a ; cin>>a; if (NT(a) == 0) cout<< Số <<a<< Không phải nguyên tố ; else { cout<< Số <<a<< là số nguyên tố ; cout<< Giai thừa của <<a<< là <<GT(a); } getch(); } Chú ý: Biên soạn: Nguyễn Mạnh Cờng Trang 5 Đề cơng chi tiết Kỹ thuật lập trình - Các file th viện .h không nhất thiết phải có các chỉ thị tiền xử lý #include - Không thể soát lỗi bằng cách bấm F9 trong file th viện .h. c. Sử dụng hàm Để nắm cách sử dụng hai loại hàm trên, ta xét cách sử dụng các biến và các lệnh trong chơng trình. Giả sử ta xét a, b là một biến và gets() là một lệnh có trong chơng trình. khi đó: Cách viết sai Cách viết đúng a; cout<<gets(b); b = a; gets(a); Tức là: - Các biến không đợc dùng một cách độc lập mà luôn đợc viết trong một lệnh nào đó hoặc trong biểu thức của lệnh gán. - Các lệnh có thể đợc dùng độc lập mà không thể dùng lệnh này bên trong lệnh kia. Ghi nhớ: - Các hàm có giá trị trả về dùng nh một biến. - Các hàm không có giá trị trả vê dùng nh một lệnh. Một số nguyên tắc khi dùng hàm: - Nếu hàm đợc định nghĩa có đối số thì khi gọi hàm ta phải truyền đầy đủ các tham số (hay đối số thực sự) cho hàm. - Các tham số phải có kiểu trùng với kiểu của đối số tơng ứng. - Nếu hàm không có đối số thì lời gọi hàm vẫn phải sử dụng dấu () kèm tên hàm: <Tên hàm> <( )>. 5. Phạm vi của biến Theo phạm vi hoạt động của biến, ta chia ra: - Biến toàn cục: là các biến có phạm vi hoạt động trong toàn bộ chơng trình, kể từ vị trí khai báo biến. Vị trí khai báo biến toàn cục nằm ngoài các hàm (kể cả hàm main). Nếu chơng trình đợc viết trên nhiều tệp, để phạm vi hoạt động của biến bao gồm cả các tệp khác, ta cần thêm chỉ danh extern vào trớc khai báo biến. - Biến cục bộ: là các biến có phạm vi hoạt động bị hạn chế: Nếu biến đợc khai báo trong thân một khối nào đó sẽ có phạm vi hoạt động chỉ trong khối, kể cả các khối con nằm bên trong khối đó. + Kết thúc khối, biến cục bộ sẽ đợc giải phóng. Biên soạn: Nguyễn Mạnh Cờng Trang 6 Đề cơng chi tiết Kỹ thuật lập trình + Muốn biến này tồn tại trong suốt thời gian chơng trình làm việc, ta cần thêm từ khóa static trớc khai báo biến để khai báo biến dới dạng biến tĩnh. VD1: Xét ví dụ sau: int x; void Ham(int a) { cout<< Biến x trong hàm <<x; //bien toan cuc if (a%2==0) { int x=5; x+= a; cout<< Biến x trong hàm << x; // bien cuc bo } } void main() { x=1; int a = 2; Ham(a); cout<< Biến x trong hàm main <<x; //bien toan cuc int x = 3; cout<< Biến x trong hàm main <<x; //bien cuc bo getch(); } Nhận xét: - Biến x dới dạng toàn cục có phạm vi hoạt động trong toàn bộ chơng trình, kể từ khi khai báo. - Nếu trong một khối có khai báo biến cục bộ trùng tên với viến toàn cục thì kể từ khi khai báo, khối đó sẽ sử dụng biến cục bộ mà không sử dụng biến toàn cục. II. Sử dụng các tham số trong lập trình đơn thể 1. Phân loại cách truyền tham số Nếu hàm có đối số (tham số hình thức), khi gọi hàm ta phải truyền các tham số tơng ứng cho hàm. Các tham số có thể là các biến hoặc các hằng giá trị. Có hai cách truyền tham số: [1]. Truyền dạng tham chiếu: Khi truyền tham số dới dạng tham chiếu, tham số là các biến và tham số sẽ đợc truy cập trực tiếp. Nh vậy, các tham số đ- ợc truyền vào một hàm thì sau khi ra khỏi hàm, giá tị của chúng có thể bị thay đổi. [2]. Truyền dạng tham trị: Khi truyền tham số dới dạng tham trị, tham số sẽ không đợc truy cập trực tiếp. Hàm sẽ cấp phát một vùng nhớ mới và sao chép giá trị của tham số vào đó. Các lệnh trong thân hàm sẽ thao tác trên vùng nhớ mới này. Nh vậy, một tham số khi truyền vào một hàm dới dạng tham trị sẽ không bị tham đổi giá trị của nó khi ra khỏi hàm. Biên soạn: Nguyễn Mạnh Cờng Trang 7 Thực thi hàm Vùng nhớ của biến Biến Gọi hàm Thực thi hàm Vùng nhớ của biến Biến Gọi hàm Vùng nhớ mới Đề cơng chi tiết Kỹ thuật lập trình a) truyền tham chiếu b) Truyền tham trị 2. Truyền tham số Nếu chơng trình viết trong các file có phần mở rộng .h, ta có duy nhất một cách truyền tham số: Truyền theo tham trị. Từ C++3.0 trở lên, cho phép sử dụng cả hai cách truyền tham số trong các chơng trình viết dới dạng các file .CPP. Xét trờng hợp ta có các biến thông thờng (không phải là biến con trỏ) - Nếu biến đợc truyền dới dạng thông thờng thì cách truyền đó là truyền theo tham trị. - Nếu ta không truyền biến vào hàm mà thay vào đó, ta truyền địa chỉ của biến vào thì đó là cách truyền tham chiếu. VD: int a=3, b=5; Ham (&a, b); Khi đó biến a đợc truyền vào hàm dới dạng tham chiếu; biến b đợc truyền vào hàm dới dạng tham trị. Xét trờng hợp ta có các biến con trỏ. Vì bản thân con trỏ thờng chứa địa chỉ của biến nào đó (mà nó trỏ tới) nên khi truyền con trỏ vào hàm thì mặc nhiên đã là truyền theo dạng tham chiếu. VD: int a, *p; a = 5; p = & a; Ham(p); Khi đó biến p đợc truyền vào hàm nhng thực chất là ta đã chuyền địa chỉ của a vào hàm. Vậy có thể coi đây là trờng hợp truyền biến a vào hàm dới dạng tham chiếu (tức sau khi ra khỏi hàm, biến a có thể bị thay đổi giá trị). VD1: Xét hàm sau: int tang(int a) { a++; } void main() { int n=1; cout<< Giá trị tr ớc khi gọi hàm <<n; tang(n); cout<< Giá trị sau khi gọi hàm <<n; getch(); } VD2: xét hàm sau int Ham(int a, int b) { Biên soạn: Nguyễn Mạnh Cờng Trang 8 Đề cơng chi tiết Kỹ thuật lập trình if (a%2==0){ a+=1; b+=a; } cout<< Giá trị a trong thân hàm <<a; cout<<Giá trị b trong thân hàm <<b; } void main() { int a, b; a=1; b=2; cout<< Giá trị a tr ớc khi gọi hàm <<a; cout<< Giá trị b tr ớc khi gọi hàm <<b; Ham(a, b); cout<< Giá trị a sau khi gọi hàm <<a; cout<< Giá trị b sau khi gọi hàm <<b; getch(); } III. Kỹ thuật đệ quy 1. Khái niệm về đệ quy Trong C++, một hàm có thể gọi đến chính nó. Tính chất này của hàm gọi là tính đệ quy. Khi một hàm gọi đến chính nó, hàm đợc viết theo kiểu đệ quy. VD: Xét hàm tính n!. Ta có định nghĩa sau: n! = n * (n-1)! . Hàm lặp: long GT(int n) { long kq=1; if (n==0 || n==1) kq=1; else for (int i=1; i<=n; i++) kq *=i; return kq; } Hàm đệ quy: long GT(int n) { if (n==1) return 1; else return GT(n-1) * n; } Thực hiện: Giả sử n =3. Khi đó, quy trình thực hiện nh sau: Biên soạn: Nguyễn Mạnh Cờng Trang 9 3! 2! 1! 3 * 2! 1! * 2 = = 1= Đề cơng chi tiết Kỹ thuật lập trình Để tính 3! ta cần tính 2!; Để tính 2 ! ta cần tính 1!. Nếu biết 1!=1 thì ta có thể từ đó tính đợc 2! và 3!. Vậy thứ tự thực hiện công việc tính toán sẽ là: 1!, 2!, 3! (tức phải gọi hàm tính n! tới 3 lần với 3 đối vào 1, 2, 3). Mỗi lần gọi đệ quy, chơng trình thực hiện nh sau: - Lu địa chỉ của dòng lệnh gọi đệ quy. - Tạo một tạo một bản sao của hàm, cấp phát các vùng nhớ mới cho các biến cục bộ, thực hiện bản sao này. - Lấy địa chỉ của dòng lệnh gọi đệ quy và quay về. Để rõ hơn ta xem sơ đồ sau: Nh vậy có bao nhiêu lời gọi hàm thì có bấy nhiêu lần kết thúc hàm. Trong trờng hợp không tồn tại một bản sao của hàm mà tại đó không thực hiện hiện lời gọi đệ quy thì quá trình đệ quy sẽ không dừng đợc (ta gọi là đệ quy vô hạn). Trong ví dụ về tính n!, với n=3 và công thức đề quy n! = n * (n-1)!, sơ đồ đệ quy có thể nh sau: Biên soạn: Nguyễn Mạnh Cờng Trang 1 0 Bắt đầu Gọi đệ quy Gọi đệ quy Gọi đệ quy Kết thúc Bản sao 1 Bản sao n Bỏ qua lệnh gọi đệ quy Bắt đầu : tính 3! Gọi đệ quy Gọi đệ quy Gọi đệ quy Kết thúc Return 1*2*3 Hàm GT(2) Hàm GT(1) Bỏ qua lệnh gọi đệ quy Return 1Return 1*2 [...]... tiết Kỹ thuật lập trình u nhợc điểm của phơng pháp đệ quy: - Chơng trình ngắn gọi, dễ hiểu - Quá trình dịch phức tạp - Nói chung, tốn nhiều không gian nhớ hơn lặp Phơng pháp đệ quy đặc biệt thích hợp với một số bài toán nh duyệt cây, đồ thị Tuy nhiên, nói chung ta nên ít sử dụng đệ quy khi viết chơng trình do các nhợc điểm trên 2 Thiết kế chơng trình theo kiểu đệ quy Các bài toán áp dụng giải thuật. .. a = b; b = Sodu; } return a; } Biên soạn: Nguyễn Mạnh Cờng Trang 1 3 Đề cơng chi tiết Kỹ thuật lập trình Hàm đệ quy: Bớc 1: - Suy biến : b=0; công thức suy biến: USCLN(a, b) = b; - Không suy biến: b khác 0; công thức tổng quát: USCLN (a, USCLN(b, a%b); Bớc 2: b) = if (b==0) return a; else return USCLN(b, a%b) Lập trình: Int USCLN_DQ(int a, int b) { if (b==0) return a; else return USCLN_DQ(b, a%b);... biến: n >1; công thức tổng quát: Fibo(n) = Fibo(n-1) + Fibo(n-2) Bớc 2: if(n 1 Khi đó: n! = n* (n-1)! Chơng trình đệ quy đợc thiết kế nh sau: Bớc 1: Xác định các trờng hợp suy biến tổng... biến : n=0 hoặc n = 1; Công thức n! = 1; - Tổng quát: n khác 0 và n khác 1; Công thức n! = n* (n-1)! Bớc 2: if (n= = 0 || n= = 1) return 1; else return n * GT(n-1); Sau khi thiết kế, việc lập hàm đệ quy trở lên rất đơn giản VD2 Dãy số Catalan đợc phát biểu đệ quy nh sau: C1 = 1; Cn = n 1 C C i =1 i n i Hãy xây dựng hàm đệ quy tìm số CataLan thứ n Hàm đệ quy đợc thiết kế nh sau: Bớc 1: - Suy biến: n . Chơng III. Kỹ thuật lập trình đơn thể I. Định nghĩa và sử dụng đơn thể 1. Khái niệm phân loại Khái niệm: Đơn thể (hay Module) là một đoạn chơng trình đợc. dữ liệu nào đó; ta gọi là kiểu giá trị trả về của hàm. Kiểu giá trị trả về của hàm có thể là các kiểu dữ liệu chuẩn. Đề cơng chi tiết Kỹ thuật lập trình [3].

Ngày đăng: 16/01/2014, 11:37

Từ khóa liên quan

Mục lục

  • I. Định nghĩa và sử dụng đơn thể

    • 5. Phạm vi của biến

    • II. Sử dụng các tham số trong lập trình đơn thể

    • III. Kỹ thuật đệ quy

Tài liệu cùng người dùng

  • Đang cập nhật ...

Tài liệu liên quan