chuong trinh con

9 6 0
chuong trinh con

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

Thông tin tài liệu

ViÖc cÊp ph¸t bé nhí cho ch¬ng tr×nh con (biÕn ®Þa ph¬ng) ®îc thùc hiÖn trong vïng bé nhí Stack, trong khi viÖc cÊp ph¸t cho c¸c biÕn trong ch¬ng tr×nh chÝnh (biÕn toµn côc) ®îc thùc hiÖ[r]

(1)

chơng trình con

1 Ch ơng trình vai trò ch ơng trình con

Chơng trình dãy lệnh đợc xây dựng cho máy tính thực cơng việc Cơng việc gồm nhiều cơng việc nhỏ đến lợt chúng lại đợc tổ chức thành chơng trình Lời gọi chơng trình đợc xuất lệnh chơng trình ban đầu Chúng đợc gọi chơng trình

Nh vậy, chơng trình chơng trình, mà đợc gọi lịng chơng trình khác Trong chơng trình có chơng trình khác Vì vậy, khái niện chơng trình mang tính chất tơng đối: chơng trình chơng trình chơng trình khác Ngời ta thờng dùng thuật ngữ chơng trình để chơng trình mức ngoi cựng

Vai trò chơng trình con:

 Cho phép phân rã toán phức tạp thành nhiều tốn đơn giản hơn, từ cho phép kiểm sốt tồn chơng trình, dễ dàng sửa chữa phát triển

 Nâng cao tính độc lập thiết kế, che dấu nội Cho phép xây dựng chơng trình lớn, có nhiều ngời tham gia

 Là phơng thức thực kỹ thuật lập trình Top-Down (từ tổng thể đến chi tiết), thích hợp với hầu hết thiết kế lập trình cấu trúc

 Cho phép xây dựng th viện lập trình, kế thừa kết trớc đấy, giảm chi phí cơng sức việc viết chơng trình

2 Cách tổ chức ch ơng trình con

Turbo Pascal cung cấp sẵn cho ngời dùng chơng trình có sẵn, đợc biên dịch đợc gọi chơng trình chuẩn đợc liên kết với chơng trình ngời sử dụng Các chơng trình đợc phân loại chứa đơn vị chơng trình (unit) nh: crt, dos, graph, Bên cạnh chơng trình chuẩn, Turbo Pascal cho phép tự tổ chức chơng trình cho riêng mình, ngời dùng phi khai bỏo

Cách tổ chức chơng trình con:

Ngay lòng chơng trình

Ta dịch độc lập liên kết với chơng trình, coi nh chơng trình chuẩn (unit) Trong Pascal có loại chơng trình con: procedure (thủ tục) function (hàm)

3 Thđ tơc (procedure)

Thủ tục chơng trình nhằm thực công việc Cũng giống nh chơng trình độc lập, thủ tục gồm phần: phần đầu (tiêu đề), phần khai báo phần thân:

procedure tên_thủ_tục(các lệnh khai báo tham số); { phần đầu } { khai báo const,type,var riêng procedure,nếu cần }

begin

{ phần thân }

end;

Trong đó:

 tên_thủ_tục: tên ngời dùng tự đặt, theo qui tắc giống tên biến (nên đặt gợi nhớ)

Nếu thủ tục có chứa tham số sau phần tên dãy lệnh khai báo tham số đợc viết giới hạn cặp ngoặc đơn

 Khai b¸o tham sè:

tªn_tham_sè_1: kiĨu_tham_sè; tªn_tham_sè_2: kiĨu_tham_sè;

Các tham số gọi tham số hình thức (cha có nội dung) Kiểu tham số tất kiểu mà ta biết: kiểu chuẩn kiểu định danh trớc Nếu có tham số có kiểu khai báo chung:

(2)

 Phần khai báo thủ tục (nh khai báo chơng trình): đối tợng khơng phải chuẩn, tức biến, hằng, dùng chơng trình phải khai báo

Cách gọi thủ tục giống nh lời gọi thủ tục chuẩn Khi truyền tham số phải tơng ứng 1-1, kiểu, thứ tự tham số truyền vào phải cách du phy

Ví dụ Chơng trình sau in đoạn thơ truyện Kiều h×nh.

program vd1; uses crt;

procedure center(s : string); { in xâu s vào hình }

begin

writeln(' ' : (80-length(s)) div 2, s); end;

begin clrscr;

center('Tram nam coi nguoi ta');

