Lập trình Pascal - Chương 6: Kiểu mảng
Tập chỉ số phải là một kiểu miền con, kiểu vô hướng liệt kê, kiểu char hoặc
kiểu boolean. Tuy nhiên. người ta thường dùng kiểu miền con các số nguyên là dễ
hình dung nhất vì nó gần giống với khái niệm chỉ số trong toán học.
Có hai cách khai báo là khai báo gián tiếp và khai báo trực tiếp.
Type
Vector = Array[1.10] of Integer;
Var
vt: Vector ;
Hoặc ta khai báo như sau:
Var
vt: Array[1.10] of Integer;
Ta thấy cách cách khai báo trực tiếp thì ngắn hơn, nhưng trong một số trường
hợp lại bất tiện, thậm chí không sử dụng được như khi truyền tham số cho các chương
trình con.
FALSE và ngược lại.
- Phép so sánh <= (nhỏ hơn hoặc bằng). A <= B cho kết quả là True khi mọi
phần tử của A đều có trong B.
- Phép so sánh >= (lớn hơn hoặc bằng). A >= B cho kết quả là True khi mọi phần
tử của B đều có trong A.
Trang 13
III. VIẾT VÀ ĐỌC DỮ LIỆU TRÊN TẬP HỢP
Đối với dữ liệu kiểu tập hợp ta không thể viết ra hoặc đọc vào bằng các lệnh
Read, Readln, Write, Writeln. Tuy nhiên ta có thể lập trình thực hiện các thao tác này.
Ví dụ sau sẽ nhập vào một tập hợp kiểu Char và in lên màn hình tập hợp vừa
nhập.
Type CHUCAI = SET OF CHAR;
Var cc: CHUCAI;
i, n: Integer;
ch: Char;
Begin
Write(‘ Tập hợp có bao nhiêu phần tử? ‘); Readln(n);
cc := [];
For i := 1 to n do Begin
Write(‘ Phần tử thứ ‘ ,i, ’ là: ’);
Readln(ch);
cc:= cc + [ch];
End;
Writeln(‘Các phần tử trong tập hợp bạn vừa nhập’);
For ch := ‘A’ to ‘z’ do
If ch IN cc then
Write(ch: 5);
Readln;
End.
Trang 14
Chương 10: KIỂU MẨU TIN
I. KHÁI NIỆM VÀ KHAI BÁO KIỂU MẨU TIN
Chúng ta đã học các cấu trúc dữ liệu như mảng (Array), tập hợp (Set). Các kiểu
dữ liệu này là một tập hợp có cùng kiểu do đó kả năng sử dụng các kiểu dữ liệu này
còn hạn chế. Vấn đề đặt ra là có một kiểu cấu trúc dữ liệu có nhiều phần tử khác kiểu
nhau nhưng lại liên quan đến nhau, người ta đã định nghĩa kiểu mẩu tin (RECORD) để
đáp ứng vấn đề đó.
Cấu trúc dữ liệu kiểu RECORD được gắn liền với cấu trúc dữ liệu kiểu FILE
(được trình bày chương sau) để lưu trữ dữ liệu. Dĩ nhiên Pascal cũng cho phép sử dụng
RECORD độc lập với FILE.
Khai báo dữ liệu kiểu RECORD bắt đầu là chữ RECORD tiếp theo là danh sách
các phần tử của Record gọi là các trường (Fields), mỗi trường có tên trường, kiểu
trường. Kết thúc khai báo Record là tìư khoá END; (End và chấm phẩy). Ta xem cú
pháp khai báo dưới đây.
Ta hãy xét ví dụ dưới đây. Khai báo Record là các thuộc tính của học sinh.
Type HOCSINH = RECORD
Holot: String[30];
Ten: String[10];
Lop: Byte;
Diachi: String;
END;
Var hsa, hsb, hsc: HOCSINH;
Lop10A: Array[1..50] of HOCSINH;
II. TRUY XUẤT MỘT MẨU TIN
Để truy xuất một trường của Record, ta cần dùng tên biến kiểu Record sau đó là
dấu . (chấm) rồi đến trường. Ví dụ ta sẽ nhập vào và in ra các thuộc tính của học sinh a
(hsa) đã khai báo trên.
Type HOCSINH = RECORD
Holot: String[30];
Ten: String[10];
Lop: Byte;
Diachi: String;
END;
Var hsa: HOCSINH;
Cú pháp: = RECORD
[, ]:
[, ]:
........................................................................
END;
Trang 15
Begin
Write(‘ Nhập vào họ và các chữ lót: ‘); Readln(hsa.Holot);
Write(‘ Nhập vào tên: ‘); Readln(hsa.Ten);
Write(‘ Nhập vào lớp: ‘); Readln(hsa.Lop);
Write(‘ Nhập vào địa chỉ: ‘); Readln(hsa.Diachi);
Writeln(‘ Thông tin về học sinh bạn vừa nhập ’);
Writeln(‘ Họ và tên: ’ , hsa. Holot,’ ‘, hsa.Ten);
Writeln(‘ Lớp: ’ , hsa.Lop);
Writeln(‘ Địa chỉ: ’ , hsa.Diachi);
Readln;
End.
Ta lưu ý lệnh hsb := hsa là sao chép toàn bộ hsa vào hsb. Đây là việc truy xuất
vào toàn bộ biến kiểu Record chứ không riêng lẻ một trường nào cả.
III. CÂU LỆNH WITH…DO
Như trên ta thấy việc truy xuất một trường biến kiểu Record phải thông qua tên
và dấu chấm, làm phức tạp thêm chương trình, giải quyết bớt phần nào sự phức tạp
này, Pascal đưa ra câu lệnh With … do ta hãy viết chương trình nhập học sinh của lớp
10A đã khai báo ở trên, có dùng lệnh With … do.
Var Lop10A: Array[1..50] of HOCSINH;
i, n: Integer;
Begin
Write(‘ Lớp có bao nhiêu học sinh? ‘); Readln(n);
For i:=1 to n do
With Lop10A[i] do Begin
Write(‘ Nhập họ và các chữ lót: ‘); Readln(Holot);
Write(‘ Nhập vào tên: ‘); Readln(Ten);
Write(‘ Nhập vào lớp: ‘); Readln(Lop);
Write(‘ Nhập vào địa chỉ: ‘); Readln(Diachi);
End;
Writeln(‘ Thông tin về các học sinh bạn vừa nhập ’);
For i:=1 to n do
With Lop10A[i] do Begin
Writeln(‘ Họ và tên: ’ , Holot,’ ‘, Ten);
Writeln(‘ Lớp: ’ , Lop);
Writeln(‘ Địa chỉ: ’ , Diachi);
End;
Readln;
End.
Trang 16
Chương 11: KIỂU TẬP TIN
I. KHÁI NIỆM
Đối với các kiểu cấu trúc dữ liệu ta đã biết như kiểu mảng, kiểu tập hợp, kiểu
Record, dữ liệu được tổ chức trên bộ nhớ trong (RAM) của máy tính nên khi kết thúc
chương trình thì dữ liệu cũng mất luôn. Điều này thật tai hại vì khi cần ta phải nhập dữ
liệu lại - một công việcchẳng thú vị gì và rất mất thời gian. Để giải quyết vấn đề này,
người ta đặt ra kiểu tập tin (File). Kiểu FILE cho phép lưu trữ dữ liệu ở bộ nhớ ngoài
(trên đĩa cứng hay đĩa mềm…), khi kết thúc chương trình hay khi tắt máy thì dữ liệu
vẫn còn nên có thể sử dụng nhiều lần.
Trong Pascal, tập tin có 3 loại: tập tin định kiểu, tập tin văn bản và tập tin tổng
quát.
II. TẬP TIN ĐỊNH KIỂU
1. Khai Báo
Khai báo gián tiếp
Type TAPTINKYTU = FILE OF CHAR;
Var fc: TAPTINKYTU;
Khai báo trực tiếp
Var fc: FILE OF CHAR;
Kiểu của tập tin có thể là bất kỳ một kiểu dữ liệu nào, trừ chính bản thân nó,
nghĩa là không có tập tin của tập tin.
2. Truy Xuất Các Phần Tử Của Tập Tin
Muốn truy xuất một phần tử của tập tin ta phải có một biến trung gian, kiểu của
biến trung gian này phải tương tích với kiểu của các phần tử trong tập tin. Biến trung
gian này gọi là con trỏ tập tin. Mỗi tập tin có một con trỏ tập tin riêng. Con trỏ tập tin
có thể di chuyển trong toàn bộ tập tin và khi con trỏ tập tin ở tại phần tử nào thì ta chỉ
có thể truy xuất tại vị trí đó mà thôi. Như vậy, mỗi lần chỉ có thể truy xuất được một
phần tử. Muốn truy xuất phần tử nào thì con trỏ tập tin phải di chuyển đến phần tử đó.
Có hai cách để di chuyển con trỏ tập tin là di chuyển tuần tự từ đầu đến cuối tập
tin hoặc di chuyển trực tiếp từ phần tử này sang phần tử khác bất kể hai phần tử đó có
kế tiếp nhau không.
3. Các Thủ Tục Và Hàm Trên Tập Tin
Ta dùng chữ FileVar để chỉ biến kiểu tập tin. Trong những thủ tục và hàm trình
bày ở chương này, có một số cũng được sử dụng cho tập tin văn bản, các hàm và thủ
tục đó sẽ có dấu * sau đề mục để người đọc tiện theo dõi.
Cú pháp: = FILE OF ;
Trang 17
a. Thủ tục ASSIGN(FileVar, FileName)*
FileName là tên của tập tin do đó phải tuân thủ qui cách đặt tên của MS-DOS.
Tổng quát FileName là một PathName để dẫn đường truy xuất một tập tin trên đĩa từ.
Lệnh này dùng để gán tên tập tin FileName vào biến tập tin FileVar. Sau lệnh
này mọi thao tác trên FileVar thực tế là thao tác trên tập tin FileName trên đĩa từ.
Ví dụ:
Var fc: FILE OF CHAR;
Assign(fc, ‘A:\VanBan.txt’);
b. Thủ tục REWRITE(FileVar)*
Tạo mới trên đĩa từ tập tin có tên là FileName (đã được khai báo trong lệnh
Assign). Nếu FileName đã có thì nội dung của nó bị xoá và con trỏ tập tin đặt ở đầu
tập tin. Như vậy sau lệnh này trên đĩa từ sẽ có tập tin là FileName với nội dung rỗng.
Thông tin mới sẽ được đưa vào nhờ lệnh Write sẽ được đề cập sau.
c. Thủ tục RESET(FileVar)*
Mở trên đĩa từ tập tin có tên là FileName (đã được khai báo trong lệnh Assign).
Con trỏ tập tin đặt ở đầu tập tin. Thông tin sẽ được đọc ra nhờ lệnh Read sẽ được đề
cập sau.
d. Thủ tục WRITE(FileVar, x1, x2,…, xn)
Các biến x1, x2,…, xn phải thuộc kiểu phần tử của FileVar. Lệnh này cho phép
ghi thông tin mới vào tập tin có tên là FileName. Thông tin sẽ được ghi vào tại vị trí
con trỏ tập tin đang đứng, sau khi ghi xong một giá trị con trỏ tập tin sẽ chuyển đến
phần tử kế tiếp.
e. Thủ tục READ(FileVar, x1, x2,…, xn)
Các biến x1, x2,…, xn phải thuộc kiểu phần tử của FileVar. Lệnh này cho phép
đọc thông tin từ tập tin có tên là FileName. Thông tin sẽ được đọc ra tại vị trí con trỏ
gán vào các biến tương ứng. Sau khi đọc xong một giá trị con trỏ tập tin sẽ chuyển đến
phần tử kế tiếp.
f. Thủ tục SEEK(FileVar, n)
Biến n là một biến số nguyên chỉ số thứ tự của phần tử trong tập tin. Phần tử
thứ nhất có số thứ tự là 0.
Thủ tục này dịch con trỏ tập tin đến vị trí thứ n của tập tin.
g. Hàm FILEPOS(FileVar): Integer
Cho kết quả là một số nguyên chỉ vị trí hiện tại của con trỏ tập tin.
h. Hàm FILESIZE(FileVar): Integer
Cho kết quả là một số nguyên chỉ số lượng phần tử có trong tập tin. FileSize
nhận giá trị 0 khi không có một phần tử nào. Để đưa con trỏ về cuối tập tin ta có thể
dùng lệnh: Seek(FileVar, FileSize(FileVar)).
Trang 18
i. Thủ tục FLUSH(FileVar)*
Cho phép đẩy thông tin nằm trong vùng nhớ đệm của tập tin ra đĩa từ.
j. Thủ tục CLOSE(FileVar)*
Đóng tập tin lại và cập nhật thư mục để phản ánh trạng thái mới của tập tin.
k. Thủ tục ERASE(FileVar)*
Xoá tập tin trên đĩa. Chú ý: tập tin phải đóng trước khi xoá.
l. Thủ tục RENAME(FileVar, NewName)*
Đổi tên tập tin thành NeưName. NewName là một chuỗi ký tự theo qui tắc đặt
tên tập tin (tổng quát là một PathName).
m. Hàm EOF(FileVar): Boolean*
Cho kết quả là True nếu con trỏ tập tin ở cuối tập tin. Người ta dùng hàm này
để kiểm tra tình trạng hết tập tin hay chưa.
4. Kiểm Tra Tập Tin Khi Mở
Có một vài điều ta cần chú ý khi làm việc với tập tin, như các trường hợp nêu ra
dưới đây.
- Ta dùng thủ tục RESET để mở một tập tin phải có trên đĩa. Nếu trên thực tế, tập
tin này không có trên đĩa thì Pascal sẽ báo lỗi “File not found” và ngừng thực
hiện.
- Khi chúng ta dùng lệnh REWRITE để tạo mới một tập tin lên đĩa. Nếu tập tin ta
tạo trùng tên với một tập tin đã có trên đĩa, thì nội dung của tập tin cũ bị xoá
hết.
Để khắc phục trình trạng trên, ta sử dụng hướng biên dịch của Pascal, kiểm tra
vào/ra bằng hàm IOResult.
- {$I+} Mở kiểm tra, khi có lỗi vào/ra thì chương trình sẽ báo lỗi và dừng thực
hiện.
- {$I-} Tắt kiểm tra tồn tại của tập tin để thông báo lỗi.
- Hàm IOResult: Word. Hàm này dùng để kiểm tra lỗi vào/ra và cho kết quả là
một số nguyên kiểu Word. Ta thường dùng hàm này để kiểm tra một tập tin có
tồn tại trên đĩa hay không, hàm IOResult được kiểm tra sau lệnh Reset, nếu
hàm trả về 0 thì tập tin đã có trên đĩa, ngược lại tập tin chưa tồn tại trên đĩa.
File đính kèm:
Lập trình Pascal - Chương 6_Kiểu mảng.pdf

