Tải bản đầy đủ (.ppt) (21 trang)

Bài giảng Ngôn ngữ lập trình C - Chương 7: Cấu trúc

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (66.49 KB, 21 trang )

CHƯƠNG 7

CẤU TRÚC
Cấu trúc là tập hợp của một hoặc nhiều biến,
có thể khác kiểu nhau, được nhóm lại dưới dạng một
tên duy nhất cho tiện xử lý. (Giống cấu trúc Record
trong Pascal).
Cấu trúc giúp cho việc tổ chức các dữ liệu
phức tạp, đặc biệt trong những chương trình lớn vì
trong nhiều tình huống chúng cho phpé nhóm các
biến có liên quan lại để xử lý như một đơn vị thay vì
như các thực thể tách biệt.


I.
1.

Định nghĩa cấu trúc và khai báo biến cấu trúc
Định nghĩa cấu trúc
struct <Tên_kiểu_cấu_trúc> {
<Kiểu> <Tên trường 1>;
<Kiểu> <Tên trường 2>;
...
}
Trong đó: struct: Là từ khố
Tên_kiểu_cấu_trúc: là tên bất kỳ, do người sử
dụng đặt


Ví dụ:
struct Date {


int day;
int month;
int year;
};
2. Định nghĩa cấu trúc bằng typedef
Nếu một cấu trúc được định nghĩa với
tên_kiểu_cấu_trúc thì ta có thể cùng typedef đê
định nghĩa như sau:
Typedef struct < tên_kiểu_cấu_trúc> <Tên_kiểu>;


Ví dụ:
typedef struct Date DATE;
Nếu một cấu trúc chưa định nghĩa, thì ta có thể dùng
typedef để định nghĩa:
Typedef struct [Tên_kiểu_cấu_trúc] {
<Kiểu> <Trường 1>;
<Kiểu> <Trường 2>;
...
} <tên_kiểu>;
Ví dụ:
Với ví dụ trên ta có thể dùng typedef để định nghĩa
lại như sau:


typedef struct {

int day;
int month;
int year;

} DATE;

3. Khai báo biến cấu trúc
Khai báo kết hợp:
struct <Tên_kiểu_cấu_trúc> {
<Kiểu> <Trương1>;
<Kiểu> <Trương2>;
...
} <Danh_sách_các_biến>;


Ví dụ:
struct Date {
int day;
int month;
int year;
} date, *pd;
Khai báo riêng lẽ:
Dùng Tên_kiểu_bản_ghi hoặc thông qua tên cấu
trúc đã được định nghĩa bằng typedef
+ Dùng tên_kiểu_cấu_trúc:
struct < tên_kiểu_cấu_trúc> <Danh sách các biến>


II.

Ví dụ:
struct Date date,*pd;
+
Dùng tên định nghĩa bằng typedef

<Tên_kiểu> <danh sách các biến>
Ví dụ:
DATE date,*pd
Khởi đầu giá trị cho cấu trúc:
Ta có thể khởi đầu giá trị cho một cấu trúc theo
phương cách như là khởi đầu giá trị cho mảng.
Theo sau tên_biến_cấu_trúc là dấu bằng (=), sau
đó là danh dách các giá trị khởi đầu được đặt trong
các dấu móc {}. Các giá trị khởi đầu có cùng kiểu
với các trường tương ứng trong cấu trúc.


Ví dụ:
DATE date = {12, 3, 2003}
III. Truy cập đến các thành phần của cấu trúc:
Có hai cách tham chiếu đến các thành phần của
cấu trúc tương ứng với hai trường hợp sau:

Nếu nó là một biến cấu trúc:
Ta dùng toán tử dấu chấm (.) để tham chiếu đến
các trường (thành phần) của cấu trúc.
Cú pháp:
<tên_biến_cấu_trúc>.<Tên_trường>


Nếu nó là một biến con trỏ trỏ đến cấu trúc:
Ta dùng toán tử mũi tên (->) để tham chiếu đến.

Cú pháp:
<tên_biến_cấu_trúc>-><Tên_trường>

Ví dụ:
struct Date {

int day;
int month;
int year;
} date;
typedef struct Date DATE
DATE *p


Với các khai báo trên ta có các cách tham chiếu sau:
date.day=18;
date.month=4;
date.year=2003;
Hoặc:
p->day = 18
p->month=4;
p->year=2003;
Các phép toán con trỏ tương đương với:
(*p).day=18;
(*p).month=4;
(*p).year=2003;


Gán hai biến cấu trúc cho nhau(cùng kiểu cấu trúc)
Ví dụ:
struct Date d={18,4,2003};
struct Date today;
today=d;