center('Chu tai chu menh kheo la ghet nhau'); center('Trai qua mot cuoc be dau');

center('Nhung dieu thay ma dau don long'); readln;

end

4 Hµm (function)

Hàm chơng trình nhằm tính tốn trả lại giá trị Cũng giống nh thủ tục, hàm gồm phần: phần đầu (tiêu đề), phần khai báo phn thõn:

function tên_hàm(các lệnh khai báo tham số): kiểu_hàm; { khai báo const,type,var riêng function, cần }

begin

{ thân hàm }

tên_hàm := <biểu_thức>; end;

Trong đó:

 tên_hàm: ngời dùng tự đặt, theo qui tắc giống tên biến (nên đặt gợi nhớ) Nếu hàm có

chứa tham số sau phần tên dãy lệnh khai báo tham số đợc viết giới hạn cặp ngoặc đơn

 kiểu_hàm: kiểu đơn giản chuẩn (integer, real, char, boolean) kiểu phc hp:

string, pointer

Phần khai báo hàm: giống phần khai báo thủ tục

 Thân hàm: nằm khối begin end; đảm bảo trớc khỏi hàm phải có câu lệnh gán giá trị cho tên hàm: tên_hàm := <biu_thc>; Kiu giỏ tr gỏn cho tờn

hàm phải kiểu với kiểu hàm Lời gọi hàm phải tham gia vµo biĨu thøc

Ví dụ Chơng trình sau đọc số nguyên dơng từ bàn phím đa hình ớc chung lớn chúng Chơng trình có thiết kế hàm:

function ucln(a, b : integer) : integer;

để tính ớc chung lớn số nguyên dơng a, b theo thuật tốn Ơ-cơlít

program vd2; uses crt; var

a, b : integer;

function ucln(a, b : integer) : integer; var

(3)

begin

r := a mod b; while r <> begin

a := b; b := r; r := a mod b; end;

ucln := b; end;

begin clrscr;

write('a, b = '); readln(a, b);

writeln('ucln(', a, ',', b, ')=', ucln(a, b)); readln;

end

5 Địa ph ơng toàn cục

Cu trỳc Pascal chơng trình chứa chơng trình gọi khối ngồi, cịn chơng trình gọi khối Đối với khối có đối tợng (biến, hằng, kiểu liệu, ) riêng loại Vì vậy:

 Những đối tợng khai báo ngồi dùng cho tất khối khai báo bên (ví dụ nh việc lấy thơng tin, cập nhật thơng tin, ) Những đối tợng gọi toàn cục

 Những đối tợng khai báo khối có tác dụng khối đó, cịn ngồi khơng tác dụng Đó đối tợng địa phơng

Hai khái niệm địa phơng tồn cục mang tính chất tơng đối Nó tồn cục khối này, nhng lại địa phơng khối khác

Vì Pascal có tính chất địa phơng nên chơng trình có tính độc lập (khơng phải ngơn ngữ có tính địa phơng tồn cục nh Pascal) Các biến chơng trình khác mang tính chất khác

Giả sử khối khối có tên biến (tồn cục = địa phơng) khối địa phơng ln dùng biến địa phơng mà khơng dùng biến ngồi (biến địa phơng đợc u tiên) Cịn khỏi khối biến địa phơng tác dụng, nhờng chỗ cho biến Một khối muốn dùng biến ngồi khai báo biến bên khối không đợc trùng tên với biến

Nh đối tợng (hằng, biến, kiểu, ) khai báo chơng trình dùng đợc nơi chơng trình Các đối tợng khai báo chơng trình có tác dụng phạm vi chơng trình Khi kết thúc chơng trình biến hết tác dụng

Cách dùng biến địa phơng toàn cục:

 Những đối tợng mang tính chất dùng chung cho khối khai báo biến tồn cục (khai báo khối ngồi) Chẳng hạn, với chơng trình cộng ma trận: C = A + B in ma trận C, bao gồm khối:

+ NhËp A, B + Céng C = A + B + In C

th× ma trËn A, B, C vµ n (kÝch thíc ma trËn) lµ biÕn toµn cơc

 Những đối tợng phát sinh trình thao tác khối (chẳng hạn: biến trung gian, biến đếm, biến điều khiển vịng for, ) có ý nghĩa chơng trình khai báo biến địa phơng

Ví dụ Chơng trình sau cho thấy phạm vi tầm tác dụng biến địa phơng, toàn cục.

program vd3; uses crt; var

(4)

procedure dia_phuong; var

