Trong các bài học trước, chúng ta đã làm quen với Mảng – nơi lưu trữ tập hợp các phần tử cùng kiểu dữ liệu. Tuy nhiên, trong thực tế, một đối tượng (như một sinh viên hay một nhân viên) thường bao gồm nhiều thông tin khác kiểu nhau (tên, tuổi, điểm số…). Đây là lúc Structure (Struct) – kiểu dữ liệu do người dùng tự định nghĩa – phát huy sức mạnh.
🎯 Mục tiêu học tập
- Hiểu khái niệm và cách định nghĩa một Structure.
- Thành thạo khai báo biến, mảng và truy xuất các thành viên của Struct.
- Sử dụng từ khóa
typedef để tối ưu hóa mã nguồn.
- Làm chủ kỹ thuật Struct lồng nhau và Con trỏ Struct.
- Ứng dụng cấp phát bộ nhớ động cho Struct trong các bài toán thực tế.
1. Khái niệm về Kiểu Struct
Structure là một kiểu dữ liệu do người dùng tự định nghĩa (user-defined datatype), cho phép kết hợp các thành phần có kiểu dữ liệu khác nhau vào một đơn vị duy nhất. Mỗi thành phần bên trong cấu trúc được gọi là một thành viên (member).
Cú pháp định nghĩa
struct structureName {
dataType member1;
dataType member2;
...
};
Ví dụ: Định nghĩa cấu trúc cho một Sinh viên:
struct SinhVien {
int maSV;
char ho[20];
char ten[20];
bool gioiTinh;
char queQuan[100];
};
2. Khai báo và Truy xuất Struct
Khai báo biến
Việc khai báo biến Struct tương tự như biến thông thường, nhưng cần đi kèm từ khóa struct (trừ khi dùng typedef):
struct SinhVien sv1, sv2; // Khai báo 2 biến đơn
struct SinhVien danhSach[100]; // Khai báo mảng 100 sinh viên
Truy xuất thành viên
C có hai toán tử chính để truy cập vào các thành viên bên trong Struct:
- Toán tử chấm (
.): Dùng cho các biến Struct bình thường. Ví dụ: sv1.maSV = 101;
- Toán tử mũi tên (
->): Dùng khi làm việc với con trỏ Struct. Ví dụ: ptr->maSV = 101;
3. Từ khóa Typedef
Từ khóa typedef giúp tạo ra tên thay thế cho kiểu dữ liệu, giúp cú pháp khai báo trở nên ngắn gọn và chuyên nghiệp hơn.
typedef struct {
int tu;
int mau;
} PhanSo;
// Bây giờ bạn có thể khai báo trực tiếp:
PhanSo ps1, ps2;
4. Struct lồng nhau và Con trỏ Struct
Struct lồng nhau
Bạn có thể sử dụng một Struct đã định nghĩa làm thành viên của một Struct khác. Điều này rất hữu ích cho các cấu trúc dữ liệu phân cấp.
struct Point { int x, y; };
struct Triangle {
struct Point a, b, c; // 3 đỉnh là 3 đối tượng Point
};
Con trỏ và Cấp phát động cho Struct
Trong lập trình nhúng, chúng ta thường xuyên sử dụng con trỏ Struct để quản lý tài nguyên hiệu quả thông qua vùng nhớ Heap.
struct person ptr; ptr = (struct person) malloc(n * sizeof(struct person));
// Truy cập qua toán tử mũi tên
scanf("%d", &ptr->age);
🚀 Bài tập quản lý nhân viên
Hãy viết chương trình quản lý danh sách nhân viên sử dụng Struct và Cấp phát động với các yêu cầu:
- Thông tin: Họ tên, Mã nhân viên, Lương hàng tháng.
- Chức năng:
- Thêm nhân viên mới.
- Xóa nhân viên theo mã hoặc theo tên.
- Tìm kiếm thông tin nhân viên.
📝 Tóm tắt: Struct là công cụ mạnh mẽ để mô hình hóa các đối tượng trong thế giới thực vào mã nguồn. Việc kết hợp Struct với con trỏ và cấp phát động là kỹ năng then chốt để quản lý dữ liệu phức tạp trong các hệ thống nhúng có tài nguyên giới hạn.
Gợi ý bài tiếp theo: Thao tác đọc ghi File (File I/O). Chúng ta sẽ học cách lưu trữ dữ liệu bền vững xuống bộ nhớ.
Người thực hiện: Nguyễn Đình Tuấn
Email: tuannguyen.aiot@gmail.com | Website: aiots.vn