5.1. KHÁI NIỆM VỀ KIẺU DỮ LIỆU CÓ CÁU TRÚC
Trong các chương hước chúng ta đã tìm hiểu kiểu dữ liệu màng - là một kiểu dữ liệu có cấu trúc, là tập hợp các phần tử có cùng kiểu dữ liệu cơ sở. Tuy nhiên, trong thực tế cỏ những trường hợp mỗi phần tử lại chứa nhiều thành phần trong nó, thường gọi là các trường. Các trường này lại có các kiểu dữ liệu khác nhau. Ví dụ như bài toán quản lý danh sách học sinh, quàn lý danh sách nhân sự ... Mỗi học sinh lại bao gồm các thông tin về học sinh như: Họ tên, ngày sinh,... Để tạo ra kiểu dữ liệu này C đã định nghĩa kiểu dữ liệu Struct (viết tắt của structure), hay còn gọi là kiểu cấu trúc.
5.2. KHAI BÁO VÀ TRUY NHẬP VÀO PHÀN TỬ STRUCT
Struct là kiểu dữ liệu có cấu trúc. Nó là tập họp các phần tử mà mỗi phần tử chứa các trường thuộc kiểu dữ liệu khác nhau, được liên kết với nhau thông qua một tên chung là tên của struct.
Struct có thể coi như một định nghĩa kiểu dữ liệu của các kiểu dữ liệu. Qua định nghĩa ta có thể thấy kiểu struct trong C tương ứng với kiểu bản ghi (record) trong Pascal.
5.2.1. Khai báo structĐịnh nghĩa kiểu struct Định nghĩa kiểu struct
Trước khi khai báo biến struct ta tìm hiểu cách định nghĩa kiểu dữ liệu struct. Tức là ta phải nêu tên của kiểu struct và các trường của nó. Định nghĩa kiểu struct có dạng như sau:
Dạng 1
struct tên_kiểu_cấu_trúc {
/* khai báo các trường */ }; Ví dụ 5.1.1: struct date { int ngay; int thang; int nam; };
Ví dụ này khai báo một kiểu cấu trúc có tên là date gồm ba trường ngay, thang và nam đều có kiểu số ngun.
Ví dụ 5.1.2: struct address { char ho_ten[30J; int sonha; char duong[30]; char quan[20]; };
Ví dụ này khai báo một kiểu dữ liệu cấu trúc có tên là address gồm bốn trường có kiểu dữ liệu khác nhau được liên kết với nhau để mô tả địa chỉ: so nha có kiểu ngun, ba trường cịn lại là các mảng (kiểu char).
Lưu ý: Ta có thể dùng tốn tử typedef để định nghĩa các kiểu struct
như sau:
Dạng 2
typedef struct {
/* khai báo các trường ♦/ } tên_kiểu_cấu_trúc;
Ví dụ 5.1.3: cấu trúc Address ở ví dụ trên có thể định nghĩa lại như
sau: typedef struct { char ho_ten[30]; int sonha; char duong[30]; char quan[20]; } address;
Nhớ rằng tên kiểu của struct lúc này được đặt ở cuối phần định nghĩa.
Khai báo biến struct
Sau khi đã định nghĩa xong kiểu dữ liệu ta có thể khai báo biến kiểu struct. Để khai báo biến struct cũng giống như việc khai báo các biến bình thường. Ta cần chỉ ra kiểu và tên của nó. Cú pháp của khai báo biến struct có dạng như sau:
Dạng 1
tên_kiểu_cấu_trúc danh_sách_tên_biến_cấu_trúc;
Ví dụ 5.1.4:
struct date ngay sinh;
Khai báo này cho ta một biến struct với tên là ngay sinh có kiểu date được định nghĩa trong ví dụ 5.1.1
Ví dụ 5.1.5:
Khai báo:
struct address X, Y;
Sẽ cho ta hai biến struct có tên là X,Y thuộc kiểu Address đã được định nghĩa ở ví dụ 5.1.2
Nhận xét
- Ta có thể thực hiện khai báo đồng thời với việc định nghĩa kiểu struct. Khi đó danh sách tên biến cẩu trúc cần khai báo được đặt sau dấu } trong định nghĩa dạng 1. Cụ thể nó có dạng như sau:
Dạng 2
struct tên_kiểu_cấu_trúc {
/* khai báo các trường */
} danh_sách_tên_biến_cấu_trúc;
Ví dụ 5.1.6: Hai cấu trúc X và Y ở ví dụ 5.1.5 ở trên có thể xây
dựng như sau: struct address { char ho_ten[30]; int sonha; char duong[30]; char quan[20]; } X, Y;
Nếu ta vừa định nghĩa kiểu vừa khai báo biến struct thì có thể khơng cần đến tên kiểu cấu trúc.
Dạng 3
struct {
/* khai báo các trường */
} danh_sách_tên_bien_cấu_trúc;
Ví dụ 5.1.7: Ví dụ 5.1.6 ở trên có thể khai báo lại như sau:
struct {
char ho_ten[30]; int sonha; char duong[30]; char quan[20]; }X, Y;
Sự khác nhau trong hai cách khai báo dạng 2 và dạng 3 như sau: Đối với dạng 2 thì ngồi việc khai báo biến cấu trúc còn khai báo được kiểu dữ liệu struct. Và ta có thể dùng kiểu dữ liệu này để khai báo các cấu trúc khác. Còn đổi với dạng 3 ta chi thực hiện được việc khai báo biến struct.
Chú ý: Nếu dùng typedef để định nghĩa kiểu cấu trúc, thì khi khai báo biến cấu trúc ta chỉ cần dùng tên kiểu cấu trúc và bỏ đi từ khóa struct.
Ví dụ 5.1.8:
Với định nghĩa trong ví dụ 5.1.3 thì khai báo ở ví dụ 5.1.5 có thể khai báo lại như sau:
address X,Y;
Ta có thể khai báo cấu trúc lồng nhau nghĩa là cấu trúc này ở bên trong cấu trúc khác.
Ví dụ 5.1.9:
Để mơ tả sinh viên của phịng đào tạo, ta phải dùng các trường họ tên, ngày sinh, lớp, điểm.. ..Ở đây ta lấy 4 trường làm ví dụ. Giả sử ta đã định nghĩa kiểu dữ liệu date như trên. Khi đó ta có khai báo như sau:
struct Sinh_vien { char ho_ten[30]; date ngaysinh; char lop[l 0]; float diem; } SV1,SV2;
5.2.2. Truy nhập vào các trường của struct
Để truy nhập vào các trường của một cấu trúc ta sử dụng toán tử . (dấu chấm) có dạng như sau:
Tên_cấu_trúc.tên_trường
Ví dụ 5.2.1 : Muốn truy nhập vào trường so nha của cấu trúc X ta viết:
x.sonha
Nếu cấu trúc có kiểu lồng nhau thì ta truy nhập theo mẫu như sau: Tên_cấu_trúc 1. Tên_cấu_trúc2. têntrường
Trong đó cấu trúc 2 được lồng trong cẩu trúc 1
Ví dụ 5.2.2: Để truy nhập vào trường ngay của SV1 trong ví dụ
5.1.9 ta viết:
S V1 .ngaysinh.ngay
Khi đó mỗi trường của cấu trúc có thể thâm nhập và sử dụng như một biến bình thường. Cụ thể là:
ỉ. Gán giá trị Ví dụ 5.2.3
x.sonha = 109;
Tuy nhiên, nếu ta gán như sau thì chương trình dịch sẽ báo Lvalue required.
x.duong = “Nguyen Van Cu”;
Đó là vì như frong phần xâu ký tự chúng ta đã nhắc đến răng không thể gán xâu ký tự cho một biến.