Tải bản đầy đủ (.pdf) (64 trang)

Giáo trình ngôn ngữ lập trình pascal phần 2 lê mạnh thạnh

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (1.38 MB, 64 trang )

Chơng 6

Kiểu tập hợp và kiểu mảng

6.1. Kiểu tập hợp (Set Type)
6.1.1. Định nghĩa
Dữ liệu kiểu tập hợp là một tập hợp của những dữ liệu cùng thuộc một kiểu vô hớng đếm
đợc (kiểu cơ sở của kiểu tập hợp).


Một kiểu tập hợp đợc định nghĩa bởi dạng sau:

TYPE
<tên kiểu> = SET OF <kiểu cơ sở> ;
trong đó <tên kiểu> là tên của kiểu dữ liệu cần định nghĩa <kiểu cơ sở> là tên hoặc là định nghĩa
một kiểu dữ liệu nào đó gọi là kiểu cơ sở.

Ví dụ 1. Sau đây là các ví dụ về định nghĩa kiểu dữ liệu tập hợp và mô tả biến thuộc kiểu dữ
liệu đó:
Type
Chu_so = Set Of 0..9 ;
Chu_cai_lon = Set Of A..Z;
Var
So: chu_so;
Chu : Chu_cai_lon;
Mau : Set Of (Xanh, Vang, Tim);


Nếu <kiểu cơ sở> là kiểu nguyên thì giá trị cần phải nằm trong đoạn 0 đến 255.

Hằng kiểu tập hợp đợc biểu diễn dới dạng liệt kê các phần tử nằm trong 2 dấu ngoặc vuông


[ ]. Chẳng hạn, [A,D,E] , [3, 5 , . . , 9] là các hằng kiểu tập hợp.


Hằng tập hợp rỗng đợc kí hiệu bởi [ ].



Biến tập hợp cho phép có từ 0 đến 255 phần tử.

Có thể sử dụng phép gán đối với các biến kiểu tập hợp. Chẳng hạn, chúng ta có các phép gán
sau đây:

so:=[1,2,7];
Chu:= [ ];
Mau:= [Vang,Tim,Xanh];

52


6.1.2. Các phép toán trên tập hợp
a. Phép toán quan hệ


Phép toán = (bằng) cho giá trị true nếu 2 tập hợp bằng nhau.



Phép toán <> (khác) cho giá trị true nếu 2 tập hợp khác nhau.




Phép toán <= (nhỏ hơn hoặc bằng): A<=B cho giá trị true nếu A là tập con của B.



Phép toán >= (lớn hơn hoặc bằng): A>=B cho giá trị true nếu B là tập con của A.

Chú ý. Để kiểm tra tập hợp A có thật sự nằm trong tập hợp B hay không ta sử dụng phép toán
AND nh trong câu lệnh sau đây:
if (A<>B) AND (A<=B) then
Write (A la tap hop con thuc su cua B);

b. Phép toán IN
Dùng để xét xem một phần tử nào đó có nằm trong tập hợp không? Nếu phần tử đó có trong
tập hợp thì phép toán sẽ trả về giá trị True, ngợc lại trả về giá trị False.

Ví dụ 2.
C In [A,C,D] cho giá trị True.
E In [A,C,D] cho giá trị False.

c. Các phép toán hợp, giao, hiệu
Gọi A,B là hai dữ liệu cùng kiểu tập hợp


A+B là hợp của A và B (tập hợp các phần tử thuộc A và thuộc B).



A*B là giao của A và B (tập hợp các phần tử thuộc và thuộc B).




A-B là hiệu của A và B (tập hợp các phần tử thuộc A và không thuộc B).

Chẳng hạn, nếu A=[1,3,9], B=[9,2,5] thì A+B có giá trị là [1,2,3,5,9], A*B có giá trị là [9], AB có giá trị là [1,3].

Ví dụ 3. Chơng trình dới đây nhập vào một chữ cái và xác định xem chữ cái đó là nguyên
âm hay phụ âm?
Use Crt;
Var
Chucai, nguyenam: Set of Char;
Ch: char;
Begin
Chucai:=[A..Z, a,...z];
nguyenam:=[A,E,I,O,U];

53


Repeat
Clrscr;
Write(Nhap mot chu cai:); readln (ch);
Until ch In chucai;
If Upcase(Ch) In Nguyenam Then Writeln(Ch,La Nguyen am)
Else Writeln (Ch, La Phu am);
Readln;
End.

6.2. Kiểu mảng (Array Type)
6.2.1. Khái niệm kiểu mảng (Array)

Mảng là một kiểu cấu trúc dữ liệu đợc dùng để lu trữ nhiều phần tử dữ liệu cùng kiểu cùng
tính chất nào đó trong cùng một tên chung. Các thành phần của mảng đợc xác định thông qua
truy xuất các chỉ số của nó.
Chẳng hạn, mảng a một chiều gồm 5 phần tử đợc phân bố nh sau:
a[1]

a[2]

a[3]

a[4]

a[5]

Mảng cũng có thể có nhiều chiều, có nghĩa là mỗi một phần tử của mảng đợc xác định bởi
một bộ nhiều hơn một chỉ số. Chẳng hạn, để lu trữ các mảng n hàng, m cột ta có thể sử dụng
mảng hai chiều a có nìm phần tử. Phần tử ở dòng i cột j của bảng là a[i,j].

6.2.2. Khai báo mảng một chiều
Dạng định nghĩa kiểu mảng:
TYPE
<tên kiểu mảng> = ARRAY [<chỉ số>] OF <kiểu phần tử> ;
trong đó <tên kiểu mảng> là một tên định nghĩa kiểu mảng, <chỉ số> là một kiểu vô hớng đếm
đợc có hữu hạn phần tử, <kiểu phần tử> là kiểu dữ liệu của các phần tử của mảng.
Để khai báo biến kiểu mảng ta có thể sử dụng một trong hai cách:

Cách 1.
VAR <tên mảng> : <tên kiểu mảng> ;
Cách 2.
VAR <tên mảng> : ARRAY[<chỉ số>] OF <kiểu phần tử>;

trong đó <tên mảng> là một tên đợc dùng để đặt cho mảng cần khai báo.

54


