You are on page 1of 28

CHƯƠNG 7.

KIỂU DỮ LIỆU CẤU TRÚC

Nội dung
7.1 Định nghĩa kiểu cấu trúc.
7.2 Khai báo, khởi tạo và truy xuất biến kiểu cấu trúc.
7.3 Truyền biến cấu trúc cho hàm
7.4 Mảng cấu trúc và con trỏ cấu trúc.

1
CHƯƠNG 7. KIỂU DỮ LIỆU CẤU TRÚC

 Để lưu trữ và xử lý thông tin trong máy tính ta có các biến và các mảng.
 Mỗi biến chứa được một giá trị.
 Mảng là tập hợp nhiều biến có cùng một kiểu giá trị và được biểu thị bằng một
tên.
Vấn đề: Lưu mảng dữ liệu mà mỗi một phần tử gồm nhiều thành phần có kiểu
khác nhau. Ví dụ như một danh sách các sinh viên với các thông tin:
- Mã số sinh viên;
- Họ tên;
- Ngày tháng năm sinh;
- Giới tính;
- Địa chỉ thường trú 2
CHƯƠNG 7. KIỂU DỮ LIỆU CẤU TRÚC
7.1 Định nghĩa kiểu cấu trúc.
Ngôn ngữ lập trình C cho phép người lập trình tự định nghĩa ra kiểu dữ liệu mới (kiểu
cấu trúc) theo nhu cầu sử dụng từ những kiểu dữ liệu đã có hoặc đã định nghĩa trước đó.
 Kiểu cấu trúc (Structure) là kiểu dữ liệu bao gồm nhiều thành phần có kiểu dữ liệu
khác nhau, mỗi thành phần được gọi là một trường (field).
Cú pháp 1: Cú pháp 2:
struct <Tên cấu trúc> typedef struct
{ {
<Kiểu dữ liệu> <Tên trường 1> ; <Kiểu dữ liệu > <Tên trường 1> ;
<Kiểu dữ liệu > <Tên trường 2> ; <Kiểu dữ liệu > <Tên trường 2> ;
…….. ……..
<Kiểu dữ liệu > <Tên trường n> ; <Kiểu dữ liệu > <Tên trường n> ;
}; } <Tên cấu trúc>; 3
7.1 Định nghĩa kiểu cấu trúc.
Cú pháp 1: Cú pháp 2:
struct <Tên cấu trúc> typedef struct
{ {
<Kiểu dữ liệu> <Tên trường 1> ; <Kiểu dữ liệu > <Tên trường 1> ;
<Kiểu dữ liệu > <Tên trường 2> ; <Kiểu dữ liệu > <Tên trường 2> ;
…….. ……..
<Kiểu dữ liệu > <Tên trường n> ; <Kiểu dữ liệu > <Tên trường n> ;
}; } <Tên cấu trúc>;
Trong đó:
- <Tên cấu trúc>: là một tên được đặt theo quy tắc đặt tên của C; tên này mang ý nghĩa
sẽ là tên kiểu cấu trúc;
- <Kiểu dữ liệu> < Tên trường i> (i=1..n): mỗi trường trong cấu trúc có kiểu dữ liệu và
tên của trường phải là một tên được đặt theo quy tắc đặt tên của C. 4
CHƯƠNG 7. KIỂU DỮ LIỆU CẤU TRÚC
7.1 Định nghĩa kiểu cấu trúc.
Ví dụ 1: Để quản lý ngày, tháng, năm của một ngày trong năm ta có thể khai báo kiểu
cấu trúc gồm 3 thông tin: ngày, tháng, năm.

struct KieuNgayThang typedef struct


{ {
unsigned char Ngay; unsigned char Ngay;
unsigned char Thang; unsigned char Thang;
unsigned int Nam; unsigned int Nam;
}; } KieuNgayThang;

5
CHƯƠNG 7. KIỂU DỮ LIỆU CẤU TRÚC
7.1 Định nghĩa kiểu cấu trúc.
Ví dụ 2: Mỗi sinh viên cần được quản lý bởi các thông tin: Mã số sinh viên, họ tên, ngày
tháng năm sinh, giới tính, địa chỉ thường trú.

struct KieuSinhVien typedef struct