Có thể lấy địa chỉ các trường của cấu trúc, kết quả là
con trỏ trỏ đến thành phần tương ứng.
Ví dụ:
scanf(“%2d - %2d %4d”, &today.day,
&today.month, &today.year);


IV.

Mảng các cấu trúc
Vì cấu trúc là khối đối tượng dữ liệu, do đó hồn tồn có
khả năng tạo ra một mảng các cấu trúc. Khai báo mảng
các cấu truc như sau:
struct <Tên_kiểu_cấu_trúc> <Tên_mảng> [<kích_thước>];

Hoặc là dùng tên đã được khai báo bởi typedef:
<Tên_kiểu> <Tên_mảng>[<kích_thước>];
Ví dụ:
Khai báo mảng cấu trúc:
struct Date aa[10];
DATE ab[10];
Lúc đó để tham chiếu đến các trường ta có thể dùng như sau:
aa[2].month = 4;
(*(aa+2)).year=2003


V.

Cấu trúc lồng nhau
Một cấu trúc được gọi là lồng nhau nếu có một

trong các trường của cấu trúc này lại có kiểu cấu
trúc. Cấu trúc lồng nhau thường được dùng phổ
biến trong lập trình C bởi vì nó cho phép tạo ra
các dữ liệu có thứ bậc.
Vi dụ: Tạo cấu trúc để lưu thông tin ngày sinh
của một người.


typedef struct
{
char name[30];
struct
{
int day;
int month;
int year;
} birth_day;
} BDATE;


Hoặc:
typedef struct
{
char name[30];
struct Date birth_day;
} BDATE;
Hoặc
typedef
{
char name[30];

DATE birth_day;
}BDATE;


Tham chiếu đến các thành phần của cấu trúc lồng
nhau thì hồn tồn giống với việc tham chiếu trong cấu
trúc khơng lồng nhau, tuy chỉ có những trường chứa cấu
trúc thì phải thêm tên biến cấu trúc đó vào.
Ví dụ
Với cấu trúc vừa định nghĩa ở ví dụ trên, ta tham chiếu
đến các thành phần của biến ngaysinh có kiểu BDATE
là:
Tên: ngaysinh.name=“Tran Van A”;
Ngày sinh:
ngaysinh.birth_day.day=19;
ngaysinh.birth_day.month=04;
ngaysinh.birth_day.year=2003;


Về mặt lý thuyết thì khơng có bất kỳ một giới hạn nào
về số mức lồng nhau của cấu trúc. Nhưng lúc đó các tham
chiếu đến các trường sẽ càng trở nên phúc tạp và khó đọc
hơn.

Cấu trúc tự tham chiếu:
Các cấu trúc gọi là tự tham chiếu nếu nó chứa một
trường là con trỏ trỏ đến chính nó.
Ví dụ:
struct a
{

int a,b;
float c;
struct a *ptoa;
};


Tính tham chiếu trước (Forward Referencing)
Tính chất này cho phép ta đưa ra các khai báo các
con trỏ trỏ đến các cấu trúc chưa được định nghĩa,
đặc tính này cũng cho phép ta tạo ra sự tự tham
chiếu như đã đề cập ở trên. Ta có thể tạo ra cấu trúc
sự tham chiếu lẫn nhau.
Ví dụ:
struct s1
{
int a;
struct s2 *b;
};


struct s2
{
int a;
struct s1 *b;
};
Đặc tính này khơng áp dụng trong các khai báo
bằng typedef
VI. Truyền cấu trúc cho hàm
Có hai cách truyền cấu trúc cho hàm:
- Truyền theo biến cấu trúc (gọi là truyền theo

giá trị)
- Truyền con trỏ trỏ đến cấu trúc (gọi là truyền
theo tham chiếu)


Ví dụ:
DATE d;
.
.
func (d); /* Định nghĩa hàm func(DATE d) */
func(&d);/* Định nghĩa hàm func (DATE *d)*/
.
.
Truyền theo địa chỉ ln nhanh hơn bởi vì chỉ là một
con trỏ đơn giản được sao chép đến vùng đối số.
Mặt khác, truyền theo giá trị sẽ địi hỏi tồn bộ các
cấu trúc sẽ được sao chép. Chỉ có hai trương hợp
nên truyền theo giá trị:


Cấu trúc nhỏ (tức là kích thước cỡ xấp xỉ với một
con trỏ)
Muốn bảo đảm rằng lời gọi hàm sẽ không làm thay
đổi cấu trúc được truyền vào. (Khi một đối số truyền
theo giá trị, trình biên dịch sẽ tạo một bản sao của
đối số đó. Hàm được gọi chỉ có thể thay đổi trên bản
sao mà thơi).




×