Ví dụ 4. ta có thể định nghĩa một mảng 20 phần tử thuộc kiểu Real, có chỉ số chạy từ 20
đến 39 nh sau:
Type DAY_THUC = Array[20...39] Of Real;
Khi đó để A, B là các mảng thuộc kiểu mảng trên ta cần khai báo:
Var A,B : DAY_THUC;
Ta có thể thay khai báo này bằng khai báo trực tiếp:
Var A,B: Array [20..39] Of Real;

Chú ý.
Việc truy nhập vào một phần tử nào đó của biến mảng đợc thực hiện qua tên biến mảng,
theo sau là giá trị chỉ số để trong dấu [ ].
Có thể gán một mảng cho một biến mảng khác cùng kiểu. Chẳng hạn, ta có thể thực hiện
phép gán A:=B (nghĩa là, A[20]:=B[20], A[21]:=B[21],..., A[39]:=B[39]).

6.2.3. Một số ví dụ sử dụng mảng
a. Nhập xuất giá trị cho một mảng
Các thủ tục nhập xuất biến nh: Writeln, Readln,... không thể truy xuất thẳng biến mảng mà
phải truy xuất từng thành phần nó.

Ví dụ 5. Chơng trình dới đây nhập vào từ bàn phím một dãy số nguyên M và xuất ra màn
hình theo thứ tự ngợc lại.
Program Day_so_nguyen;
Use Crt;
Const
Max=100;

Var
M : Array [1..Max] of Integer;
i,n: Byte;
Begin
Clrscr;
Repeat
Write (Cho biet so phan tu (< , Max, ): );
Readln (n);
Until n<= Max;
For i:=1 to n Do
Begin

55


Write (phan tu thu , i la: );
Readln (M[i]);
End;
Writeln (------------------------);
Writeln (In dau theo thu tu nguoc lai:);
For i:=n downto 1 do Write (M[i]#32);
Writeln;
Writeln(In cac doi so của day:);
For i:=1 to n do Write (-M[i],#32);
Readln;
End.

b. Ví dụ sắp xếp các phần tử trong mảng
Chơng trình sau đây thực hiện việc đọc vào một dãy số và sắp xếp lại nó theo thứ tự tăng.


Program săp_xep;
Var A: array [1..100] of Real;
i, j, n : Byte; T:real;

Begin
Write (Dua vao so phan tu cua day: ); readln(n);
For i:=1 to n do Begin Write(a[, i, ] = ); readln(a[i]) end;
For i:=n downto 2 do
For j:=1 to i-1 do
If A[j]>A[j+1] then
Begin
T:= A[j];
A[j]:=A[j+1] ;
A[j+1]:=T
End;
For j:=1 to n do Writeln(A[j],#32)

End.
6.2.4. Mảng nhiều chiều
Phần sau đây chủ yếu trình bày mảng hai chiều. Các mảng nhiều hơn hai chiều đợc suy diễn
lên một cách tự nhiên.

56


Khai bao mảng hai chiều : Khai báo mảng hai chiều cũng tơng tự nh mảng một chiều, chỉ
có điều có hai tập chỉ số cách nhau bởi dấu phẩy (,).

Dạng định nghĩa kiểu:
TYPE

<tên kiểu mảng>=ARRAY[<chỉ số 1>, <chỉ số 2>] OF <kiểu phần tử>; trong đó <chỉ số 1>
và <chỉ số 2> là các kiểu vô hớng đếm đợc hữu hạn phần tử. Đây là các giá trị mà các chỉ số
của các phần tử của mảng có thể nhận đợc.
Khai báo các biến của mảng nhiều chiều tơng tự nh khai báo các biến mảng hai chiều.

Ví dụ 6. Ta có thể định nghĩa kiểu mảng 2 chiều
Type M_2C=Array [1...4,A..D] Of Integer;
Khi đó mảng A với kiểu dữ liệu M_2C có thể khai báo qua tên:
Var A : M_2C;
hay khai báo trực tiếp:
A: Array [1 ...4,A..D] Of Integer;

Câu hỏi Bài tập Chơng 6

1. Viết chơng trình nhập vào một dãy số và xuất ra màn hình các thông tin sau:
a) Phần tử lớn nhất của dãy,
b) Phần tử nhỏ nhất của dãy,
c) Tổng các phần tử của dãy,
2. Viết trong cùng một chơng trình thực hiện các yêu cầu sau:
a) Nhập vào từ bàn phím một dãy số nguyên M có 10 phần tử và một số nguyên x thoả mãn
tính chất : chữ số tận cùng của x bằng 6 và 180x1200.
b) Xuất ra màn hình số phần tử trong dãy M thoả mãn tính chất : có hai chữ số và chia đúng
cho x.
c) Tính tích của các phần tử M[i] thoả mãn tính chất: 103. Viết chơng trình đổi số nguyên dơng từ hệ có số 10 sang hệ cơ số 2.

57


4. Viết chơng trình tính điểm trung bình, xếp loại cho các học sinh trong một lớp với 2 môn thi

là Văn, Toán và các thông tin thống kê sau:


Số lợng các học sinh đợc xếp loại giỏi, khá, trung bình, yếu. Tỉ lệ phần trăm tơng ứng.



Số lợng học sinh dới điểm trung bình môn Văn, Toán. Tỉ lệ phần trăm tơng ứng.

5. Viết phơng trình nhập vào từ bàn phím một dãy B có 10 phần tử và một số x. Dò tìm xem
trong dãy có hai phần tử liên tiếp nào mà tổng của chúng bằng x không ?
6. Viết chơng trình nhập vào từ bàn phím một dãy số nguyên và xuất ra màn hình tần suất (số lần
xuất hiện) của các số trong dãy số đó.
7. Viết chơng trình tạo và in ra trên màn hình ma trận đơn vị cấp 10.
8. Viết chơng trình nhập vào từ bàn phím một ma trận vuông và xuất ra màn hình tổng các phần
tử trên đờng chéo chính.
9. Viết chơng trình nhập vào từ bàn phím giá trị lợng ma trung bình của 12 tháng trong năm.
In ra màn hình biểu đồ cột đứng biểu thị lợng ma từng tháng (sử dụng ký tự #219).
10. Viết chơng trình nhập vào một chuỗi rồi tách ra các nguyên âm và phụ âm của chuỗi đó.
11 Viết chơng trình nhập vào 2 xâu rồi in ra màn hình các kí tự xuất hiện trong cả 2 xâu.
12. Viết chơng trình nhập vào các kí tự cho đến khi nào gặp dấu ! thì kết thúc. Hãy in ra kết quả.
a) Số lần xuất hiện của mỗi chuỗi loại kí tự Alphabet.
b) Tổng số các chữ cái đợc nhập vào.
c) Số kí tự nhập vào không phải là Alphabet.
13. Viết chơng trình in ra màn hình 100 số ngẫu nhiên từ 1 dến 100 sao cho không có 2 số nào
trùng nhau.
14. Viết chơng trình in ra màn hình tập hợp các từ có trong một xâu kí tự.