{ {
char MSSV[10]; char MSSV[10];
char HoTen[40]; char HoTen[40];
struct KieuNgayThang NgaySinh; KieuNgayThang NgaySinh;
int Phai; int Phai;
char DiaChi[40]; char DiaChi[40];
}; } KieuSinhVien; 6
CHƯƠNG 7. KIỂU DỮ LIỆU CẤU TRÚC
7.1 Định nghĩa kiểu cấu trúc.
struct KieuSinhVien typedef struct
{ {
char MSSV[10]; char MSSV[10];
char HoTen[40]; char HoTen[40];
struct KieuNgayThang NgaySinh; KieuNgayThang NgaySinh;
int Phai; int Phai;
char DiaChi[40]; char DiaChi[40];
}; } KieuSinhVien;

 Kết thúc của phần khai báo kiểu cấu trúc là dấu chấm phẩy (;).
 Các kiểu cấu trúc được phép khai báo lồng nhau, nghĩa là kiểu cấu trúc có thể lại là
một trường của kiểu cấu trúc.
 Một biến có kiểu cấu trúc sẽ được cấp phát bộ nhớ sao cho các thành phần của nó
được sắp liên tục theo thứ tự xuất hiện trong khai báo. 7
7.2 Khai báo, khởi tạo và truy xuất biến kiểu cấu trúc .
7.2.1 Khai báo biến kiểu cấu trúc .
Cú pháp:
 Đối với cấu trúc được định nghĩa theo cách 1:
struct <Tên cấu trúc> <Biến 1> [, <Biến 2>…];
Ví dụ: struct KieuNgayThang NgaySinh;
struct KieuSinhVien SV;
 Đối với các cấu trúc được định nghĩa theo cách 2:
<Tên cấu trúc> <Biến 1> [, <Biến 2>…];
Ví dụ: KieuNgayThang NgaySinh;
KieuSinhVien SV; 8
7.2 Khai báo, khởi tạo và truy xuất biến kiểu cấu trúc .
7.2.2 Truy xuất đến từng trường của biến cấu trúc
Cú pháp:
<Biến cấu trúc>.<Tên trường>;
Ví dụ1: Viết chương trình cho phép đọc dữ liệu từ bàn phím cho biến SinhVien và in
biến đó lên màn hình:
#include<conio.h> typedef struct
#include<stdio.h> {
#include<string.h> char MSSV[10];
typedef struct char HoTen[40];
{ KieuNgayThang NgaySinh;
unsigned char Ngay; int Phai;
unsigned char Thang; char DiaChi[40];
unsigned int Nam; } KieuSinhVien;
9
} KieuNgayThang;
Ví dụ1: Viết chương trình cho phép đọc dữ liệu từ bàn phím cho biến SinhVien và in
biến đó lên màn hình:
void InSV(KieuSinhVien s)
{ printf(“MSSV: | Ho va ten | Ngay Sinh | Dia chi\n”);
printf(“%s | %s | %d-%d-%d | %s\n”,s.MSSV,s.HoTen,
s.NgaySinh.Ngay,s.NgaySinh.Thang,s.NgaySinh.Nam,s.DiaChi);
}
int main() fflush(stdin);
{ printf(“Dia chi: “);gets(SV.DiaChi);
KieuSinhVien SV, s; printf("In cac thong so cua bien cau truc SV\n");
printf(“Nhap MSSV: “);gets(SV.MSSV); InSV(SV);
printf(“Nhap Ho va ten: “);gets(SV.HoTen); s=SV;
printf(“Sinh ngay: “); printf("In cac thong so cua bien cau truc s\n");
scanf(“%d”,&SV.NgaySinh.Ngay); InSV(s);
printf(“Thang: “);scanf(“%d”,&SV.NgaySinh.Thang); getch();
printf(“Nam: “);scanf(“%d”,&SV.NgaySinh.Nam); return 0;
printf(“Gioi tinh (0: Nu), (1: Nam): “); }
scanf(“%d”,&SV.Phai); 10
7.2 Khai báo, khởi tạo và truy xuất biến kiểu cấu trúc .
7.2.2 Truy xuất đến từng trường của biến cấu trúc
Lưu ý:
 Với các biến kiểu cấu trúc ta không thể thực hiện được các thao tác sau đây:
 Không sử dụng các hàm xuất nhập trên biến cấu trúc; Hàm xuất nhập dung