i : integer; { biến i địa phơng }

begin

i := 5; j := 7;

writeln('i=', i, ', j=', j); end;

begin clrscr;

i := 2; j := 3;

writeln('i=', i, ', j=', j); dia_phuong;

writeln('i=', i, ', j=', j); readln;

end

Chơng trình chạy cho kết sau:

i=2, j=3 i=5, j=7 i=2, j=7

6 C¸c c¸ch trun tham sè a Truyền theo trị (giá trị)

Vic truyn tham số theo trị truyền (tạo tham số truyền vào, chuyển cho chơng trình con), thao tác chơng trình thao tác Ví dụ, thủ tục procedure center(s : string); việc truyền liệu cho tham số hình thức s truyền theo trị Và hàm function ucln(a, b : integer) : integer; tham số hình thức a, b đợc truyền theo trị

Việc truyền theo trị có đặc điểm sau:

 Nếu chơng trình có lệnh làm thay đổi tham số hình thức đầu vào thay đổi khơng ảnh hởng đến giá trị biến đợc truyền vào, việc tác động lên

 Việc truyền theo tham trị gây tốn nhớ, nh thời gian chép để tạo cho tham số truyền vào Việc tốn tuỳ theo kích th ớc kiểu tham số

 Do viÖc chÐp nên tham số đầu vào phong phú, là: h»ng, biÕn, biĨu thøc VÝ dơ:

ucln(9, 12), ucln(a, b), ucln(a+3, b),

b Truyền theo biến (địa chỉ)

Truyền theo biến truyền địa đối tợng đầu vào Vì thao tác chơng trình thao tác đối tợng đầu vào

Để biết đợc chơng trình truyền theo biến hay theo trị nằm phần khai báo tham số chơng trình con:

 Cách khai báo theo tham trị:

tên_tham_số : kiểu_tham_số; Cách khai báo theo tham biến:

var tên_tham_số : kiĨu_tham_sè;

Việc truyền theo biến có đặc điểm sau:

 Nếu chơng trình có lệnh làm thay đổi tham số hình thức thay đổi thay đổi biến đợc truyền vào

 Kh«ng tèn nhớ thời gian chép

Chỉ có phơng thức truyền theo biến: đầu vào có biến, biểu thức

(5)

Tuỳ theo mục đích cơng việc mà việc khai báo phải phù hợp theo nguyên tắc sau:

 Nếu chơng trình mà khơng có lệnh làm thay đổi tham số hình thức việc truyền theo biến hay theo trị cho kết

 Nếu chơng trình có lệnh làm thay đổi tham số hình thức cần vào chức năng:

- Cần thay đổi đầu vào: bắt buộc truyền theo biến Ví dụ, thủ tục hoán chuyển giá trị hai biến procedure doi_cho(var a, b : integer);

- Ngợc lại có chơng trình cấm khơng đợc thay đổi đầu vào phải truyền theo trị

 Việc không thay đổi hay thay đổi đầu vào mà không ảnh hởng đến kết việc truyền theo trị hay theo biến tuỳ ý Nhng tròng hợp nên:

- Tham số hình thức kích thớc bé (dữ liệu chuẩn): truyền theo trị

- Tham số hình thức kÝch thíc lín (m¶ng, b¶n ghi, ): trun theo biÕn Ví dụ Cho biết kết thực chơng tr×nh sau:

program vd4; uses crt; var

a, b : integer;

procedure doi_cho(a, b : integer); var

t : integer; begin

t := x; x := y; y := t; end;

begin clrscr;

a := 5; b := 7; doi_cho(a, b);

writeln('a=',a,', b=',b); readln;

end

Giải

- Chơng trình sau chạy in hình:

a=5, b=7

Vỡ cỏc tham số chơng trình truyền theo trị, đổi giá trị hai

- Để đổi giá trị hai biến a, b cần sửa chơng trình nh sau:

procedure doi_cho(var a, b : integer);

VÝ dô Chơng trình phân số tối giản:

- Đầu vào nhập tử số, mẫu số số nguyên dơng

- Đầu in dạng tối giản phân số Giải

program vd5; uses crt; var

tu, mau, d : integer;

function ucln(var a, b : integer) : integer; var

r : integer; begin

r := a mod b; while r <> begin

(6)

ucln := b; end;

begin clrscr;

write('Tu so = '); readln(tu); write('Mau so = '); readln(mau); d := ucln(tu, mau);

