NGÔN NGỮ LẬP TRÌNH PASCAL 2
(03 đơn vị học trình)
Mục đích, yêu cầu
• Cung cấp kiến thức về NNLT Pascal với cấu trúc dữ liệu nâng cao.
• Sử dụng phần mềm Turbo Pascal lập trình giải các bài toán giúp cho việc học
tập, nghiên cứu và giảng dạy.
Nội dung
C7: Kiểu Set (tập hợp)
C8: Kiểu Record (bản ghi)
C9: Kiểu File (tệp)
C10: Kiểu Pointer (con trỏ)
Tài liệu tham khảo
1. Nguyễn Quý Khang, Kiều Văn Hưng, Bài tập Pascal (tập 1), NXB ĐHQG
Hà Nội, 2002 (hoặc Bài tập Pascal, ĐHSP Hà Nội 2).
2. Quách Tuấn Ngọc, Ngôn ngữ lập trình Pascal, NXBGD, 1996.
3. Bùi Thế Tâm, Văn Văn Tuấn Dũng, Turbo Pascal 7.0, NXB Thống kê, 1996.
Hình thức thi, kiểm tra
Thi trắc nghiệm lý thuyết + Lập trình trên máy.
1
Chương 7
KIỂU SET (TẬP HỢP)
7.1 KHÁI NIỆM VÀ KHAI BÁO
Khái niệm, biểu diễn tập hợp
• Kiểu tập hợp (set) trong Pascal là một tập của những dữ liệu thuộc một kiểu vô hướng đếm
được (số nguyên, kí tự, logic, đoạn con, liệt kê).
Với TP, một tập hợp có số phần tử từ 0..256 và giá trị các số từ 0..255.
• Biểu diễn tập hợp: liệt kê các phần tử trong cặp ngoặc vuông.
[1, 2, 6, 9] (số phần tử: 4)
['A', 'a'..'z'] (số phần tử: 27)
[] (số phần tử: 0, tập rỗng)
Khai báo
• Khai báo kiểu tập hợp
TYPE KieuTH = Set of KieuCS;
trong đó
KieuTH: từ tự đặt xđ kiểu tập hợp;
KieuCS: kiểu dữ liệu của phần tử.
• Khai báo biến tập hợp
Cách 1 (khai báo trực tiếp biến tập hợp)
VAR BienTH : Set of KieuCS;
Cách 2 (khai báo gián tiếp)
VAR BienTH : KieuTH;
(Tham số hình thức của CTC phải dùng
Cách 2)
2
VD 7.1 (khai báo kiểu, biến tập hợp)
TYPE {Khai bao kieu tap hop}
SoNguyen = Set of Byte;
ChuHoa = Set of 'A' .. 'Z';
VAR {Khai bao bien tap hop}
so : SoNguyen;
chu : ChuHoa;
kt : Set of Char;
Chú ý
(i) Vị trí của các phần tử trong tập hợp không có ý nghĩa ([1, 2] = [2, 1]).
(ii) Dùng lệnh gán để thay đổi giá trị cho các biến tập hợp.
(iii) Không dùng lệnh Read và Write trực tiếp cho dữ liệu kiểu tập hợp.
TH := TH + [pt]; {Thêm pt}
if pt in TH then Write(pt); {Viết pt}
7.2 CÁC PHÉP TOÁN
Phép hợp (+), giao (*), hiệu (-), bao hàm (IN): giống như trong toán học.
A := [1, 3]; B := [2, 3, 4]
A + B = [1, 2, 3, 4]; A * B = [3];
A - B = [1]; B - A = [2, 4];
2 in A FALSE
Phép so sánh (=, <>, <=, >=): kết quả có kiểu logic (TRUE/FALSE).
A <= B có KQ là TRUE nếu A là tập con của B, trái lại KQ là FALSE.
A >= B có KQ là TRUE nếu A bao hàm tập B, trái lại KQ là FALSE.
Không có phép so sánh < và > trên kiểu tập hợp trong Pascal.
7.3 VÍ DỤ
3
VD 7.2 (Phân loại kí tự) Lập trình nhập vào một kí tự. Kiểm tra xem kí tự đó chữ cái, chữ số
hay kí tự khác?
Hướng dẫn: khai báo biến ch kiểu Char và 2 biến ChuCai, ChuSo kiểu tập hợp kí tự, rồi gán giá
trị:
ChuCai := ['A'..'Z', 'a'..'z']
ChuSo := ['0'..'9']
Nếu ch in ChuCai thì viết "là chữ cái".
Nếu ch in ChuSo thì viết "là chữ số".
Nếu ... thì viết "kí tự khác".
VD 7.3 (Bán vé máy bay, BT 6.9, tr. 187) Một máy chứa tối đa 250 hành khách, với các ghế
được đánh số 1, 2, ..., 250. Lập trình bán vé máy bay, yêu cầu hiện lên các số ghế còn trống để
khách lựa chọn.
Hướng dẫn: Tạo tập V = [1..250] tương ứng với số ghế trên các vé và liệt kê chúng ra màn
hình.
Dùng vòng lặp không xác định để nhập số ghế mà hành khách chọn. Một số ghế đã
chọn thì số đó không còn trong V và trên màn hình.
Chương 8
KIỂU RECORD (BẢN GHI)
8.1 KHÁI NIỆM VÀ KHAI BÁO
Khái niệm
4
• Kiểu bản ghi (Record) là một kiểu dữ liệu có cấu trúc gồm nhiều thành phần và được gọi là
field - trường.
Mỗi trường được đặt tên và các trường có thể có các kiểu dữ liệu khác nhau.
• Kiểu bản ghi dùng để mô tả các đối tượng có cùng một số thuộc tính mà các thuộc tính có
thể có kiểu dữ liệu khác nhau.
Chẳng hạn, bảng kết quả thi TSĐH gồm thông tin về các thí sinh như: họ tên, SBD, ngày sinh,
giới tính, điểm môn 1, 2, 3, ... mà các thông tin này thuộc các kiểu dữ liệu khác nhau.
Khai báo
• Khai báo kiểu bản ghi
TYPE KieuBG = RECORD
T1 : K1;
...
Tn : Kn;
END;
trong đó
KieuBG: từ tự đặt xđ tên kiểu bản ghi;
T1, ... Tn: tên các trường;
K1, ... Kn: kiểu dữ liệu của các trường.
• Khai báo biến bản ghi
Cách 1 (khai báo trực tiếp biến bản ghi)
VAR BienBG : RECORD
T1 : K1;
...
Tn : Kn;
END;
5
Cách 2 (khai báo gián tiếp)
VAR BienBG : KieuBG;
(Tham số hình thức của CTC phải dùng
Cách 2)
VD 8.1 (khai báo kiểu, biến bản ghi)
TYPE {Khai bao kieu ban ghi}
HSTS = RECORD
hoten : String[25];
sbd : String[8];
ngaysinh : String[10];
gt : Boolean;
mon1, mon2, mon3,
tong : Real;
KQ : String[10];
END;
HSCB = RECORD
hoten : String[25];
ngaysinh : String[10];
chucvu : String[15];
Luong : Real;
Ghichu : String[10];
END;
VAR {Khai bao bien ban ghi}
ts : HSTS;
cb : HSCB;
sv : Record
hoten : String[25];
lop : String[5];
tuoi : Byte
dtb: Real;
End;
6
8.2 SỬ DỤNG RECORD
Lệnh gán 2 biến Record cùng kiểu
A := B;
Chỉ được phép truy nhập tới các trường của biến Record
BienBG.Truong
Các thao tác truy nhập:
- Nhập: Readln(BienBG.Truong);
- Xuất: Write(BienBG.Truong);
- Gán trị: BienBG.Truong := ... ;
Chú ý
(i) Không dùng thủ tục Read, Readln, Write, Writeln cho một biến Record.
Write(bg); {SAI !}
Readln(bg) {bg - biến Record}
(ii) Không dùng các phép toán số học, logic, so sánh (= , <>, >, >=, <, <=) đối
với các biến Record.
VD 8.2 (Dùng sai đối với biến Record).
Type
HSSV = record
hoten:string[20];
dtb:real;
end;
var s1, s2: HSSV;
begin
s1.hoten:= 'Mot'; s1.dtb:= 1.1;
s2.hoten:= 'Hai'; s2.dtb:= 2.2;
if (s1=s2) then writeln('s1 = s2')
else
writeln('SV1 khac SV2!');
7
Readln;
end.
VD 8.3 (Khoảng cách giữa 2 điểm) Lập trình nhập vào toạ độ 2 điểm A(xA, yA), B(xB, yB)
trong hệ toạ độ đềcác. Tính d(A, B).
Hướng dẫn:
- Khai báo 2 biến A, B kiểu Record với 2 trường x, y (kiểu thực).
- Tính d(A, B) theo công thức:
Sqrt(Sqr(xA-xB) + Sqr(yA-yB))
VD 8.4 (Xếp loại học bổng) Lập trình nhập vào danh sách N sinh viên (N < 1000) với các thuộc
tính họ tên, ngày sinh, lớp, điểm trung bình mở rộng, học bổng. Xếp loại học bổng cho các SV
theo quy định hiện hành và in kết quả ra màn hình.
Hướng dẫn:
- Khai báo 1 biến SV kiểu mảng Record, mỗi phần tử của mảng lưu trữ thông tin cho
một SV.
- Nhập N và dùng lệnh FOR để nhập thông tin của mỗi SV gồm họ tên, ngày sinh, lớp,
điểm trung bình mở rộng vào biến SV, đồng thời dùng lệnh IF để gán trị cho trường
học bổng.
- Dùng lệnh FOR để in DS ra màn hình.
Lệnh WITH ... DO
WITH BienBG DO
begin
T1:= ...;
Readln(T2);
...
Write(Tn);
end;
8
truy nhập đơn giản tới các trường (T1, ..., Tn) của biến bản ghi (BienBG).
VD 8.4 (tiếp) Lập trình dùng With ... do ...
8.3 RECORD CÓ CẤU TRÚC THAY ĐỔI (Tham khảo [3], tr. 140)
Chương 9
KIỂU FILE (TỆP)
9.1 CẤU TRÚC VÀ PHÂN LOẠI TỆP
9
Khái niệm về tệp
• Tệp (File, tập tin, hồ sơ) dữ liệu là một tập hợp các dữ liệu có liên quan với nhau, có cùng
kiểu được tổ chức thành dãy, và được lưu trữ ở bộ nhớ ngoài (đĩa, băng từ).
Mỗi ô là 1 phần tử của tệp
EOF
• Tệp dùng để lưu trữ dữ liệu: dữ liệu trong tệp được dùng nhiều lần và tồn tại cả khi kết
thúc chương trình hay mất điện (khác với các kiểu mảng, xâu, bản ghi,...).
• Các loại tệp trong TP: tệp văn bản (TEXT file), tệp định kiểu (Typed file), tệp không định
kiểu (Untyped file).
Khai báo kiểu và biến tệp
• Khai báo kiểu tệp
TYPE
KieuTep = FILE OF KieuPT;
trong đó KieuTep là một từ tự đặt xác định kiểu tệp, KieuPT là kiểu dữ liệu của phần tử
(Real, String, Array, Record, ... trừ kiểu file).
• Khai báo biến tệp
Cách 1: VAR BienTep : KieuTep;
Cách 2: VAR BienTep : FILE OF KieuPT;
10
VD 9.1 (khai báo kiểu, biến tệp)
TYPE {Đinh nghia cac kieu tep}
FileInteger = FILE OF Integer;
FileReal = FILE OF Real;
HosoSV= RECORD
hoten: String[25];
lop: String[5];
dtb: Real;
END;
FHosoSV = FILE OF HosoSV;
VAR {Khai bao cac bien tep}
F1, F2: FileInteger; {tep cac so nguyen}
F3: FileReal; {tep cac so thuc}
g: FHosoSV; {tep cac ban ghi}
F4: Text; {tep van ban}
F5: File; {tep khong đinh kieu}
F6: FILE OF Char; {tep cac ki tu}
Cấu trúc và phân loại tệp
• Các phần tử của ARRAY hay RECORD được truy nhập ngẫu nhiên thông qua tên biến và
chỉ số / tên trường.
Một phần tử của tệp được truy nhập thông qua giá trị của một biến đệm (tampon
variable). Biến đệm được dùng để đánh dấu vị trí truy nhập hay còn gọi là cửa sổ
(window) của tệp.
• Có lệnh để di chuyển cửa sổ tệp sang vị trí khác (Reset, Seek, ...).
• Mỗi tệp có một dấu hiệu kết thúc tệp - EOF (End of File).
Hàm chuẩn EOF(f) trả về TRUE nếu cửa sổ ở vị trí dấu hiệu kết thúc tệp f, trái lại hàm
trả về FALSE.
Mỗi ô là 1 phần tử của tệp
Chỉ số ptử 0 1 2 ...
Các ptử EOF
• Phân loại tệp theo bố trí các phần tử và cách truy nhập tệp: tệp truy nhập tuần tự
(sequential access), tệp truy nhập trực tiếp (direct access).
- Tệp truy nhập tuần tự: việc đọc một phần tử bắt buộc phải tuần tự đi qua các phần
tử trước đó. Ghi một phần tử phải ghi vào sau phần tử cuối tệp.
11
Cửa sổ tệp
- Tệp truy nhập trực tiếp: để đọc/ghi, có thể đặt cửa sổ vào phần tử bất kỳ thông qua
chỉ số thứ tự của phần tử trong tệp.
- Trong Pascal chuẩn chỉ có tệp truy nhập tuần tự.
Chú ý:
(1) Sự giống/khác nhau giữa mảng và tệp
ARRAY FILE
- Tập các dữ liệu cùng kiểu
- Chứa tạm trong RAM
- Truy nhập ngẫu nhiên đến các phần tử qua chỉ số
- Số phần tử xác định khi khai báo
- Tập các dữ liệu cùng kiểu
- Lưu trữ trên đĩa, băng từ
- Truy nhập ngẫu nhiên hay tuần tự đến các phần tử qua chỉ số
- Số phần tử không xác định khi khai báo
(2) Biến tệp đại diện cho một tệp. Việc truy xuất dữ liệu trên tệp được thể hiện qua
các lệnh với thông số là biến tệp.
9.2 CÁC THAO TÁC CƠ BẢN TRÊN TỆP
Mở tệp mới để ghi dữ liệu
• Mở tệp để ghi
ASSIGN(BienTep, TenTep);
REWRITE(BienTep);
trong đó BienTep là một biến kiểu tệp; TenTep là một xâu kí tự xác định tên của tệp
(quy tắc đặt tên tệp theo quy định của hệ điều hành).
VD 9.2 (mở tệp mới để ghi)
ASSIGN(f, ’HOSOSV.DAT’);
REWRITE(f);
Gán tên tệp HOSOSV.DAT cho biến tệp f, trên đĩa sẽ có tệp HOSOSV.DAT (ở thư mục
hiện tại).
Chú ý:
- Khi mới mở, tệp sẽ rỗng (chưa có phần tử nào).
- Khi mở tệp, nếu trên đĩa đã có tệp trùng tên với tệp được mở thì dữ liệu tệp cũ sẽ
mất.
12