58



Chơng 7

Chơng trình con

7.1. Khái niệm về chơng trình con
Khi lập trình thờng gặp những đoạn chơng trình cùng giải quyết một công việc giống nhau
ở nhiều chỗ khác nhau. Để ngắn gọn và dễ sửa đổi chơng trình ngời ta thay thế việc lập những
đoạn chơng trình này thành một chơng trình con, sau đó chỉ cần gọi tên chơng trình con thay
cho việc lặp lại cả đoạn chơng trình. Chẳng hạn, có thể xây dựng chơng trình con có tên MAX
với hai tham số a, b để tính chọn giá trị lớn nhất trong hai số a, b sau đó mỗi khi cần tính giá trị
lớn nhất của hai số x,y nào đó trong chơng trình ta chỉ cần gọi chơng trình con MAX(x,y).
Một ứng dụng khác của chơng trình con là phát triển các chơng trình lớn. Khi đó có thể
chia nhỏ công việc thành nhiều chơng trình con riêng biệt (Module). Các lập trình viên có thể
làm việc độc lập với nhau, ngời quản lí chung chỉ cần tập hợp và sử dụng các chơng trình con
để phát triển chơng trình chính. Phơng pháp này cho phép nhìn nhận và giải quyết vấn đề một
cách tổng quát, không bị sa vào các chi tiết nhỏ.
Trong Pascal có hai loại chơng trình con : Chơng trình con thủ tục và chơng trình con
hàm.

7.1.1. Chơng trình con hàm
a. Dạng tổng quát của khai báo hàm
FUNCTION <tên_hàm>(<tham số hình thức>) : <kiểu dữ liệu>; <khai báo>;
Begin
<dãy các câu lệnh>

End;
trong đó:
<tên hàm> là một tên dùng để kí hiệu hàm. Kết quả thực hiện hàm giá trị lu trong
<tên_hàm>.

<tham số hình thức> là một dãy các tên biến cùng với mô tả kiểu của nó. Các biến
này đợc gọi là tham số hình thức của chơng trình con. Trong <tham số hình thức> các
biến đợc khai báo kiểu bằng hai cách:
+ Cách 1 : <danh sách biến>: <kiểu dữ liệu>. Các biến trong danh sách biến đợc gọi là các
tham trị.
+ Cách 2 : Var <danh sách biến>: <kiểu dữ liệu>. Các biến trong danh sách biến đợc gọi
là các tham biến.

59


<kiểu dữ liệu > là một tên kiểu dữ liệu hoặc định nghĩa kiểu dữ liệu, nó quy định kiểu dữ
liệu cho kết quả.
<khai báo> là các khai báo thêm cho chơng trình con nếu cần. Phần này thờng sử dụng để
khai báo các biến không phải là tham số hình thức và chỉ đợc sử dụng trong chơng trình con
(gọi là các biến cục bộ).
<dãy các câu lệnh> là một dãy các câu lệnh Pascal (có thể là lệnh ghép) để thực hiện
việc tính giá trị cho <tên hàm> mỗi khi có lời gọi hàm.

Ví dụ 1. Sau đây là một chơng trình con dạng hàm tính dùng để tính hàm tang:
Function tg(x: Real): Real;
Begin
tg:=Sin(x)/Cos(x);

End;
b. Lời gọi hàm
Hàm đợc gọi nh là một toán hạng trong biểu thức. Lời gọi hàm nh sau:
<tên hàm>(<tham số thực sự>);
trong đó <tham số thực sự > là một dãy các biểu thức tơng ứng với các biến trong thức>. Nếu tham số hình thức là tham biến thì tham số thực sự tơng ứng phải là tên biến. Nếu

tham số hình thức là tham trị thì tham số thực sự tơng ứng có thể là biểu thức.

Ví dụ 2. Nh hàm đã định nghĩa ở trên ta có thể có lời gọi:
y:=tg(x*x+2);

7.1.2. Thủ tục
a. Dạng tổng quát của khai báo thủ tục
PROCEDURE <tên thủ tục> (<tham số hình thức>);
<khai báo>;

Begin
<dãy các câu lệnh>

End;
trong đó:


<tên thủ tục> là một tên dùng để kí hiệu thủ tục.

<tham số hình thức> là một dãy các tên biến cùng với mô tả kiểu của nó. Trong hình thức> các biến đợc khai báo kiểu dữ liệu của nó bằng hai cách nh đối với chơng trình con

60


FUNCTION.
(<tham số hình thức>) có thể không có.


<khai báo> và <dãy các câu lệnh> đợc xác định nh đối với chơng trình con FUNCTION.


Ví dụ 3. Chơng trình con MAX sau đây thực hiện việc tìm số lớn nhất trong 2 số nguyên cho
trớc.
Procedure MAX(x,y:Real; Var z: Real);
Begin
If x>y then z:=x else z:=y;

End;
b. Lời gọi thủ tục
Thủ tục đợc gọi nh là một lệnh đơn trong chơng trình. Dạng gọi thủ tục nh sau:
<tên thủ tục>(tham số thực sự>);
trong đó <tham số thực sự> là một dãy các biểu thức tơng ứng với các biến trong thức>. Nếu tham số hình thức là tham biến thì tham số thực sự tơng ứng phải là tên biến. Nếu
tham số hình thức là tham trị thì tham số thực sự tơng ứng có thể là biểu thức.
Kết quả của lời gọi thủ tục là giá trị nhận đợc ở các tham biến.