writeln('Phan so toi gian la: ', tu div d, '/', mau div d); readln;

end

- Khi chạy chơng trình cho kết khơng (ví dụ, tử số 8, mẫu số 12 chơng trình cho kết 2/1) khai báo tham số hình thức chơng trình khai báo tham biến Sau thực chơng trình xong chơng trình giá trị tử số mẫu số thay đổi

- Để chơng trình chạy đúng, ta bỏ từ khoá var khai báo tham số chơng trình con:

function ucln(a, b : integer) : integer;

Ví dụ Chơng trình sau gồm chơng trình tính giá trị hàm F(x) = x + Sau đ-a kết (F(đ-a))2 hình.

Gi¶i

program vd6; uses crt; var

a : integer;

function f(var x : integer) : integer; begin

x := x + 1; f := x; end; begin clrscr; a := 5;

writeln(f(a)*f(a)); readln;

end

- Khi chạy chơng trình kết quả: 42 (= 6.7) Vì tham số đầu vào chơng trình truyền theo biến chơng trình có câu lệnh làm thay đổi giá trị tham số Do thực gọi chơng trình F(a) = lần thứ lúc biến a = 6, quay lại lần thứ hai: F(a) = Do kết 42

- Để đạt đợc kết quả: 36 (= 6.6) cần bỏ từ khoá var phần khai báo tham số, lệnh chơng trình khơng làm thay đổi giá trị a

7 Cấp phát nhớ cho ch ơng trình con

Việc cấp phát nhớ cho chơng trình (biến địa phơng) đợc thực vùng nhớ Stack, việc cấp phát cho biến chơng trình (biến tồn cục) đợc thực vùng nhớ data Trong trình chạy chơng trình, gọi chơng trình con, biến đợc cấp phát chơng trình kết thúc, biến đợc tự động giải phóng Nh vùng cấp phát cho chơng trình đợc gọi mức đợc giải phóng Nhờ vậy, biến chơng trình độc lập với biến ch-ơng trình biến chch-ơng trình độc lập với biến chch-ơng trình khác, chúng trùng tên

(7)

{$M stackSize, HeapMin, HeapMax}

trong chơng trình để tăng giá trị stackSize vào chức Option/Memory size môi trờng Turbo Pascal đặt lại giá trị cho kích thớc stack

8 Ch ơng trình đệ quy

Chơng trình đệ qui chơng trình mà lịng lại gọi Khái niệm đệ qui xây dựng lại dùng Thơng thờng để xây dựng khái niệm phải dùng khái niệm cũ, đệ qui phải có điểm dừng Khái niệm đệ quy giống với khái niệm quy nạp tốn học, ví dụ nh hàm n giai thừa:

  

 

 

0 )!1

