Trong Pascal tồn tại các kiểu dữ liệu có cấu trúc làcác kiểu dữ liệu được tạo ra từ các phần tử có kiểu dữ liệu đơn giản bằng một cách nào đó.Chúng được đặc trưng bằng kiểu dữ liệu của c
Trang 1DỮ LIỆU KIỂU MẢNG
I MẢNG MỘT CHIỀU
1 Khái niệm chung về cấu trúc dữ liệu:
Chúng ta đã làm quen với các kiểu dữ liệu đơn giản là các kiểu vô hướng (Integer, Char,Boolean, Real, kiểu liệt kê) và đoạn con Trong Pascal tồn tại các kiểu dữ liệu có cấu trúc làcác kiểu dữ liệu được tạo ra từ các phần tử có kiểu dữ liệu đơn giản bằng một cách nào đó.Chúng được đặc trưng bằng kiểu dữ liệu của các phần tử và quan trọng hơn cả là phươngpháp cấu thành kiểu dữ liệu mới (điều đó cũng có nghĩa là phương pháp truy nhập vào kiểu
dữ liệu có cấu trúc) Tính có cấu trúc của dữ liệu là một đặc trưng của ngôn ngữ lập trình cócấu trúc
Pascal có tất cả 4 kiểu dữ liệu có cấu trúc mà chúng ta sẽ lần lượt ngiên cứu : mảng
(Array), tập (Set), bản ghi (Record) và tệp (File)
2 Kiểu dữ liệu có cấu trúc : Mảng (Array)
Một mảng dữ liệu gồm một số hữu hạn phần tử có cùng kiểu gọi là kiểu cơ bản Số phần
tử của mảng được xác định ngay từ khi định nghĩa ra mảng Mỗi phần tử của mảng đựoctruy nhập trực tiếp thông qua tên mảng cùng với chỉ dẫn truy nhập được để giữa hai ngoặcvuông [ ]
Định nghĩa kiểu mảng T có kiểu các phần tử là KPT, có kiểu chỉ dẫn KCD để hướng dẫncách tổ chức mảng cũng như cách truy nhập vào các phần tử mảng được viết trong Pascalnhư sau :
Trang 2MC : Array[ 'A' 'Z' ] Of Integer ;
MM : Array[ Color ] Of Boolean ;
AI, AC là hai kiểu mảng gồm 10 phần tử được đánh số thứ tự từ 1 đến 10 thông qua kiểuchỉ dẫn là một đoạn con các số nguyên 1 10 Các phần tử của AI có kiểu là số nguyên còncác phần tử của AC có kiểu là các kí tự A, B, C là các biến có kiểu là AI
Còn M1, M2 là hai biến được định nghĩa kiểu luôn khi khai báo Đây là hai biến mảnggồm 9 phần tử là các số thực, được đánh số từ -3 đến 5
MC là một biến mảng gồm 26 số nguyên được đánh số qua các chỉ dẫn là các chữ cái từ'A' đến 'Z'
MM là một mảng gồm 5 phần tử kiểu Boolean, các phần tử đựoc đánh dấu qua chỉ dẫn làtên của 5 màu sắc
Một điều lưu ý là khi khai báo mảng, kiểu chỉ dẫn chí có thể là các kiểu đơn giản nhưsau: kí tự ( như biến MC ), đoạn con ( ví dụ đoạn con Integer như các kiểu AI, AC ), kiểuliệt kê do người sử dụng định nghĩa (như biến MM) và kiểu Boolean Kiểu chỉ dẫn khôngđược là kiểu Real hoặc Integer Nghĩa là không được viết :
X : Array[ Integer ] Of Integer ;
Y : Array[ Real ] Of Integer ;
Việc truy nhập vào một phần tử nào đó của mảng được thực hiện qua tên biến mảng, theosau là giá trị chỉ dẫn để trong ngoặc vuông như :
Trang 3Write (' B[ ', I, ' ] = ') ;
Readln ( B[ I ] ) ;
End ;
Kết quả thể hiện ra màn hình với các con số là do người sử dụng gõ vào :
Vao so lieu cho mang B
Write (' Vao so lieu hang 1 ') ;
Readln ( B[1], B[2], B[3], B[4], B[5] ) ;
Kết quả hiện ra màn hình :
Vao so lieu hang 1 : 2 12 612 2 34
Giữa các số gõ là các dấu cách với số lượng tùy ý nhưng ít nhất phải là 1
Giả sử ta muốn đếm trong 100 lần gõ kí tự vào qua bàn phím, số lần xuất hiện các kí tự
từ 'A' đến 'Z' là bao nhiêu Biến MC được khai báo dưới đây đóng vai trò là bộ đếm,biến kí tự Ch được dùng như là biến chỉ dẫn
Trang 4Giả sử ta có một dãy dữ liệu ( số thực, số nguyên, kí tự ) được chứa trong một mảng.Sau đây là một số vì dụ về một số phương pháp xếp mảng các số nguyên Việc các phần tửmảng là các số nguyên chỉ là một ví dụ, nó có thể là mảng các số thực hoặc mảng các xâu
kí tự
Cách làm:
Đầu tiên đem phần tử thứ nhất so sánh với các phần tử tiếp theo, nếu nó lớn hơn thì đemđổi chỗ giá trị của hai phần tử so sánh Kết quả sau lượt đầu tiên giữ giá trị nhỏ nhất Tiếptheo vòng 2, Đem phần tử thứ 2 so sánh với các phần tử tiếp theo
Trang 5T : Integer ; (* T là biến trung gian *)
I, J : Integer ;
BEGIN
(* Đọc các số cần sắp xếp vào mảng MI *) For I := 1 To N Do
Writeln ( ' Sau khi sap xep ' ) ;
For I := 1 To N Do Writeln ( MI[ I ] : 6 ) ; END
Trang 6II MẢNG HAI CHIỀU:
Kiểu phần tử của mảng không bị hạn chế nhiều như kiểu chỉ dẫn Nó còn có thể là cáckiểu có cấu trúc Ví dụ sau cho thấy việc khai báo một mảng có các phần tử cũng là mảng
Z : Array [ 1 3, 'A' 'C' ] Of Color ;
hoặc viết một lần như sau :
MPT được định nghĩa như trên chính là ma trận hai chiều 3 hàng và 5 cột
Việc truy nhập đối với mảng có định nghĩa phức tạp như MPT được tiến hành qua hai lần
đóng mở ngoặc vuông Ví dụ MPT [3] [5] hoặc MPT [ 3, 5 ] biểu diễn phần tử ở hàng 3 và
Trang 7(* In kết quả theo kiểu viết ma trận *)
Writeln (' Tich cua hai ma tran = ') ;
Trang 8Một cách khác lười hơn đỡ phải đọc ma trận trong khi thử, hãy làm một đoạn chươngtrình tạo số ngẫu nhiên cho các phần tử của ma trận Bạn cần nhớ lại hoặc tra cứu hàm
Random và Randomize
Mảng có thể dùng làm tham số cho chương trình con và mảng không bao giờ dùng làmkết quả của Function Tuy nhiên cần lưu ý khai báo kiểu của tham số trong vùng khai báoType chứ không định nghĩa trực tiếp ngay trong phần khai báo tham số của chương trìnhcon
Trang 9DỮ LIỆU KIỂU XÂU
Các chương trình dịch Pascal hiện nay đã có một kiểu dữ liệu mới là xâu kí tự để xử lýcác chuỗi, các dãy kí tự có độ dài thay đổi nhằm đáp ứng nhu cầu xử lý văn bản, xử lý từ(ngữ) Một xâu kí tự được định nghĩa bằng từ khóa String theo sau là số kí tự cực đại có thể
có của xâu kí tự, được đặt trong ngoặc vuông :
String [ do_dai_cuc_dai ] ;
Ví dụ 1:
Var Filename : String[20] ;
Line : String[80] ; (* Dòng 80 kí tự là nhiều nhất *)
Ví dụ 2: Biến Filename khai báo ở trên được gán giá trị :
Truy nhập vào các phần tử của xâu kí tự : ta có thể truy nhập vào từng kí tự một của xâu
kí tự với tên biến và chỉ số đặt trong ngoặc vuông như khik truy nhập vào phần tử củamảng Chỉsố này có thể chạy từ 1 đến độ dài cực đại của xâu kí tự
If filename[3] = 'D' then
Writeln (' Chu thu ba cua xau ki tu la D ') ;
Nếu vị trí kí tự đó nằm ngoài độ dài thực của xâu kí tự thì phần tử đó của xâu không cógiátrị xác định Vì vậy, khi truy nhập vào từng phần tử của xâu chữ, ta còn cần phải kiểmtra xem vị trí đó có nằm trong khoảng độ dài thực của xâu hay không
If 3 < Length(Filename) then
Writeln (' Chu thu ba cua Filename la : ', Filename[3]) ;
Trang 10Cho kết quả của Filename là : ' C:\Vidu.pas ' ;
hoặc Filename := ' Ten ' + ' file ' + '.pas ' ;
Cho kết quả của Filename là : ' Tenfile.pas ' ;
Rõ ràng với kiểu mảng kí tự , chúng ta không thể thực hiện được phép cộng để ghép haimảng với nhau vì độ dài của chúng đã cố định
* Lưu ý: không có phép tính trừ, nhân, chia cho xâu kí tự.
2 Khai báo String làm tham số chương trình con :
Tương tự Array , String có thể dùng làm tham số cho chương trình con ,
Cách viết sau đây là sai :
Function Vidusai : String[20] ;
Procedure Vidusai (St : String[30]) ;
Khi dùng String làm tham số cho chương trình con , độ dài của tham số thực phải bằng
độ dài của tham số hình thức Vì vậy lời gọi thủ tục sau là đúng hoàn toàn :
Vidu2(Ten30) ;
vì Ten30(tham số thực) có kiểu là St30 trùng với tham số hình thức (St30).
Tuy vậy , bạn có thể chuyển tham số String có độ dài khác vào chương trình con bằngcách hướng dẫn chương trình dịch không kiểm tra tính tương thích về độ dài Cách làm :
định hướng {$V-}sẽ bỏ việc kiểm tra tính tương thích về độ dài của tham số xâu kí tự và {$V+} sẽ làm hoạt động việc kiểm tra trở lại.
Ví dụ: Lời gọi Vidu2(Ten20) sẽ gây ra lỗi vì Ten20 có độ dài khác St30 Muốn khắc
phục điều này , ta chỉ cần thêm định hướng {$V-} :
Trang 11Có thể dùng Write(St) hay Writeln(St) cho một xâu kí tự St.
Read(St) hay Readln(St) sẽ đọc các kí tự cho xâu St với độ dài thực là số kí tự gõ vào từ
bàn phím
4 Các thủ tục và hàm chuẩn xử lý xâu kí tự:
_ Length(St) là hàm cho ta độ dài của xâu St.
Ví dụ: với St := 'Filename' ; thì Length(St) có giá trị bằng 8
_ Delete(St , Pos , Num) là thủ tục xóa đi một số kí tự Num kể từ vị trí Pos trong xâu St.
Ví dụ : Sau khi gọi Delete (St , 2 , 3) ; St sẽ còn ' Fname ' vì bị xóa đi 3 kí tự ' ile ' NếuPos + Num > Length (St) thì St sẽ bị xóa toàn bộ kí tự kể từ vị trí Pos
_ Insert(Obj , St , Pos) là thủ tục xen xâu kí tự Obj vào xâu St tại vị trí Pos.
Ví dụ: Sau khi gọn Insert(' 12 ' , St , 4) ; thì St sẽ thành ' Fil12ename ' Nếu Length
(Obj) + Length (St) vượt quá độ dài cực đại cho phép thì chỉ những kí tự nào nằmtrong khoảng độ dài cực đại cho phép mới được giữ lại
_ Str(Value , St) là thủ tục biến đổi giá trị bằng số nguyên hoặc thực Value thành một
dãy kí tự biểu diễn số đó
Ví dụ: I là biến kiểu số nguyên , X là biến kiểu số thực :
I := 512 ;
Str(I : 5 , St) ; sẽ cho ra St là ' 512 ' (* 5 kí tự *)
X := 123.4567890 ;
Str(X : 12 : 5 , St) ; cho ra St là ' 123.45678 ' (* 12 kí tự *)
_ Val(St , Var1 , Code) là thủ tục biến đổi một xâu kí tự St (biểu diễn một số nguyên
hoặc thực) thành một số nguyên hoặc thực chứa trong Var1 Code là số nguyên đểphát hiện lỗi
Ví dụ:
St1 := ' 123.45 ' ;
St2 := ' 123X ' ;
Trang 12Val (St1 , Var1 , Code1) ; cho ta Var1 = 123.45 và Code1 = 0 ;
Val (St2 , Var2 , Code2) ; cho ta Var2 không xác định và Code2 = 4 ;
Lưu ý : Các biến Var1 , Var2 , Code1 , Code2 đều phải được khai báo trước
_ Copy(St , Pos , Size) nhận Size kí tự trong St từ vị trí Pos.
Ví dụ:
St := ' 12345678 ' ;
St1 := Copy (St , 3 , 2) ; sẽ cho St1 = ' 34 ' ;
Nếu Pos > Length (St) thì Copy sẽ cho một xâu rỗng
Nếu Pos + Size > Length (St) thì Copy sẽ chỉ nhận các kí tự nằm trong xâu St
_ Concat(St1 , St2 , , StN) là hàm ghép nối tất cả các xâu kí tự St1 , St2 , , StN
thành một xâu kí tự theo thứ tự đã viết Tất nhiên , nếu tổng chiều dài của tất cả cácxâu kí tự lớn hơn 255 thì máy sẽ báo lỗi
_ Pos(Obj , Target) là hàm cho ta vị trí đầu tiên của xâu Obj gặp trong xâu Target Nếu
không tìm thấy , Pos có giá trị bằng 0
Ví duï : Nếu St = ' 123454545 ' và Obj = ' 45 ' thì
Pos (Obj , St) cho giá trị bằng 4
Pos (' 4X ' , St) cho giá trị bằng 0 vì không tìm thấy
Trang 13
DỮ LIỆU KIỂU BẢN GHI
I KHÁI NIỆM VÀ ĐỊNH NGHĨA:
1 Khái niệm và định nghĩa:
Chúng ta đã học về các kiểu cấu trúc dữ liệu như mảng (Array), kiểu tập hợp (Set) Cáckiểu cấu trúc dữ liệu này đều được tạo ra bằng một tập hợp các phần tử có cùng (mô tả),
kiểu.Ví dụ: các phần tử của một array[1 100] of Integer là các số nguyên (Integer)
Để 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 nhưng
có liên kết với nhau, người ta định nghĩa ra bản ghi hay còn gọi là Thẻ ghi, Phiếu ghi
(tiếng Anh là Record) Nói một cách khác, để mô tả các kiểu khác nhau, chúng ta phải dùng
cấu trúc kiểu Record Như vậy Record là một phương tiện linh hoạt nhất để xây dựng các
kiểu dữ liệu mới
Cấu trúc dữ liệu Record được gắn liền với cấu trúc dữ liệu kiểu Tệp (File) (sẽ được trìnhbày ở chương sau) để lưu trữ dữ liệu Không giống một số ngôn ngữ bậc cao khác nhưFortran , ngôn ngữ Pascal còn cho phép Record có thể được mô tả và sử dụng một cách độclập với File
Để mô tả một kiểu T có cấu trúc Record với danh sách các trường có tên là S1 , S2 , ,
Sn và có các mô tả kiểu trường tương ứng là T1 , T2 , , Tn , ta có thể viết tổng quát sau :
Ví dụ 1: Một địa chỉ bao gồm các dữ liệu như số nhà, tên phố, thành phố Ta mô tả
Record Dia_chi như sau :
Như vậy chúng ta có 3 trường là So_nha, Pho và Thanh_pho với kiểu khác nhau
(integer, string[20], string[15]) và chúng được liên kết lại với nhau để mô tả địa chỉ
Ví dụ 2 : Để mô tả thời gian Date, ta có 3 trường : Ngày, Tháng và Năm
Type
Date = Record
Ngay : 1 31 ;
Thang : 1 12 ;
Trang 14Ví dụ 3: Để miêu tả nhân sự hay phiếu cán bộ của phòng tổ chức, ta phải dùng các
trường Họ tên, Ngày sinh, Chỗ ở, Lương Ở đây ta ví dụ với 5 trường Giả sử
ta đã có mô tảù kiểu Date và Dia_chi như ở trên.
Thí dụ 3 cho ta thấy điểm đặc biệt là việc mô tả lồng nhau của cấu trúc dữ liệu Trong mô
tả RECORD của nhân sự, ta có thể mô tả các phần tử (các trường) của Record là một kiểuRecord khác như các trường Ngày sinh và chỗ ở Mức lương được mô tả là Real (số thực)
Trang 15II SỬ DỤNG RECORD:
Để thâm nhập vào môi trường của Record , ta cần phải dùng tên biến kiểu Record, sau đódấu chấm (.) và tên trường của Record
Ví dụ 4: Với mô tả kiểu được nêu ở trên, ta tiếp tục khai báo tên biến và thực hiện 1 đoạn
chương trình để đọc dữ liệu vào các biến như sau :
Var
Nguoi_1, Nguoi_2, Nhan_su ;
Ta thấy muốn thâm nhập vào trường Ho_ten của biến Nguoi_1, ta phải viết Nguoi_1.Ho_ten Ở đây Nguoi_1 là tên biến kiểu nhân sự và Ho_ten là tên thường Nguoi_1.Ho_ten là một biến kiểu String[30] Còn Nguoi_1.O_tai Pho cho ta thâm nhập vào trường Pho của trường O_tai của biến Nguoi_1 Trong đó O_tai có mô tả kiểu Dia_chi.
Dòng lệnh nguoi_2 := Nguoi_1 cho phép ta copy 2 biến với nhau Thực chất dòng lệnh
này là việc thâm nhập vào cả một biến kiểu Record chứ không phải là việc thâm nhập vào
môi trường riêng lẻ nào đó của biến Record đó (là Nguoi_1 và Nguoi_2 ở đây).
Ta có thể dùng phép so sánh :
If Nguoi_1 = Nguoi_2 then writeln ('Cung mot nguoi!) ;
hoặc :
If Nguoi_2.Ho_ten = Nguoi_1.Ho_ten then writeln (hai nguoi trung ten nhau!)
Tuy nhiên cần lưu ý là không thể dùng các thao tác sau :
_ Viết ra màn hình hoặc đọc từ bàn phím cả một biến kiểu Record như :
_ Readln (Nguoi_1) hoặc Writeln (Nguoi_1) ;
_ So sánh các Record bằng các phép toán quan hệ như sau : < , > , <= , >= Riêng cácphép so sánh <> (khác nhau) và = (bằng nhau) thì có thể được dùng với hai biến có cùngmột kiểu Record
Canbo : Array[1 100] Of Nhan_su ;
TG : Nhan_su ; (* Ô nhớ trung gian *)
I , J : integer ;
Trang 16III CÂU LỆNH WITH:
Qua ví dụ trước ta thấy việc thâm nhập vào các trường của một biến kiểu Record là
tương đối phức tạp và có phần tẻ nhạt vì phải dùng nhiều lần tên biến (Nguoi_1 trong ví dụ này) cùng với tên các trường Để đơn giản cách viết, Pascal đưa ra lệnh WITH DO xét
Với A, B đều được mô tả là Record, song B là một trường của A (ở thí dụ trên B là
Ngay_sinh, A là Nguoi_1) Ta có thể ghi gọn lại :
Trang 17Với thí dụ 3, ta có thể thâm nhập vào các trường Ngay_sinh trực tiếp như sau :
With Nguoi_1, Ngay_sinh Do
I CÁC KHÁI NIỆM - ĐỊNH NGHĨA:
Tệp hay tệp dữ liệu là một tập hợp các dữ liệu có liên quan với nhau và có cùng kiểu
được nhóm lại với nhau tạo thành một dãy Chúng thường được chứa trong một thiết bị nhớngoài của máy tính (ví dụ như đĩa mềm, đĩa cứng, băng từ ) với một cái tên nào đó
Tệp dữ liệu với dữ liệu được hiểu theo nghĩa rộng : đó có thể là chương trình, có thể là sốliệu, có thể là các dữ liệu khác như kí tự, văn bản
Tệp còn có tệp có định kiểu, tệp văn bản và tệp không định kiểu (sẽ học kĩ ở cuốichương)
Để dễ hình dung ra tệp, chúng ta hãy xem tổ chức tủ phiếu của thư viện Các dữ liệu chomột cuốn sách là tên sách, tên tác giả, giá tiền, số trang, nhà xuất bản Các dữ liệu nàyđược nhóm lại với nhau để tạo thành các tờ phiếu, mỗi tờ phiếu đóng vai trò là một phần tửcủa tệp dưới dạng một Record (bản ghi) Đây cũng là lý do gắn liền khái niệm cấu trúc dữliệu Record với cấu trúc File Các phần tử của tệp (các Record) có cùng một kiểu dữ liệu(Ví dụ các phiếu thư viện đều giống nhau ở chỗ mỗi cái đều có tên sách, tên tác giả, nhàxuất bản ) Các phiếu này được xếp lại thành một tệp (phiếu) và được để vào một ô ngănkéo nào đó với một cái tên (tên tệp) Ví dụ ngăn chữ A (tên tệp là A) là tệp các cuốn sách
Trang 18có tên bắt đầu bằng chữ A Các ngăn kéo lại được chứa trong một cái tủ Trong máy tính,một đĩa cứng hoặc một một đĩa mềm đóng vai trò là chiếc tủ
File còn được gọi là hồ sơ, là tập tin
Tệp thường được chứa trong một bộ nhớ ngoài như đĩa cứng, đĩa mềm, băng từ Điều đócũng có nghĩa là tệp được lưu trữ để dùng nhiều lần và tồn tại ngay cả khi chương trình kếtthúc hoặc mất điện Khác với các cấu trúc dữ liệu khác mà chúng ta đã học như : mảng, tậphợp, bản ghi, là các cấu trúc dữ liệu được tổ chức trên bộ nhớ trong (RAM) của máy tínhnên một khi kết thúc chạy chương trình hoặc mất điện thì các dữ liệu này cũng mất luôn Vìvậy những dữ liệu nào cần lưu trữ (như hồ sơ cán bộ, vật tư hàng hóa của kho, tín hiệuđiện ) thì ta bắt buộc phải dùng đến tệp Bên cạnh đó một số thiết bị ngoại vi như bànphím, màn hình, máy in được coi như là một tệp (xem phần tệp văn bản ở sau) Tệp cũngcòn có thể tổ chức trong bộ nhớ trong của máy song đó là những tệp tạm thời, trung gian vìchúng không lưu trữ lại được khi dừng chương trình hoặc mất điện
Tệp là một kiểu dữ liệu có cấu trúc Định nghĩa của tệp có phần nào giống mảng ở chỗchúng đều là tập hợp của các phần tử dữ liệu có cùng kiểu Song mảng được định nghĩa vàkhai báo trong chương trình với số phần tử đã xác định còn số phần tử của tệp không đượcxác định khi định nghĩa
Định nghĩa một kiểu tệp T với các phần tử có kiểu là KPT (Kiểu phần tử) được viết trong
phần mô tả kiểu với từ khóa FILE OF như sau :
FileInteger = File Of Integer ;
FileReal = File Of Real ;
FileBoolean = File Of Boolean ;
NhanSu = Record
Ten : String[ 30 ] ;
Tuoi : Byte ;
Luong : Real ;