cho các trường của
Ví dụ: biến cấu trúc thì được
gets(SV) gets(SV.MSSV)
printf(“chuỗi định dạng”, SV) printf(“%s”, SV.Hoten)
scanf(“chuỗi định dạng”, SV) scanf(“%d”, SV.NgaySinh.Nam)

 Không sử dụng các phép so sánh, các phép toán số học và logic.
Ví dụ: SV ==s; hay SV=s+5; 11
7.2.2 Truy xuất đến từng trường của biến cấu trúc
Lưu ý:
 Các biến cấu trúc cùng kiểu có thể gán cho nhau. ( Thao tác gán thực hiện trên toàn
bộ các trường của biến cấu trúc không phải trên một trường riêng rẽ nào)
Ví dụ câu lệnh gán: s=SV;

Nhập dữ liệu
(trong hàm main)

In dữ liệu biến cấu trúc


SV trong hàm InSV

In dữ liệu biến cấu trúc s


trong hàm InSV 12
CHƯƠNG 7. KIỂU DỮ LIỆU CẤU TRÚC
7.2 Khai báo, khởi tạo và truy xuất biến kiểu cấu trúc .
7.2.3 Khởi tạo biến cấu trúc

 Việc khởi tạo cấu trúc có thể được thực hiện trong lúc khai báo biến cấu trúc.
 Các trường của cấu trúc được khởi tạo được đạt giữa 2 dấu { và }, chúng được
phân cách nhau bởi dấu phẩy (,).
Ví dụ khởi tạo biến cấu trúc NgaySinh:
struct KieuNgayThang NgaySinh ={29, 8, 1986};
Ví dụ khởi tạo một mảng biến cấu trúc:
struct KieuNgayThang a[3]= {{29,8,1986},{30,9,1987},{15,10,1988}};
13
CHƯƠNG 7. KIỂU DỮ LIỆU CẤU TRÚC
7.3 Truyền biến cấu trúc cho hàm.
 Giống như các tham số có kiểu dữ liệu cơ bản khác, ta có thể truyền tham số
có kiểu cấu trúc cho hàm

<kiểu dữ liệu trả về> <tên hàm>(<kiểu cấu trúc> <tên biến>,…)

Ví dụ:
Void InSV(KieuSinhVien s);
Lời gọi hàm:
InSV(s);
InSV(SV);

14
CHƯƠNG 7. KIỂU DỮ LIỆU CẤU TRÚC
7.4 Mảng cấu trúc và con trỏ cấu trúc.
7.4.1 Mảng cấu trúc.
 Khai báo mảng dữ liệu kiểu cấu trúc

Đối với cấu trúc struct <Tên kiểu cấu trúc> <tên mảng>[số phần tử ];
được định nghĩa
theo cách 1
Ví dụ :struct KieuSinhVien a[10];
Hoặc:

Đối với cấu trúc


<Tên kiểu cấu trúc> <tên mảng>[số phần tử ];
được định nghĩa
theo cách 2
Ví dụ : KieuSinhVien a[10]; 15
CHƯƠNG 7. KIỂU DỮ LIỆU CẤU TRÚC
7.4 Mảng cấu trúc và con trỏ cấu trúc.
7.4.1 Mảng cấu trúc.
 Truy cập đến các phần tử của mảng cấu trúc: Sử dụng chỉ số để truy cập
Ví dụ: Truy cập đến trường họ tên của phần tử thứ có chỉ số 5 của mảng a

a[5].HoTen Cú pháp: <Biến cấu trúc>.<Tên trường>;

Ví dụ: Câu lệnh nhập họ tên cho phần tử thứ có chỉ số 5 của mảng a

printf(“Nhap Ho va ten: “);gets(a[5].HoTen); printf(“Nhap Ho va ten: “);gets(SV.HoTen);

16
CHƯƠNG 7. KIỂU DỮ LIỆU CẤU TRÚC
7.4 Mảng cấu trúc và con trỏ cấu trúc.
7.4.2 Con trỏ cấu trúc.
 Khai báo con trỏ kiểu cấu trúc