(

0 1

!

n n

nÕu

nÕu

n n n

Đối với chơng trình đệ qui chơng trình dịch làm việc vất vả Nếu chơng trình đệ qui khơng có điểm dừng điểm dừng q sâu thờng dẫn đến lỗi tràn stack (stack overflow error)

Ví dụ Thiết kế hàm giai thừa. Giải

 Dùng hàm có tính đệ qui:

function gt(n : integer) : integer; begin

if n = then gt :=

else gt := n * gt(n-1); end;

 Thiết kế hàm giai thừa mà không đệ qui:

function gt(n : integer) : integer; var

i, t : integer; begin

t := 1;

for i := to n t := t * i; gt := t;

end;

Về mặt logíc, hai hàm cho kết nh nhau, nhng mặt hệ thống, chúng hoàn toàn đợc thực khác Khi tính n! , hàm thứ đợc gọi số lần tỉ lệ với n, hàm thứ hai gọi lần không phụ thuộc vào n Trớc nói u điểm, nhợc điểm chơng trình đệ quy, ta xét tiếp ví dụ sau

Ví dụ Thiết kế hàm tính số hạng thø n cña d·y Fibonaci: F1 = F2 = 1

Fn = Fn - + Fn - 1 víi n > Gi¶i

 Xây dựng hàm F đệ qui để tính:

function f(n : integer) : integer; begin

if n < then f :=

else f := f(n-2) + f(n-1); end;

Giả sử để tính F(5), lời gọi F(5) kéo theo lời gọi sau:

7 F(5)

F(3) F(4)

F(2) F(1) F(3) + F(2)

(8)

Trong sơ đồ trên, số phép cộng 4, F(3) đợc tính lại lần, F(2) đợc tính lại lần Các số đợc lũy tiến theo n Vùng nhớ stack đợc cấp phát tỷ lệ với giá trị n

 Thiết kế hàm Fibonaci không đệ qui: cần dùng biến (2 biến luân chuyển)

function f(n : integer) : integer; var

x, y, z, i : integer; begin

x := 1; y := 1; for i := to n begin

z := x + y; x := y; y := z; end; f := y; end;

Về mặt hình thức, hàm viết phức tạp cách trớc, nhiên mặt tính tốn sử dụng nhớ, hiệu nhiều Các giá trị đợc tính lần, số phép cộng phải thực n-2 (tuyến tính theo n), nhớ cấp phát khơng tăng theo n Dới vài giá trị để bạn so sánh:

n 31 32 33 34 35

Số phép + (không đệ quy) 29 30 31 32 33

Số phép + (đệ quy) 1.346.268 2.178.308 3.524.577 5.702.886 9.227.464 Nh vậy, điểm lợi hiển nhiên dùng đệ quy tiết kiệm công sức cho ngời lập trình Hàm gt, f cách cài đặt đệ quy chép lại công thức quy nạp Một toán phát biểu quy nạp toán học dễ dàng đợc cài đặt đệ quy Tuy nhiên việc dùng đệ quy th-ờng trả giá cho tốn nhớ số phép toán cần thực

Trong kỹ thuật lập trình nay, có lĩnh vực chuyên nghiên cứu việc khử đệ quy nhằm cao tính hiệu chơng trình Nói chung, bạn khơng nên lạm dụng đệ quy tình nh ví dụ vừa nêu

Mặc dù vậy, đệ quy khơng phải khơng có ích Những tốn có tính quy nạp, tiết kiệm cơng sức lập trình nhiều Nhiều tình huống, khơng dùng đệ quy việc cài đặt trở nên phức tạp Một ví dụ điển hình tốn Tháp Hà Nội

Ví dụ (bài tốn Tháp Hà Nội) Có cọc đợc đánh số 1, 2, Trên cọc đặt vị trí a có n đĩa kích thớc từ nhỏ đến lớn đợc xếp cho đĩa nhỏ nằm đĩa lớn Cần phải chuyển n đĩa từ cọc đặt vị trí a sang cọc đặt vị trí b theo nguyên tắc:

 Mỗi bớc di chuyển đĩa;

 Trong q trình di chuyển khơng đợc để đĩa lớn đĩa bé;

 ViÖc di chun cho phÐp dïng mét vÞ trÝ thø gäi vị trí trung gian Chẳng hạn, với n = 3, a = 1, b = ta cã bíc chun nh sau:

1)  (Chuyển đĩa nhỏ từ vị trí ban đầu sang vị trí tập kết) 2) 

3)  4)  5)  6)  7)  Gi¶i

Để xây dựng cách chuyển đĩa, ta dùng phơng pháp qui nạp:

 Với n = đĩa  xong;

(9)

(i) Chuyển n-1 đĩa từ vị trí ban đầu đến vị trí trung gian (ii) Chuyển đĩa lớn từ vị trí ban đầu đến vị trí tập kết (iii) Chuyển n-1 đĩa từ vị trí trung gian sang vị trí tập kết

Ta chứng minh quy nạp đợc rằng: số bớc để chuyển n đĩa từ vị trí ban đầu đến vị trí tập kết là: 2n - (*).

ThËt vËy:

 Với n = đĩa số bớc chuyển là: 21 - = bớc  (*) với n = 1;

 Giả sử để chuyển n-1 đĩa ta phải là: (2n - 1 - 1) bớc Khi theo cách giải bài tốn tháp Hà Nội số bớc chuyển n đĩa tổng số bớc chuyển (i), (ii), (iii) bằng:

(2n - 1 - 1) + + (2n - 1 - 1) = 2n - 1 Cài đặt:

program thap_ha_noi; uses crt;

var

n, a, b : integer;

procedure chuyen_dia(n, a, b : integer);

{ Chuyển n đĩa từ a sang b Cọc trung gian 6-a-b }

begin

if n = then writeln(a,' >',b) else begin

chuyen_dia(n-1, a, 6-a-b); chuyen_dia(1, a, b);

chuyen_dia(n-1, 6-a-b, b); end;

end; begin clrscr;

write('n = '); readln(n);

write(‘a, b = ’); readln(a, b); chuyen_dia(n, a, b);

Ngày đăng: 03/05/2021, 01:11

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

Tài liệu liên quan