Nội Dung Chính
Các ngôn ngữ lập trình đều có các quy tắc viết và sử dụng chương trình con. Trong mục này, ta xét cách viết và sử dụng chương trình con trong Pascal.
1. Cách viết và sử dụng thủ tục
Xét ví dụ vẽ hình chữ nhật có dạng sau:
Ta có thể vẽ hình chữ nhật trên với ba câu lệnh:
writeln('* * * * * *');
writeln('* *');
writeln('* * * * * *');
Như vậy, trong một chương trình, mỗi khi cần vẽ một hình chữ nhật như trên, ta cần phải đưa vào ba câu lệnh này.
Trong chương trình sau, ta đưa ba câu lệnh trên vào một thủ tục có tên là Ve_Hơn (vẽ hình chữ nhật). Mỗi khi cần vẽ một hình chữ nhật ta đưa vào một câu lệnh gọi thủ tục đó. Chương trình VD_thutucl gọi thủ tục Ve_Hơn ba lần để vẽ ba hình chữ nhật.
program VD_thutucl;
procedure Ve_Hcn; { Bắt đầu thủ tục }
begin
writeln('*******');
writeln('* *');
writeln('*******');
end; { Kết thúc thủ tục }
begin
Ve_Hcn; { Gọi thủ tục Ve_Hcn }
writeln;
writeln;
Ve_Hcn;
writeln;
writeln;
Ve_Hcn;
end.
a) Cấu trúc của thủ tục
Thủ tục có cấu trúc như sau:
procedure <tên thủ tục>[(<danh sách tham số>)];
[<phần khai báo>]
begin
[<dãy các lệnh>]1
end;
Phần đầu thủ tục gồm tên dành riêng procedure, tiếp theo là tên thủ tục. Danh sách tham số có thể có hoặc không có.
Phần khai báo dùng để xác định các hằng, kiểu, biến và cũng có thể xác định các chương trình con khác được sử dụng trong thủ tục. Thủ tục Ve_Hơn ở trên không khai báo hằng, biến hay chương trình con nào.
Dãy câu lệnh được viết giữa cặp tên dành riêng begin và end tạo thành thân của thủ tục.
Chú ý:
- Sau tên dành riêng and kết thúc chương trình chính là dấu chấm (.) còn sau and kết thúc thủ tục là dấu chấm phẩy (;).
- Các thủ tục, nếu có, phải được khai báo và mô tả trong phần khai báo của chương trình chính, ngay sau phần khai báo các biến.
- Khi cần thực hiện, ta phải viết lệnh gọi thủ tục tương tự như các thủ tục chuẩn.
b) Ví dụ về thủ tục
Thủ tục Ve Hơn trong ví dụ trên chỉ vẽ được hình chữ nhật với kích thước cố định là 7×3. Giả sử chương trình cần vẽ nhiều hình chữ nhật với kích thước khác nhau. Để thủ tục Ve Hơn có thể thực hiện được điều đó, cần có hai tham số cho dữ liệu vào là chiều dài và chiều rộng. Khi đó phần đầu của thủ tục được viết như sau:
procedure Ve Hcn (chdai, chrong:integer);
Khai báo này có nghĩa thủ tục Ve_Han sẽ được thực hiện để vẽ hình chữ nhật có kích thước tuỳ theo giá trị của các tham số chdai, chrong và giá trị của các tham số chdai và chrong là nguyên (integer).
Chương trình sau đây mô tả đầy đủ thủ tục Ve Hơn với các tham số chdai, chrong và sử dụng thủ tục này để vẽ các hình chữ nhật có kích thước khác nhau.
program VD_thutuc;
uses crt;
var
a, b, i: integer;
procedure VeHcn(chdai, chrong: integer);
var
i: integer;
begin
{ ve canh tren cua hinh chu nhat }
for i := 1 to chdai do
write('*');
writeln;
{ ve 2 canh ben }
for i := 1 to chrong - 2 do
begin
write('*');
for a := 1 to chdai - 2 do
write(' ');
writeln('*');
end;
{ ve canh duoi }
for i := 1 to chdai do
write('*');
writeln;
end;
begin { bat dau chuong trinh chinh }
clrscr;
{ ve hinh chu nhat kich thuoc 25x10 }
VeHcn(25, 10);
writeln;
writeln; { de cach 2 dong }
{ ve hinh chu nhat kich thuoc 5x10 }
VeHcn(5, 10);
readln;
clrscr;
{ ve 4 hinh chu nhat: hinh dau tien co kich thuoc 4x2, moi hinh sau co kich thuoc gap doi hinh truoc }
a := 4;
b := 2;
for i := 1 to 4 do
begin
VeHcn(a, b);
a := a * 2;
b := b * 2;
writeln;
end;
readln;
end.
Trong lệnh gọi thủ tục, các tham số hình thức được thay bằng các tham số thực sự tương ứng là các giá trị cụ thể được gọi là các tham số giá trị (gọi tắt là tham trị).
Các tham số chdai, chrong của thủ tục Ve_Hơn là tham trị. Trong lệnh gọi thủ tục Ve_Hcn(5, 3) (vẽ hình chữ nhật kích thước 5×3) tham số chdai được thay bởi số nguyên 5, tham số chrong được thay bởi số nguyên 3.
Còn trong lời gọi thủ tục Ve Hcn(a, b) vẽ hình chữ nhật kích thước axb, tham số chdai được thay bởi giá trị hiện thời của biến a, tham số chrong được thay bởi giá trị hiện thời của biến b.
Trong lệnh gọi thủ tục, các tham số hình thức được thay bằng các tham số thực sự tương ứng là tên các biến chứa dữ liệu ra được gọi là các tham số biến (gọi tắt là tham biến).
Để phân biệt tham biến và tham trị, Pascal sử dụng từ khoá var để khai báo những tham số biến.
Ví dụ, thủ tục Hoan_doi trong chương trình sau đổi giá trị của hai biến. Vì cả hai biến đều chứa dữ liệu ra nên cần sử dụng từ khoá var để khai báo cho cả
hai biến.
program VD_thambienl;
uses crt;
var
a, b: integer;
procedure Hoan_doi(var x, y: integer);
var
TG: integer;
begin
TG := x;
x := y;
y := TG;
end;
begin
clrscr;
{ Khởi tạo giá trị }
a := 5;
b := 10;
{ Hiển thị giá trị trước khi hoán đổi }
writeln('Trước khi hoán đổi:');
writeln('a: ', a: 6, ' b: ', b: 6);
{ Hoán đổi giá trị }
Hoan_doi(a, b);
{ Hiển thị giá trị sau khi hoán đổi }
writeln('Sau khi hoán đổi:');
writeln('a: ', a: 6, ' b: ', b: 6);
readln;
end.
Khai báo sau xác định .x và y là hai tham biến kiểu nguyên
var x, y: integer;
Trong lệnh gọi Hoan_doi(a,b) các tham biến x và y được thay thế bởi các biến nguyên tương ứng a và b.
Giá trị của các biến này bị thay đổi khi thực hiện các lệnh:
TG: -a; a:b; b:=TG;
Do vậy, sau khi thực hiện thủ tục Hoan_doi, biến a sẽ nhận giá trị của biến h và biến b nhận giá trị của biến a. Nếu giá trị của a là 5 còn giá trị của b là 10 thì trên màn hình có hai dòng:
5 10
10 5
Chương trình sau cho thấy sự khác nhau khi chương trình con dùng tham số giá trị và tham số biến (có và không khai báo với từ khoá var):
program VD_thambien2;
uses crt;
var
a, b: integer;
procedure Hoan_doi(x: integer; var y: integer);
var
TG: integer;
begin
TG := x;
x := y;
y := TG;
end;
begin
clrscr;
a := 5;
b := 10;
writeln(a:6, b:6);
Hoan_doi(a, b);
writeln(a:6, b:6);
readln;
end.
Khi chương trình thực hiện, sẽ nhận được kết quả:
5 10
5 5
2. Cách viết và sử dụng hàm
Điểm khác nhau cơ bản giữa thủ tục và hàm là việc thực hiện hàm luôn trả về giá trị kết quả thuộc kiểu xác định và giá trị đó được gán cho tên hàm.
Hàm có cấu trúc tương tự như thủ tục, tuy nhiên có khác nhau phần đầu. Khai báo phần đầu một hàm như sau:
function <tên hàm> [ (<danh sách tham số>)]: <kiểu dữ liệu);
trong đó, kiểu dữ liệu là kiểu dữ liệu của giá trị mà hàm trả về và chỉ có thể là các kiểu integer, real, char, boolean, string.
Cũng giống như thủ tục, nếu hàm không có tham số hình thức thì không cần danh sách tham số.
Khác với thủ tục, trong thân hàm cần có lệnh gán giá trị cho tên hàm:
<tên hàm>:= <biểu thức>;
Ví dụ 1
Xét chương trình thực hiện việc rút gọn một phân số, trong đó có sử dụng hàm tính ước chung lớn nhất (ƯCLN) của hai số nguyên.
program Rutgon_Phanso;
uses crt;
var
TuSo, MauSo, a: integer;
function UCLN(x, y: integer): integer;
var
sodu: integer;
begin
while y <> 0 do
begin
sodu := x mod y;
x := y;
y := sodu;
end;
UCLN := x;
end;
begin
clrscr;
write('Nhap tu so, mau so vao: ');
readln(TuSo, MauSo);
a := UCLN(TuSo, MauSo);
if a > 1 then
begin
TuSo := TuSo div a;
MauSo := MauSo div a;
end;
writeln(TuSo:5, MauSo:5);
readln;
end.
Ghi chú: Trong chương trình này, các biến TuSo, MauSo và a là các biến toàn cục, còn biến sodu là biến cục bộ.
Sử dụng hàm
Việc sử dụng hàm hoàn toàn tương tự với việc sử dụng các hàm chuẩn, khi viết lệnh gọi gồm tên hàm và tham số thực sự tương ứng với các tham số hình thức.
Lệnh gọi hàm có thể tham gia vào biểu thức như một toán hạng và thậm chí là tham số của lời gọi hàm, thủ tục khác, ví dụ:
A: 6*Ucln (TuSo, MauSo) +1;
Ví dụ 2
Chương trình sau cho biết giá trị nhỏ nhất trong ba số nhập từ bàn phím, trong đó có sử dụng hàm tìm số nhỏ nhất trong hai số.
program Minbaso;
var
a, b, c: real;
{ Hàm tìm số nhỏ nhất trong hai số a và b }
function Min(x, y: real): real;
begin
if x < y then
Min := x
else
Min := y;
end;
begin
write('Nhap vao ba so: ');
readln(a, b, c);
writeln('So nho nhat trong ba so la: ', Min(Min(a, b), c):0:2);
readln;
end.
Bài tập và thực hành 6
1. Mục đích, yêu cầu
Rèn luyện các thao tác xử lí xâu, kĩ năng tạo hiệu ứng chữ chạy trên màn hình;
Nâng cao kĩ năng viết, sử dụng chương trình con.
2. Nội dung
a) Trước hết, hãy tìm hiểu việc xây dựng hai thủ tục sau đây:
- Thủ tục CatDan(s1, s2) nhận đầu vào là xâu s1 gồm không quá 79 kí tự, tạo xâu s2 thu được từ xâu sẽ bằng việc chuyển kí tự đầu tiên của nó xuống vị trí cuối cùng. Ví dụ nếu s1 = 'abcd thì s2='beda.
type
str79 = string[79];
procedure CatDan(s1: str79; var s2: str79);
begin
s2 := copy(s1, 2, length(s1) - 1) + s1[1];
end;
- Thủ tục CanGiua(s) nhận đầu vào là xâu s gồm không quá 79 kí tự, bổ sung vào đầu s một số dấu cách để khi đưa ra màn hình xâu kí tự s ban đầu được căn giữa dòng (80 kí tự).
procedure CanGiua(var s: str79);
var
i, n: integer;
begin
n := (80 - length(s)) div 2;
for i := 1 to n do
s := ' ' + s;
end;
b) Theo dõi cách sử dụng hai thủ tục trên, ta có thể viết chương trình sau đây để nhập một xâu kí tự từ bàn phím và đưa xâu đó ra màn hình có dạng dòng chữ chạy giữa màn hình văn bản 25×80.
uses crt;
type
str79 = string[79];
var
s1, s2: str79;
stop: boolean;
procedure CatDan(s1: str79; var s2: str79);
begin
s2 := copy(s1, 2, length(s1) - 1) + s1[1];
end;
procedure CanGiua(var s: str79);
var
i, n: integer;
begin
n := (80 - length(s)) div 2;
for i := 1 to n do
s := ' ' + s;
end;
begin
clrscr;
write('Nhap xau s1: ');
readln(s1);
CanGiua(s1);
clrscr;
stop := false;
while not stop do
begin
gotoxy(1, 12); (* Chuyen con tro den dau dong 12 *)
write(s1);
delay(500); (* Dung 500 miligiay *)
CatDan(s1, s2);
s1 := s2;
stop := keypressed; (* Nhan mot phim bat ki de ket thuc *)
end;
readln;
end.
Hãy chạy thử chương trình trên với dòng chữ
'... Mung nghin nam Thang Long - Ha Noi!... '
c) Hãy viết thủ tục ChuChay(s, dong) nhận đầu vào là xấu s gồm không quá 79 kí tự và biến nguyên dong, đưa ra xấu s có dạng chữ chạy ở dòng dong. Viết và chạy chương trình có sử dụng thủ tục này.
Bài tập và thực hành 7
1. Mục đích, yêu cầu
- Nâng cao kĩ năng viết, sử dụng chương trình con;
- Biết cách viết một chương trình có cấu trúc để giải một bài toán trên máy tính.
2. Nội dung
a) Tìm hiểu việc xây dựng các hàm và thủ tục thực hiện tính độ dài các cạnh, chu vi, diện tích, kiểm tra các tính chất đều, cân, vuông của tam giác được trình bày dưới đây.
Giả thiết tam giác được xác định bởi toạ độ của ba đỉnh. Ta sử dụng kiểu bản ghi để mô tả một tam giác:
type
Diem = record
x, y: real;
end;
Tamgiac = record
A, B, C: Diem;
end;
Ta xây dựng các thủ tục và hàm
- Thủ tục nhận dữ liệu vào là biến mô tả tam giác R và dữ liệu ra là độ dài của ba cạnh a, b,c:
procedure Daicanh(var R: Tamgiac; var a, b, c: real); - Hàm tính chu vi của tam giác R:
function Chuvi (var R: Tamgiac): real; - Hàm tính diện tích của tam giác R:
function Dientich (var R: Tamgiac): real; - Thủ tục nhận đầu vào là biến mô tả tam giác R và đầu ra là tính chất của tam giác (Deu hay Can hay Vuong):
procedure Tinhchat (var R: Tamgiac; var Deu, Can, Vuong: boolean); - Thủ tục hiển thị toạ độ ba đỉnh tam giác lên màn hình:
procedure Hienthi (var R: Tamgiac); - Hàm tính khoảng cách giữa hai điểm P, Q
function Kh_cach (P,Q: Diem): real;
b) Tìm hiểu chương trình nhập vào toạ độ ba đỉnh một tam giác và sử dụng các hàm, thủ tục được xây dựng dưới đây để khảo sát các tính chất của tam giác.
uses crt;
const
eps = 1.0E-6;
type
Diem = record
x, y: real;
end;
Tamgiac = record
A, B, C: Diem;
end;
var
T: Tamgiac;
Deu, Can, Vuong: boolean;
function Kh_cach(P, Q: Diem): real;
begin
Kh_cach := sqrt((P.x - Q.x) * (P.x - Q.x) + (P.y - Q.y) * (P.y - Q.y));
end;
procedure Daicanh(var R: Tamgiac; var a, b, c: real);
begin
a := Kh_cach(R.B, R.C);
b := Kh_cach(R.A, R.C);
c := Kh_cach(R.A, R.B);
end;
function ChuVi(var R: Tamgiac): real;
var
a, b, c: real;
begin
Daicanh(R, a, b, c);
ChuVi := a + b + c;
end;
function Dientich(var R: Tamgiac): real;
var
a, b, c, p: real;
begin
Daicanh(R, a, b, c);
p := (a + b + c) / 2;
Dientich := sqrt(p * (p - a) * (p - b) * (p - c));
end;
procedure Hienthi(var R: Tamgiac);
begin
writeln('Toa do 3 dinh cua tam giac la: ');
writeln('Dinh A(', R.A.x:0:3, ', ', R.A.y:0:3, ')');
writeln('Dinh B(', R.B.x:0:3, ', ', R.B.y:0:3, ')');
writeln('Dinh C(', R.C.x:0:3, ', ', R.C.y:0:3, ')');
end;
procedure Tinhchat(var R: Tamgiac; var Deu, Can, Vuong: boolean);
var
a, b, c: real;
begin
Deu := false;
Can := false;
Vuong := false;
Daicanh(R, a, b, c);
if (abs(a - b) < eps) and (abs(a - c) < eps) then
Deu := true
else if (abs(a - b) < eps) or (abs(a - c) < eps) or (abs(b - c) < eps) then
Can := true;
if (abs(a * a + b * b - c * c) < eps) or (abs(a * a + c * c - b * b) < eps) or (abs(b * b + c * c - a * a) < eps) then
Vuong := true;
end;
begin
clrscr;
writeln('Nhap tam giac: ');
write('Toa do dinh A: ');
readln(T.A.x, T.A.y);
write('Toa do dinh B: ');
readln(T.B.x, T.B.y);
write('Toa do dinh C: ');
readln(T.C.x, T.C.y);
Hienthi(T);
writeln('Dien tich: ', Dientich(T):9:3);
writeln('Chu vi: ', ChuVi(T):9:3);
Tinhchat(T, Deu, Can, Vuong);
writeln('Tam giac co tinh chat: ');
if Deu then writeln('la tam giac deu');
if Can then writeln('la tam giac can');
if Vuong then writeln('la tam giac vuong');
readln;
end.
c) Viết chương trình sử dụng các hàm và thủ tục xây dựng ở trên để giải bài toán:
Cho tệp dữ liệu TAMGIAC.DAT có cấu trúc như sau:
- Dòng đầu tiên chứa số N;
- N dòng tiếp theo, mỗi dòng chứa sáu số thực x, Y, X, Y, X, Y là toạ độ ba đỉnh A(x,, YA), B(xg, Ya), C(X, Y) của tam giác ABC.
Hãy nhập dữ liệu từ tệp đã cho và trong số N tam giác đó, đưa ra tệp TAMGIAC.OUT gồm ba dòng:\
- Dòng đầu tiên là số lượng tam giác đều;
- Dòng thứ hai là số lượng tam giác cân (nhưng không là đều);
- Dòng thứ ba là số lượng tam giác vuông.
Bình Luận
Để Lại Bình Luận Của Bạn