Ví dụ 4. Lời gọi sau đây cho kết quả là giá trị lớn nhất giữa hai giá trị a*a+2 và b-1, với a, b
là hai biến có giá trị đã đợc xác định trớc đó. Kết quả đợc lu trong tên biến c.
MAX(a*a+2, b-1, c);

Chú ý.
Các tham số có mặt trong <tham số hình thức> và trong <tham số thực sự> phải tơng ứng
với nhau về số lợng tham số và kiểu dữ liệu.
Các biến trong chơng trình có sử dụng chơng trình con (trớc từ khoá BEGIN) đợc chia
thành hai loại:
+ Biến toàn cục : đợc khai báo ở ngoài chơng trình con trong phần khai báo của chơng
trình chính.
+ Biến cục bộ : đợc khai báo bên trong chơng trình con và chỉ đợc sử dụng bên trong
chơng trình con đó.
Các biến thực sự tơng ứng với tham trị sau khi ra khỏi chơng trình con vẫn giữ nguyên giá

trị trớc khi vào chơng trình con.
Có nghĩa là giá trị của nó không bị thay đổi bởi các phép gán trong chơng trình con.

Ví dụ 5. Hai chơng trình dới đây sẽ chỉ rõ sự khác nhau giữa tham biến và tham trị trong
các chơng trình con.
Chơng trình 1.
Program Tham_tri;

61