struct <Tên kiểu cấu trúc> * <tên biến con trỏ>;

Ví dụ : struct KieuSinhVien *p ;
Hoặc:

<Tên kiểu cấu trúc> * <tên biến con trỏ>;

Ví dụ : KieuSinhVien *p ; 17
CHƯƠNG 7. KIỂU DỮ LIỆU CẤU TRÚC
7.4.2 Con trỏ cấu trúc.
 Sử dụng các con trỏ kiểu cấu trúc.
 Khi khai báo biến con trỏ cấu trúc, biến con trỏ chưa có địa chỉ cụ thể.
 Muốn thao tác trên con trỏ cấu trúc hợp lệ, tương tự như các con trỏ khác, ta phải:
- Cấp phát một vùng nhớ cho nó (sử dụng hàm malloc() hay calloc);
- Hoặc, cho nó quản lý địa chỉ của một biến cấu trúc nào đó.

Ví dụ: Sau khi khởi tạo giá trị của cấu trúc:
struct KieuNgayThang NgaySinh ={29, 8, 1986};
struct KieuNgayThang *p;
Khi đó biến con trỏ p chứa
p = & NgaySinh;
địa chỉ của NgaySinh 18
7.4.2 Con trỏ cấu trúc.
 Truy cập các thành phần của cấu trúc đang được quản lý bởi con trỏ
 Để truy cập đến từng trường của 1 cấu trúc thông qua con trỏ của nó, ta sử
dụng toán tử dấu mũi tên -> (dấu - và dấu >).
 Sử dụng đến phép toán * để truy cập vùng dữ liệu đang được quản lý bởi con
trỏ cấu trúc để lấy thông tin cần thiết.
Ví dụ: int main()
{
#include<conio.h> NgayThang Ng={29,8,1986};
#include<stdio.h> NgayThang *p; p=&Ng;
typedef struct printf("Truy cap binh thuong %d-%d-%d\n", Ng.Ngay,Ng.Thang,Ng.Nam);
{ printf("Truy cap qua con tro %d-%d-%d\n", p->Ngay,p->Thang,p->Nam);
unsigned char Ngay; printf("Truy cap qua vung nho con tro %d-%d-%d\n",
unsigned char Thang; (*p).Ngay,(*p).Thang,(*p).Nam);
unsigned int Nam; getch(); return 0;
} NgayThang; } 19
CHƯƠNG 7. KIỂU DỮ LIỆU CẤU TRÚC
7.4 Mảng cấu trúc và con trỏ cấu trúc.

Bài tập ví dụ: Viết chương trình xử lý danh sách sinh viên (tối đa 20 Sinh viên),
cho phép thực hiện các công việc sau:
1. Cho phép nhập danh sách sinh viên
2. Cho phép in danh sách sinh viên
3. Cho phép sửa danh sách sinh viên.
(viết dưới dạng các hàm con với tham số truyền là cấu trúc)

20
CHƯƠNG 7. KIỂU DỮ LIỆU CẤU TRÚC
Truyền biến cấu //cac ham xu ly
#include <stdio.h> trúc cho hàm int nhap(struct Sinhvien *p) ;
#include <conio.h> int nhapds(struct Sinhvien *a, int n) ;
#include<string.h> int in(struct Sinhvien x) ;
struct Ngaythang Truyền mảng int inds(const struct Sinhvien a[], int n) ;
{ cấu trúc cho int sua(struct Sinhvien *r)
int ng ; hàm int suads(struct Sinhvien *a, int n) ;
int th ; //Khai báo mảng
int nam ; Truyền con struct Sinhvien a[20];
}; trỏ cấu trúc
int main()
cho hàm
struct Sinhvien {
{ nhapds(a,20);
char hoten[25] ; inds(a,20);
struct Ngaythang ns; suads(a,20);
int gt; getch();
float diem ; return 0;
}; } 21
int nhap(struct Sinhvien *p) int main()
{ fflush(stdin); {
printf("Nhap ho va ten: ");gets(p->hoten); Cách sử nhapds(a,20);
printf("Nhap ngay sinh (ngay thang nam): "); dụng inds(a,20);
scanf("%d%d%d", &p->ns.ng ,&p->ns.th,&p->ns.nam); con trỏ suads(a,20);
printf("Gioi tinh 0: nu, 1: nam: "); truy cập getch();
đến các
scanf("%d",& p->gt); return 0;
trường
printf("Diem: "); }
của biến
scanf("%f",& p->diem); cấu trúc
return 0;
}
int nhapds(struct Sinhvien *a, int n)
{
int i; So sánh thông số
truyền trong 2 lời
for (i=0; i<n; i++) nhap(&a[i]) ;
gọi hàm
return 0;
}
22
int in(struct Sinhvien x) int main()
{ {
printf("Ho ten :%s\nNgay sinh %d/%d/%d\n",x.hoten,x.ns.ng, nhapds(a,20);
x.ns.th, x.ns.nam) ; inds(a,20);
printf("Gioi tinh :%s\nDiem :%f\n",(x.gt==1) ?"Nam" :"Nu",x.diem) ; suads(a,20);
return 0; getch();
} return 0;
int inds(const struct Sinhvien a[], int n) }
{
int i;
for (i=0; i<n; i++)
in(a[i]) ;
return 0;
}

