Kiểu dữ liệu có cấu trúc là gì

Trường ðại học Nông nghiệp 1 - Giáo trình Lập trình nâng cao ..............................................................- 20 Chương 2 Các kiểu dữ liệu có cấu trúc Trong chương này không trình bày chi tiết các kiểu dữ liệu có cấu trúc ñơn giản như kiểu mảng, chuỗi. Nội dung trọng tâm của chương là kiểu bản ghi [Record] có cấu trúc thay ñổi, kiểu tệp và kiểu tập hợp. Chương này bạn ñọc cần nắm ñược các vấn ñề sau:  Cách thức ñịnh nghĩa một kiểu dữ liệu mới  Khai báo biến với các kiểu dữ liệu do người lập trình tự ñịnh nghĩa  Cách sử dụng toán tử CASE khi khai báo bản ghi có cấu trúc thay ñổi  Cách thức ghi và ñọc dữ liệu cho ba loại tệp: tệp văn bản, tệp có kiểu và tệp không kiểu, chú trọng cách ghi dữ liệu kiểu số vào tệp văn bản và lấy số liệu ra ñể xử lý  Xử dụng dữ liệu kiểu tập hợp trong lập trình Trường ðại học Nông nghiệp 1 - Giáo trình Lập trình nâng cao ..............................................................- 21 1. Dữ liệu kiểu bản ghi [record] 1.1 Khái niệm cơ bản Kiểu bố trí dữ liệu thông dụng nhất mà con người nghĩ ra là bố trí dưới dạng bảng. Bảng ñược coi là một ñối tượng [ñể quản lý hoặc nghiên cứu], bảng bao gồm một số cột và một số dòng. Số cột, dòng trong bảng phụ thuộc vào phần mềm quản lý mà chúng ta sử dụng. Trong từng cột dữ liệu có tính chất giống nhau. Các phần mềm quản trị dữ liệu như Excel, Foxpro... ñều ứng dụng khái niệm bảng và Pascal cũng không phải là ngoại lệ. ðể có ñược một bảng trước hết Pascal xây dựng nên một dòng gọi là "bản ghi", tập hợp nhiều dòng sẽ cho một bảng, mỗi bảng ñược ghi vào bộ nhớ dưới dạng một tệp. Bản ghi [Record] là một cấu trúc bao gồm một số [cố ñịnh hoặc thay ñổi] các phần tử có kiểu khác nhau nhưng liên quan với nhau. Các phần tử này gọi là các trường [Field]. Ví dụ bảng ñiểm của lớp học bao gồm các trường Hoten, Ngaysinh, Gioitinh, Lop, Diachi, Toan, Ly, Hoa,...., dữ liệu ñiền vào các trường hình thành nên một bản ghi [Record]. Có thể có những trường trong một bản ghi lại là một bản ghi, ví dụ trường Ngaysinh ở trên có thể là một bản ghi của ba trường là Ngay, Thang, Nam. Bản ghi không phải là kiểu dữ liệu ñã có sẵn trong Pascal mà do người sử dụng tự ñịnh nghĩa do ñó chúng phải ñược khai báo ở phần TYPE. Bản ghi bao gồm hai loại: * Bản ghi có cấu trúc không ñổi : là loại bản ghi mà cấu trúc ñã ñược ñịnh nghĩa ngay từ khi khai báo và giữ nguyên trong suốt quá trình xử lý. * Bản ghi có cấu trúc thay ñổi: là loại bản ghi mà cấu trúc của nó [tên trường, số trường, kiểu trường] thay ñổi tuỳ thuộc vào những ñiều kiện cụ thể. Loại bản ghi này khi khai báo thì vẫn khai báo ñầy ñủ song khi xử lý thì số trường có thể giảm ñi [so với cấu trúc ñã khai báo] chứ không thể tăng lên. ðiểm mạnh của Bản ghi là cho phép xây dựng những cấu trúc dữ liệu ña dạng phục vụ công việc quản lý, tuy vậy muốn lưu trữ dữ liệu ñể sử dụng nhiều lần thì phải kết hợp kiểu Bản ghi với kiểu Tệp. 1.2 Khai báo Kiểu dữ liệu của các trường trong Record có thể hoàn toàn khác nhau và ñược khai báo sau tên trường, những trường có cùng kiểu dữ liệu có thể khai báo cùng trên một dòng phân cách bởi dấu phảy "," . Cuối mỗi khai báo trường phải có dấu ";" . Kiểu dữ liệu Record ñược khai báo như sau: TYPE = RECORD : Kiểu; : Kiểu; ...... : Kiểu; END; Trường ðại học Nông nghiệp 1 - Giáo trình Lập trình nâng cao ..............................................................- 22 Ví dụ 2.1 Khai báo kiểu dữ liệu BANGDIEM bao gồm một số trường nhằm phục vụ việc quản lý ñiểm. TYPE BANGDIEM = RECORD Hoten: String[25]; Gioitinh: Char; Lop: String[5]; Diachi: String[30]; Toan,Ly,Hoa: Real; END; Với khai báo như trên dung lượng bộ nhớ dành cho các trường [tính bằng Byte] sẽ là: Hoten 26, Gioitinh 1, Lop 6, Diachi 31, Toan 6, Ly 6, Hoa 6. [Các trường kiểu String bao giờ cũng cần thêm 1 Byte chứa ký tự xác ñịnh ñộ dài chuỗi]. Tổng ñộ dài của Record bằng 26+1+6+31+18=82 Bytes. Có thể dùng hàm Sizeof[tên kiểu] ñể xác ñịnh ñộ dài một kiểu dữ liệu, ví dụ: Write[sizeof[bangdiem]] sẽ nhận ñược số 82 Ví dụ 2.2 Xây dựng kiểu dữ liệu quản lý hồ sơ công chức. Chúng ta sẽ tạo ra bốn kiểu dữ liệu mới ñặt tên là Diadanh, Donvi, Ngay và Lylich. Type Diadanh = Record Tinh, Huyen, Xa, Thon: String[15]; End; Donvi = Record Truong: String[30]; Khoa, Bomon: String[20] End; Ngay = Record Ng: 1..31; Th: 1..12; Nam: Integer; End; Lylich = Record Mhs: Word; Trường ðại học Nông nghiệp 1 - Giáo trình Lập trình nâng cao ..............................................................- 23 Hoten: String[25]; Ngaysinh: Ngay; Quequan: Diadanh; Coquan: Donvi; End; Trong cách khai báo trên trường Ngaysinh thuộc kiểu Ngay, Quequan thuộc kiểu Diadanh, Coquan thuộc kiểu Donvi, nói cách khác ba trường này lại chính là ba Record. ðể khắc phục cách khai báo nhiều kiểu bản ghi như trên có thể sử dụng các bản ghi lồng nhau. Kiểu bản ghi lồng nhau có thể khai báo trực tiếp, nghĩa là không cần khai báo riêng rẽ các bản ghi con. Ví dụ 2.3 Uses crt; Type Lylich=record Mhs:word; Hoten:string[25]; Ngaysinh:record Ng:1..31; Th:1..12; Nam:Integer; End; Quequan:record Tinh,Huyen,xa,thon:string[15]; End; Coquan:record Truong:string[30]; Khoa, Bomon:string[20]; End; End; ................. Ngoài cách khai báo kiểu rồi mới khai báo biến, Pascal cho phép khai báo trực tiếp biến kiểu bản ghi theo cú pháp sau: Var Tên biến:Record Tên trường 1:kiểu trường; Tên trường 2:kiểu trường; ................. Trường ðại học Nông nghiệp 1 - Giáo trình Lập trình nâng cao ..............................................................- 24 End; 1.3 Truy nhập vào các trường của bản ghi Sau khi ñã khai báo kiểu dữ liệu ta phải khai báo biến, giả sử cần quản lý danh sách cán bộ một trường ñại học chúng ta phải khai báo một biến chứa danh sách viết tắt là DS. Khi ñó ta phải khai VAR DS: Lylich; Giống như hai kiểu dữ liệu Mảng và Chuỗi, việc xử lý ñược thực hiện trên các phần tử của mảng hoặc chuỗi. ở ñây mặc dù DS là một biến nhưng chúng ta không thể xử lý chính biến ñó mà chỉ có thể xử lý các trường của biến DS. ðể truy nhập vào trường cần viết: ..…. Ví dụ ñể nhập dữ liệu cho trường Hoten ta viết các lệnh: Write[' Ho va ten can bo: ']; Readln[DS.hoten]; Lệnh Readln[DS.hoten]; cho phép ta gán Họ tên cán bộ vào trường Hoten của bản ghi hiện thời. ðể nhập ngày tháng năm sinh chúng ta phải truy nhập vào các trường con Readln[Ds.Ngay.Ngays]; Readln[Ds.Ngay.Thang]; Readln[Ds.Ngay.Nam]; Lệnh viết dữ liệu ra màn hình cũng có cú pháp giống như lệnh nhập. Writeln[DS.Hoten]; Writeln[Ds.Ngay.Ngays]; ........... Chú ý: Khi khai báo biến DS kiểu LYLICH chúng ta có thể nhập dữ liệu vào biến DS nhưng chỉ nhập ñược một bản ghi nghĩa là chỉ nhập dữ liệu ñược cho một người. Nếu muốn có một danh sách gồm nhiều người thì phải có nhiều bản ghi, ñể thực hiện ñiều này chúng ta có thể xây dựng một mảng các bản ghi. Trình tự các bước như sau: * ðịnh nghĩa kiểu dữ liệu bản ghi * Khai báo biến mảng với số phần tử là số người cần quản lý, kiểu phần tử mảng là kiểu Bản ghi ñã ñịnh nghĩa. [xem ví dụ 2.4] Với tất cả các trường khi truy nhập ta luôn phải ghi tên biến rồi ñến tên trường mẹ, tên trường con, … ñiều này không chỉ làm mất thời gian mà còn khiến cho chương trình không ñẹp, Pascal khắc phục nhược ñiểm này bằng cách ñưa vào lệnh WITH... DO. 1.4 Lệnh WITH...DO Cú pháp của lệnh: WITH DO Trường ðại học Nông nghiệp 1 - Giáo trình Lập trình nâng cao ..............................................................- 25 Khi sử dụng lệnh WITH...DO chuỗi lệnh viết sau DO chỉ cần viết tên trường có liên quan mà không cần viết tên biến. Xét ví dụ nhập ñiểm cho lớp học với giả thiết lớp có nhiều nhất là 40 học sinh. Ví dụ 2.4: Program Nhapdiem; Uses CRT; Type BANGDIEM = RECORD Hoten: String[25]; Gioitinh: ['T','G']; [* kiểu liệt kê, 'T' = Trai, 'G' = Gái *] Lop: String[5]; Diachi: String[50]; Toan,Ly,Hoa: Real; End; Var DS_LOP: Array[1..40] of BANGDIEM [*danh sách lớp là mảng 40 phần tử*] i,j: Integer; lam: Char; BEGIN clrscr; lam:='C'; i:=1; Repeat With DS_LOP[i] Do Begin Write[' Ho va ten hoc sinh: ']; Readln[Hoten]; Write[' Trai hay gai T/G: ']; Readln[Gioitinh]; Write[' Thuoc lop: ']; Readln[Lop]; Write[' Cho o thuong tru: ']; Readln[Diachi]; Write[' Diem toan: ']; Readln[Toan]; Write[' Diem ly: ']; Readln[Ly]; Write[' Diem hoa: ']; Readln[Hoa]; End; i:=i+1; Write[' NHAP TIEP HAY THOI ? C/K ']; Readln[lam]; Until upcase[lam]='K'; clrscr; For j:=1 to i-1 do With DS_LOP[j] DO Writeln[Hoten:15,' ',Gioitinh:2,' ',Lop:4,' ',Diachi:10,' Toan:', Toan:4:2,' Ly:',Ly:4:2,' Hoa:',Hoa:4:2]; Trường ðại học Nông nghiệp 1 - Giáo trình Lập trình nâng cao ..............................................................- 26 Repeat Until Keypressed; END. Ví dụ 2.4 sử dụng mảng DS_LOP gồm 40 phần tử, mỗi phần tử là một Record. Mỗi lần nhập xong dữ liệu cho một phần tử lại hỏi "Nhap tiep hay thoi?", như vậy số phần tử cụ thể của mảng tuỳ thuộc vào câu trả lời C hay là K. Vấn ñề ñáng quan tâm ở ñây là cách sử dụng lệnh With ... Do, ví dụ 2.4 sử dụng biến mảng DS_LOP vì vậy trước tiên phải truy nhập vào phần tử thứ i của mảng DS_LOP [1

Chủ Đề