Var
a,b,c: Integer;
Procedure InTri(x,y,z : Integer);
Begin
x:=x*2; y:=y*2; z:=z*2;
Writeln(Trong thu tuc ta co 3 so:,x,#32,y,#32,z);
End;
Begin
a:=10; b:=20; c:=30;
Writeln (Truoc khi vao thu tuc ta co 3 so:, a,#32,b,#32,c);
Intri(a,b,c);
Writeln (sau khi ra thu tuc ta co 3 so:, a,#32,b,#32,c);
End.
Trong ví dụ này ta thấy a, b, c không thay đổi mặc dầu thủ tục InTri đã nhân x, y, z cho 2.

Chơng trình 2.
Program Tham_bien;
Var a,b,c: Integer;
Procudure InTri(Var x,y,z : Integer);

Begin
x:=x*2; y:=y*2; z:=z*2;
Writeln (Trong thutuc ta co 3 so:,x,#32,y,#32,z);
End;
Begin
a:=10; b:=20; c:=30;
Writeln (Truoc khi vao thu tuc ta co 3 so:,a,#32,b,#32,c);
Intri(a,b,c);
Writeln (sau khi ra thu tuc ta co 3 so :,a,#32,b,#32,c);
End.
Trong ví dụ này khi thủ tục InTri nhân x, y, z với 2 thì biến toàn cục thay đổi.
7.2. Một số hàm và thủ tục của Turbo Pascal
7.2.1. Các thủ tục
CLRSCR: Thủ tục này có tác dụng xoá toàn bộ màn hình và đa con trỏ màn hình (cursor)
về vị trí (1,1) trên màn hình.
CLREOL : Thủ tục này có tác dụng xoá từ vị trí con trỏ màn hình đến cuối dòng hiện hành
trên màn hình.
INSLINE : Thủ tục này có tác dụng chèn dòng trống vào vị trí hiện hành của con trỏ màn
hình trên màn hình.

62


DELLINE : Thủ tục này có tác dụng xoá dòng chứa con trỏ màn hình, các dòng sau sẽ đợc
chuyển lên một dòng.
TEXMODE(<Medo>: Integer). Thủ tục này có tác dụng chọn chế độ trình bày văn bản.
Tham số< Mode> sẽ lấy giá trị:
BW40=0;

{40x25 B/W trên Color Adapter},


C40=1;

{40x25 Color trên Color Adapter},

BW80=2;

{80x25 B/W trên Color Adapter},

C80=3;

{80x25 Color trên Color Adapter},

Mono=7;

{80x25 trên Monochrome Adapter},

Font8x8=256; EGA và VGA: 43, 50 Line Mode.
LastMode= -1.
Khi khai báo TextMode (LastMode) chơng trình tự động thử xem Mode màn hình trớc đó và
ấn định Mode đó cho chơng trình. Điều này đặc biệt thuận lợi khi ta muốn chơng trình chạy đợc
trên nhiều loại máy khác nhau.
WINDOW (x1,y1,x2,y2): Thủ tục này có tác dụng thiết lập một cửa sổ để trình bày. (x1,y1)
là toạ độ góc trái phía trên của cửa sổ, (x2,y2) là toạ độ góc phải phía dới của cửa sổ. Cửa sổ mặc
nhiên là Window(1,1,80,25). Thủ tục này ảnh hởng đến các lệnh trình bày dữ liệu trên màn hình
ở chế độ văn bản.

x.

GOTOXY(x,y) : Thủ tục này có tác dụng đa con trỏ màn hình đến tọa độ (x,y) : dòng y, cột




HIGHVIDEO : Thủ tục này cho phép hiển thị trên màn hình với độ chói cao.



LOWVIDEO : Thủ tục này cho phép hiển thị trên màn hình với độ chói thấp.

NORMVIDEO: Thủ tục này khôi phục thuộc tính màn hình, mặc định theo các thuộc tính đã
hiện hữu ở vị trí con trỏ màn hình khi thực hiện chơng trình.
SOUND(Hz) : Thủ tục này cho phép phát âm thanh có tần số Hz cho đến khi gặp thủ tục
NoSound.


NOSOUND : Thủ tục này có tác dụng tắt loa phát âm thanh ở máy.



DELAY (ms) : Thủ tục này tạm treo chơng trình trong thời gian ms mili giây.

TEXTCOLOR(color) : Thủ tục này chọn màu của kí tự trình bày trên màn hình. Color có
giá trị từ 0 đến 255


TEXTBACKGROUND(color). Thủ tục này chọn màu nền trong chế độ văn bản.

63



Các hằng xác định màu nền và chữ:
Black

= 0 Brown

= 6 LightRed

= 12

Blue

= 1 LighGray

= 7 LightMagenta

= 13

Green

= 2 DarkGray

= 8 Yellow

= 14

Cyan

= 3 LightBlue

= 9 White


= 15

Read

= 4 LightGreen

= 10

Magenta

= 5 LightCyan

= 11

Hằng xác định nhấp nháy:

Blink = 128

Chú ý. Nếu muốn màu nền loang đều trên màn hình thì sau khi phát lệnh
TextBackGround(color) thì đánh tiếp lệnh ClrScr.
7.2.2. Các hàm
KEYPRESSED : Hàm kiểm tra có nút nào đợc nhấn trên bàn phím không. Nếu có cho giá
trị True, nếu không cho giá trị False.


READKEY : Hàm đọc kí tự từ bàn phím (ký tự nhập không đợc trình bày trên màn hình).

Các nút trên bàn phím nh: A, B, C, ... chỉ tạo một kí tự khi đợc nhấn. Còn các nút chức
năng F1, F2,... Home, end, Alt, Ctrl,... tạo hai kí tự khi đợc nhấn, trong đó kí tự thứ nhất sẽ mang

mã 0. Hàm ReadKey chỉ đọc đợc kí tự thứ nhất (kết quả đều nh nhau). Để sử dụng đợc các nút
này, trong lập trình ta sử dụng:
Ch:= ReadKey;
If Ch=#0 then Ch:= ReadKey;
Nếu nhấn nút chức năng thì đọc tiếp kí tự còn lại trong bộ đệm của keyboard.

7.2.3. Thủ tục và hàm đệ quy
Trong Pascal chuẩn cũng nh trong Turbo Pascal đều cho phép gọi đệ quy trong các chơng
trình con thủ tục và hàm. Chơng trình con (thủ tục hoặc hàm) là đệ quy nếu trong nó chứa lời gọi
đến chính nó. Để thấy rõ hơn ta xét hai chơng trình con sau đây:

Chơng trình con 1. Thủ tục đệ quy sau đây thực hiện việc in ra dãy các chữ số của một số
tự nhiên theo thứ tự ngợc lại:
Procedure In_so(n:word);
Begin
if n <>0 then
begin
write(n mod 10);

In_so(n div 10)

64


end
End;
Khi có lời gọi, chẳng hạn In_so(123) thì quá trình thực hiện sẽ nh sau:


IN số 3 (theo lệnh write(123 mod 10).




Gọi thủ tục In_so(12) (theo lời gọi In_so(123 div 10)).



In số 2 (theo lệnh write(12 mod 10).



Gọi thủ tục In_so(1) (theo lời gọi In_so(12 div 10)).



In số 1 (theo lệnh write(1 mod 10).



Gọi thủ tục In_so(0) (theo lời gọi In_so(1 div 10)).

Đến đây dừng vì n=0.

Chơng trình con 2. Chơng trình con hàm sau đây thực hiện việc tính giai thừa của một số
tự nhiên n.
Function G_thua(var n:word): word
Var GT: word;
Begin
If n=0 then G_thua:=1 else
begin

GT:=G_thua(n-1);
G_thua:=n*GT
end
End;
Khi đó lời gọi hàm, chẳng hạn A:=G_thua(4), quá trình thực hiện sẽ nh sau:


A=4.G_thua(3)(G_thua:=4*GT mà GT:=G_thua(4-1)).



A=4. 3.G_thua(2)( G_thua:=3*GT mà GT:=G_thua(3-1)).



A=4. 3.2.G_thua(1)( G_thua:=2*GT mà GT:=G_thua(2-1)).



A=4. 3. 2. 1.G_thua(0)( G_thua:=1*GT mà GT:=G_thua(0)).

Cuối cùng A=4.3.2.1.1 = 4!

Câu hỏi Bài tập Chơng 7

1. Viết chơng trình tính tổng:

65



1! + 2! + 3! + ... +n! với n < 12 và đã đợc nhập vào từ bàn phím.
2. Viết chơng trình có các chức năng sau:


Tìm ớc số chung lớn nhất của hai số nguyên.



Tìm bội số chung nhỏ nhất của hai số nguyên.



Tìm số bé nhất trong ba số.

3. Viết chơng trình vẽ một đờng thẳng đứng (bằng kí tự *) có chiều dài bằng 5 tại cột 4 và cho
di chuyển đến cột 20.
4. Viết trong cùng một chơng trình :
Khai báo một hàm tên là F nhằm mục đích đối chiếu số nguyên k có thoả mãn tính chất : số
tận cùng của k là 6 và k chia hết cho 4 hay không?
Trong phần chơng trình chính : Nhập vào một mảng số nguyên M gồm 8 phần tử từ bàn
phím. Dùng hàm F đếm và in ra số phần tử trong mảng M thoả mãn tính chất : Chữ số tận cùng là
6 và chia hết cho 4.
5. Viết chơng trình đọc vào một dãy số, xác định phần tử nhỏ nhất, lớn nhất và trung bình cộng
của dãy số đó. Hãy sử dụng 4 chơng trình con sau: DOC (đọc vào các phần tử của mảng),
MAX (tìm giá trị lớn nhất của mảng), MIN (tìm giá trị nhỏ nhất của mảng) và TRUNGBINH
(tìm giá trị trung bình cộng của mảng).
6. Tàu NT1 cứ k ngày cập bến cảng một lần, tàu NT2 cứ m ngày cập bến cảng một lần (km).
Viết chơng trình nhập k và m từ bàn phím rồi tính xem nếu hai tàu cùng rời cảng thì sau thời
gian ngắn nhất là bao nhiêu ngày chúng lại cùng cập cảng. Biết rằng ngày rời cảng luôn luôn
cùng với ngày cập cảng.

7. Viết chơng trình nhập từ bàn phím 2 ma trận vuông cấp 2 và xuất ra màn hình các kết quả sau:
a) Ma trận tổng A + B.
b) Ma trận hiệu A B.
c) Ma trận tích A * B.
d) Ma trận chuyển vị của A.
8. Viết hàm Function NTo(n:word) : Boolean; để kiểm tra xem n có phải là số nguyên tố ?
9. Viết 2 hàm tìm Max, Min của 3 số thực.
10. Viết hàm LOWCASE(c: Char): Char để đổi chữ cái hoa C thành chữ thờng.
11. Viết thủ tục KHUNG(x1,y1,x2,y2:Integer) để vẽ một khung hình chữ nhật có đỉnh trên bên
trái là (x1,y1) và đỉnh dới bên phải là (x2,y2).
12. Viết thủ tục FILL(x1,y1,x2,y2:Integer; ch:Char) để tô một vùng màn hình hình chữ nhật có
đỉnh trên bên trái là (x1,y1) và đỉnh dới bên phải là (x2,y2) bằng các kí tự ch.
13. Viết thủ tục để hoán đổi hai giá trị x,y cho nhau.
14. Viết hàm tìm BSCNN và USCLN của 2 số nguyên a,b đợc khai báo nh sau:

66


Function USCLN(a,b: word ) : word;
Function BSCNN(a,b: word ) : word;
15. Viết thủ tục để tối giản phân số a/b, với a, b là 2 số nguyên.
16. Viết các hàm đệ quy để tính :
S1 = 1 + 2 + 3 + ..........+n ;
S2 = 1 + 1/2 + .......... + 1/n ;
S3 = 1 1/2 + .......... + (1)n+1 1/n;
S4 = 1/1*2 + 1/2*3 + .......... + 1/(n 1)*n;
S5 = 1 + sin(x) + sin2(x) + .......... + sinn(x).
k-1
k
17. Viết hàm đệ quy tính C nk biết : C nn = 1, C 0n = 1, C nk = C n-1

+ C n-1

18. Cho m, n nguyên dơng. Lập hàm đệ quy tính:

m +1

A(m,n) = A(n - 1,1)
A(n - 1, A(n,m - 1))


n=0
n 0, m = 0
n>0^m>0

19. Lập hàm đệ quy để tính dãy Fibonaci :
1
F(n) =
F(n - 1) + F(n - 2)

n =1 n =2
n>2

20. Viết hàm đệ quy tìm USCLN của 2 số.

67


Chơng 8

Kiểu chuỗi kí tự


8.1. Khai báo kiểu chuỗi
Chuỗi là kiểu dữ liệu có cấu trúc dùng để tổ chức lu trữ và xử lí các xâu kí tự. Một chuỗi
đợc khai báo bằng từ khoá STRING theo sau là số kí tự cực đại có thể có của chuỗi đợc đặt
trong hai dấu ngoặc vuông [ ].
Định nghĩa kiểu chuỗi:
TYPE
<tên> = String[<độ dài cực đại>];
trong đó <tên> là tên của kiểu dữ liệu, <độ dài cực đại> là một số nguyên dơng chỉ độ dài tối đa
của mỗi chuỗi có thể đợc lu trữ trong biến thuộc kiểu dữ liệu này.
Đối với Turbo Pascal:


String có chiều dài tối đa là 255.



Có thể không chỉ ra <độ dài cực đại> khi đó mặc nhiên độ dài cực đại là 255.

Biến kiểu chuỗi có thể đợc khai báo bằng tên hoặc khai báo trực tiếp nh trong ví dụ sau
đây:

Ví dụ 1.
Var
Hoten : String[30];
St

: String;

Nếu St là một chuỗi, để chỉ ra kí tự thứ i của St ta viết St[i]. Chẳng hạn, nếu St:= ABCDE;

thì lệnh Writeln(St[3]); sẽ cho ra kí tự C.
Cấu trúc của một biến kiểu chuỗi nh sau : Trong bộ nhớ, nó chiếm số byte bằng <độ dài
cực đại> cộng thêm một byte đầu tiên (gọi là byte 0) để chứa kí tự mà mã thập phân ASCII
của kí tự này là số kí tự thực có của chuỗi. Chẳng hạn, biến Hoten đợc khai báo ở trên đợc
gán giá trị : Hoten:=HO DUC ; khi đó độ dài của chuỗi chỉ là 6 kí tự, mặc dù ở độ dài
cho phép của Hoten la 30. Sau đây là cấu trúc chuỗi Hoten:=HO DUC.
0

1

2

3

4

5

6

7

68

8

......

28


29

30




H O

D

U

C

*

*

......

*

*

*

Kí tự đầu là kí tự mà mã ASCII của nó chỉ độ dài thực có của String, ở đây nó là kí tự . Kí tự
* biểu diễn kí tự không xác định.


Chú ý.
Có thể dùng Write(St) hay Writeln (St) để in kí tự St trong khi đó không thể dùng Write và
Writeln để viết ra cả một mảng.
Readln(St) sẽ đọc các kí tự cho chuỗi St với độ dài thực sự là số kí tự gõ vào từ bàn phím. Nếu
ta gõ <Enter> luôn, không cho kí tự nào thì St = (chuỗi rỗng).

8.2. Các phép toán trên chuỗi kí tự
a) Phép gán
Đối với các đại lợng thuộc kiểu chuỗi kí tự ta có thể thực hiện lệnh gán dạng:
<biến> := <biểu thức>;
trong đó <biến> là tên biến thuộc kiểu chuỗi kí tự, còn <biểu thức> là một biểu thức kiểu
chuỗi kí tự. Biểu thức kiểu chuỗi kí tự là một dãy hằng, biến, hàm kiểu chuỗi kí tự đợc nối
với nhau bằng phép ghép (+) các chuỗi kí tự.

b) Ghép nối chuỗi
Phép nối String : Kí hiệu bởi dấu (+).
Chẳng hạn : Nếu A:= Turbo;
B:= Pascal;
C:= A + B;
thì sau khi thực hiện 3 lệnh này C sẽ có nội dung là chuỗi Turbo Pascal.

c) So sánh chuỗi
Giữa các đại lợng kiểu chuỗi kí tự có các phép so sánh < (nhỏ hơn), <= (nhỏ hơn hoặc
bằng), > (lớn hơn), >= (lớn hơn hoặc bằng), = (bằng), <> (khác).
Khi so sánh hai chuỗi, các kí tự của hai chuỗi đợc so sánh từng cặp một từ trái qua phải theo
giá trị của bảng mã ASCII.
Nếu hai chuỗi có độ dài khác nhau song số kí tự giống nhau đến độ dài chuỗi ngắn nhất thì
chuỗi có độ dài ngắn hơn đợc coi là bé hơn.

Ví dụ 2. Các phép so sánh:

ABC = ABC có trị là True.
ABC = AB có trị là False.
ABCD < ABED có trị là True.

69


ABC > AD có trị là False.

8.3. Các thủ tục trên chuỗi kí tự
Thủ tục DELETE (<St>, <Pos>, <Num>);
trong đó <St> là biến kiểu String, <Num> và <Pos> là các biểu thức nguyên. Thủ tục này xoá
khỏi chuỗi <St> một số kí tự là <Num> và bắt đầu từ vị trí thứ <Pos> (tính từ trái sang phải).

Ví dụ 3. Nếu St là biến kiểu chuỗi kí tự thì sau khi thực hiện dãy lệnh:
St:=ABCDEFG;

Delete(St, 2, 4);
Writeln(St);
trên màn hình sẽ có kết quả là : AFG.
Thủ tục INSERT(<St2>,<St1>,<Pos>);
trong đó <St1> là biến kiểu String, <St2> là biểu thức kiểu String, <Pos> là biểu thức kiểu
nguyên. Thủ tục này dùng để chèn chuỗi kết quả của biểu thức <St2> vào chuỗi <St1> ở vị trí
<Pos>.

Ví dụ 4. Nếu St là biến kiểu chuỗi thì dãy lệnh:
St:= ABCD;

Insert(TFG, St, 3);
Writeln(St);

sẽ cho kết quả trên màn hình là: ABTFGCD.
Trờng hợp <Pos> vợt quá chiều dài của <St1> thì <St2> sẽ đợc nối đuôi vào <St1>.
Thủ tục STR(<Value>,<St>);
trong đó <Value> là một biểu thức nguyên hay thực có kèm theo dạng in ra, <St> là biến kiểu
chuỗi kí tự. Thủ tục này đổi giá trị số <Value> thành chuỗi rồi gán cho <St>.

Ví dụ 5. Nếu St là tên biến thuộc kiểu kí tự, I là biến nguyên thì sau khi thực hiện dãy lệnh
sau:
i:=1234;

Str(i:5, St);
Writeln(St);
thì kết quả xuất hiện trên màn hình là: 1234 (có năm kí tự, kí tự đầu tiên là kí tự trắng).
Thủ tục VAL(<St>,<var>,<code>);
trong đó <St> là biểu thức kiểu chuỗi kí tự, <var> là biến nguyên hay thực, còn <code> là biến
nguyên. Thủ tục này đổi chuỗi chữ số <St> (biểu diễn một số nguyên hay thực) thành số và gán
cho biến <var>.<code> là số nguyên để phát hiện lỗi : Nếu phép biến đổi đúng thì <code> có giá

70


trị bằng 0, nếu sai do <St> không biểu diễn đúng số nguyên hay thực, <code> sẽ nhận giá trị bằng
vị trí của kí tự sai trong chuỗi <St>.

Ví dụ 6. Nếu St là biến kiểu chuỗi kí tự, i và e là hai biến nguyên thì sau khi thực hiện dãy
lệnh:
St:=234 ;
e:=0;

Val(St, i, e);

Writeln(i);
sẽ cho kết quả trên màn hình là : 234
Nếu thay lệnh đầu tiên là St:=2121x thì i không xác định và e=3 (kí tự thứ 3 gây lỗi).
Sau đây là một ứng dụng dùng thủ tục Val để đọc số nguyên từ bàn phím. Bình thờng ta dùng
thủ tục Readln(i) để đọc số nguyên i, song nếu chẳng may ta gõ nhầm chữ cái vào máy thì máy
dừng lại, có thể gây lãng phí thời gian, bây giờ ta muốn máy kiểm tra lỗi, nếu có thì báo lỗi để gõ
lại số liệu.

Procedure DOC_Integer(Var: Integer);
Var St: String[6]; e: Integer;
Begin
Repeat
Readln(St);

Val(St,I,e);

If e<>0 Then Writeln(#7,Error!);
Until e=0;
End;
Bạn có thể sửa đổi một ít chơng trình này để đọc số thực.

8.4. Các hàm trên chuỗi
Hàm LENGTH(<St>);
trong đó <St> là một biểu thực chuỗi. Hàm này cho ta độ dài của biểu thức chuỗi kí tự <St>.

Ví dụ 7. Nếu St là biến chuỗi , i là một biến nguyên thì sau khi thực hiện dãy lệnh sau:
St = ABCDEF ;
i:= Length(St);
Writeln(i);
sẽ cho kết quả trên màn hình là số nguyên 7.

Hàm COPY(<St>,<Pos>,<Num>);

71


trong đó <St> là biểu thức kiểu chuỗi kí tự, <Pos>, <Num> là các biểu thức kiểu nguyên. Hàm
cho ta một chuỗi mới bằng cách chép <Num> kí tự từ chuỗi <St>, bắt đầu từ vị trí <Pos>.

Ví dụ 8. Nếu St1, St2 là các biến kiểu chuỗi kí tự thì sau khi thực hiện dãy lệnh:
St1:=BCDEF;
St2:=Copy(St1, 3, 2);
Writeln(St2);
thì trên màn hình sẽ cho kết quả là chuỗi : CD
Nếu <Pos>+<Num> lớn hơn Length (<St>) thì Copy chỉ nhận các kí tự nằm trong chuỗi <St>.
Nếu <Pos> lớn hơn Length(<St>) thì Copy sẽ cho một chuỗi rỗng.
Hàm CONCAT(<St1>,<St2>, ..., <Stn>);
trong đó <St1>, <St2>, ...,<Stn> là các biểu thức kiểu chuỗi kí tự.
Hàm này cho kết quả là ghép nối tất cả các chuỗi <St1>, <St2>,...,<Stn> thành một chuỗi theo
thứ tự đã viết.

Chú ý.


Số lợng đối số của hàm concat phải 2.



Nếu tổng số chiều dài của các chuỗi cộng lại > 255 thì máy sẽ báo lỗi.




Có thể dùng phép (+) để ghép nối chuỗi thay Concat.

Hàm

POS(<St1>,<St2>);

trong đó <St1>,<St2> là hai biểu thức kiểu chuỗi kí tự. Hàm này cho ta số nguyên chỉ vị trí đầu
tiên của chuỗi <St1> gặp trong chuỗi <St2>. Nếu không tìm thấy thì <Pos> có giá trị bằng 0.
Chẳng hạn, nếu St:=ABCDEFBCD thì
Pos(DE,St) cho kết quả là 4,
Pos(XY,St) là 0;
Pos(BCD, St) là 2

Ví dụ 9. Viết chơng trình nhập vào từ bàn phím một chuỗi kí tự và in ra màn hình chuỗi
ngợc tơng ứng. Ví dụ, nhập vào TRUNG TAM xuất ra MAT GNURT.
Program Chuoi_nguoc;
Uses Crt;
Var
cau

: String[80];

i

: Byte;

Begin

72



Writeln(Nhập vào một câu: ); Readln(cau);
For i := Length(cau) Downto 1 Do Writeln(cau[i]);
Readln
End.

Ví dụ 10. Viết chơng trình nhập vào một chuỗi, sau đó tách thành chuỗi con theo ý muốn,
bằng cách cho biết vị trí đầu tiên và độ dài của chuỗi con.
Program Tach_chuoi;
Uses Crt;
Var
St: String[80];
Vt, dd: Byte;
begin
Clrscr;
Writeln(Nhap vao mot chuoi: );
Readln(St);
Write(Muon tach tai vi tri nao?: );
Readln(Vt);
Writeln(Dua vao do dai cua chuoi con?: );
Readln(dd);
Writeln(--------------------------);
Writeln(Chuoi con can tach la: ) , Copy(St,VT,dd));
Readln;
End.

73



Câu hỏi Bài tập chơng 8

1. Viết chơng trình nhập vào từ bàn phím họ và tên Việt Nam và chỉ xuất phần tên ra màn hình.
Chẳng hạn, nhập Nguyễn Văn Long, xuất Long.
2. Viết chơng trình nhập vào từ bàn phím một chuỗi kí tự bằng các kí tự thờng hay hoa và xuất
ra màn hình chuỗi đó bằng kí tự hoa. Chẳng hạn, nhập Trung Tam xuất ra TRUNG TAM.
3. Viết chơng trình đổi một số nguyên dơng hệ cơ số 10 sang hệ cơ số bất kì.
4. Viết chơng trình đọc vào từ bàn phím một câu đợc kết thúc bằng dấu chấm và cho biết có
bao nhiêu nhóm kí tự T.R trong câu này.
5. Viết chơng trình đọc vào từ bàn phím một câu đợc kết thúc bằng dấu chấm. Hãy đếm trong
câu có bao nhiêu từ. Để đơn giản, ta định nghĩa từ là một dãy liên tục các kí tự khác khoảng
trắng, khoảng trắng là dấu tách từ duy nhất.
6. Viết chơng trình xuất lên màn hình một khung hình chữ nhật và một dòng chữ di chuyển từ
phải qua trái bên trong khung cho đến khi nhấn một phím bất kì.
7. Viết hàm Trim(St:String):String, có kết quả trả về chuỗi St đợc loại bỏ các khoảng
trống bên phải.
8. Viết chơng trình tính tổng các số hạng của một số nguyên dơng bất kì nhập vào từ bàn phím.

74


Chơng 9

Kiểu bản ghi và kiểu tập tin

9.1. Kiểu bản ghi (Record type)
9.1.1. Khái niệm và định nghĩa
Các kiểu cấu trúc dữ liệu nh kiểu mảng, kiểu tập hợp đều đợc tạo ra bằng một tập hợp các
phần tử có cùng kiểu. Chẳng hạn, các phần tử của mảng đợc mô tả bởi Array[1..50] of Integer là
các số nguyên. Để tạo ra một kiểu cấu trúc dữ liệu mới với các phần tử dữ liệu có kiểu khác nhau,

ngời ta định nghĩa ra các bản ghi (Record).
Record là một cấu trúc nhiều thành phần. Các thành phần có thể thuộc các kiểu dữ liệu khác
nhau và đợc gọi là trờng (Field), mỗi trờng đều đợc đặt bởi một tên.
Để định nghĩa kiểu T có cấu trúc kiểu bản ghi với danh sách các trờng có tên là: S1, S2, ...,
Sn và có các mô tả kiểu tơng ứng là T1, T2,...,Tn ta có cách viết nh sau:
TYPE
T = RECORD
S1 : T1;
S2 : T2;
.........
Sn : Tn;

END;
Ví dụ 1. Để định nghĩa kiểu thời gian DATE có 3 trờng Ngay (ngày), Thang (tháng) và Nam
(năm) trong Pascal có thể viết:
Type
Date = Record
Ngay : 1..1;
Thang : 1..12;
Nam : Word;

End;
Ví dụ 2. Định nghĩa kiểu bản ghi Dia_chi (địa chỉ) bao gồm có 3 trờng : So_nha (số nhà),
Duong_pho (tên đờng phố), Thanh_pho (tên thành phố).

75


Type
Dia_chi = Record

So_nha : Word;
Duong_pho : String[20];
thanh_pho : String[15];

End;
Để mô tả một biến kiểu bản ghi ta có thể mô tả bằng tên kiểu bản ghi hoặc mô tả thông qua
định nghĩa trực tiếp. Chẳng hạn, với tên Dia_chi đã đợc định nghĩa trong ví dụ 2 ta có thể mô tả:

Var X,Y,Z : Dia_chi;
hoặc có thể mô tả trực tiếp nh sau:

Var X,Y,Z : Record
So_nha : Word;
Duong_pho : String[20];
Thanh_pho : String[15];

End;
9.1.2. Sử dụng biến kiểu bản ghi
Muốn truy xuất một biến kiểu bản ghi ta phải truy xuất theo thành phần của chúng. Cú pháp
để truy xuất đến một thành phần nào đó là:
<tên biến>.<tên trờng>
trong đó, <tên biến> là tên của biến kiểu bản ghi cần truy xuất còn <tên trờng> là tên của trờng
cần truy xuất trong biến kiểu bàn ghi.

Ví dụ 3. Với mô tả biến :
Var X : Record
Ngay : 1..31;
Thang : 1..12;
Nam : Word;
End;

ta có thể sử dụng các lệnh truy xuất sau:
X.Ngay := 01 ;
X. Thang := 06;
X.Nam := 1953;

Ví dụ 4. Chơng trình sau đây thực hiện việc nhập lí lịch cán bộ cho một đơn vị.

76


×