23
int suads(struct Sinhvien *a, int n) int main()
{ {
int chon; nhapds(a,20);
do inds(a,20);
{ suads(a,20);
printf("\nNhap phan tu duoc su tu 0 den %d, gia tri khac thoat:",n-1); getch();
scanf("%d",&chon); return 0;
if(chon>=0 &&chon<n) sua(&a[chon]) ; }
}while(chon>=0 && chon<n);
return 0;
}

24
int sua(struct Sinhvien *r)
{
int chon;
do {
printf("1: Sua ho ten\n2: Sua ngay sinh\n3:Sua gioi tinh\n4:Sua diem\n5:In\n0: Ket thuc\n");
scanf("%d",&chon);
switch (chon)
{
case 1: fflush(stdin);
printf("Nhap ho ten:"); gets(r->hoten);
break;
case 2: printf("Nhap ngay thang nam sinh:");
scanf("%d%d%d",&r->ns.ng,&r->ns.th,&r->ns.nam);
break;
case 3: printf("Nhap gioi tinh 0:Nu 1:Nam:");scanf("%d",&r->gt) ;
break;
case 4: printf("Nhap diem:");scanf("%f",&r->diem);
break;
case 5: printf("Sinh vien:");in(*(r));break;
case 0: break;
default:
printf("Nhap gia tri khong dung\n");break;
}
25
} while (chon) ;return 0;}
Tóm Tắt Nội Dung Chương 7

 Tìm hiểu kiểu dữ liệu cấu trúc và công dụng


 Định nghĩa cấu trúc
 Khai báo các biến kiểu cấu trúc
 Cách truy cập vào các phần tử của cấu trúc
 Khởi tạo biến cấu trúc
 Sử dụng biến cấu trúc trong câu lệnh gán
 Cách truyền tham số cấu trúc
 Sử dụng mảng các cấu trúc
 Tìm hiểu cách khởi tạo mảng các cấu trúc
 Con trỏ cấu trúc
 Cách truyền tham số kiểu con trỏ cấu trúc
26
BÀI TẬP CHƯƠNG 7
Bài 1:
Khai báo kiểu dữ liệu biểu diễn thông tin của một số phức, sau đó viết chương trình thực
hiện các chức năng sau:
a. Nhập số phức
b. Xuất số phức (theo định dạng Re + Im*i)
c. Tính modul số phức
d. So sánh hai số
e. Tính tổng hai số phức
f. Tính hiệu hai số phức
g. Tính tích hai số phức
h. Tính thương hai số phức 27
BÀI TẬP CHƯƠNG 7

Bài 2:
Khai báo kiểu dữ liệu biểu diễn thông tin một tam giác, sau đó viết chương trình thực hiện
các chức năng sau:
a.Nhập tam giác
b.Xuất tam giác theo định dạng ((x1, y1); (x2, y2); (x3, y3))
c.Kiểm tra 3 đỉnh có lập thành 3 đỉnh của một tam giác không?
d.Tính chu vi tam giác
e.Tính diện tích tam giác
f. Tính tọa độ trọng tâm tam giác
g.Phân loại tam giác
28

You might also like