Đếm xem trong mảng sinh viên có bao nhiêu người Ho nguyên

Cách đơn giản nhất để tiếp cận về kiểu cấu trúc là xét ví dụ sinh viên. Một lớp có 100 sinh viên mỗi sinh viên gồm họ tên và mã sinh viên. Hãy nhập dữ liệu cho lớp đó. Hehe. Bạn nghĩ đến cách dùng 2 mảng: 1 mảng lưu tên, 1 mảng lưu mã sinh viên đúng không. Đúng, cách đó không sai… nhưng hãy xem yêu cầu tiếp theo… Thi học kỳ xong, hãy nhập điểm cho từng sinh viên, mỗi sinh viên gồm 10 môn [Toán, Tin, Hóa, Vật lý,…]. Giờ bạn thấy sao nào… Dùng 12 mảng chăng… ồ không nên, hãy dùng kiểu cấu trúc. Với kiểu cấu trúc chỉ cần 1 mảng mà thôi.

1. Kiểu cấu trúc

Đối với mảng, chỉ có thể lưu nhiều thông tin có cùng kiểu dữ liệu. Nhưng với kiểu cấu trúc ta có thể lưu thông tin có nhiều kiểu dữ liệu khác nhau.

1.1 VD mở đầu

//code by nguyenvanquan7826 #include #include // khai bao struct struct sinhvien { char MSV[20]; // ma sinh vien char hoten[30]; // ho ten sinh vien double toan, tin, anh; // cac diem toan, tin, anh }; /* Hay thay tat ca fflush[stdin]; thanh __fpurge[stdin] khi ban lam tren linux*/ int main[] { /* khai bao 2 bien sv1, sv2 va 1 mang * CNPMK10A gom 100 sinh vien */ struct sinhvien sv1, sv2, CNPMK10A[100]; printf["Nhap du lieu cho sv1:\n"]; printf["MSV: "]; fflush[stdin]; gets[sv1.MSV]; printf["Ho ten: "]; fflush[stdin]; gets[sv1.hoten]; printf["Diem toan, tin, anh: "]; fflush[stdin]; scanf["%lf %lf %lf", &sv1.toan, &sv1.tin, &sv1.anh]; printf["Nhap du lieu cho sv2:\n"]; printf["MSV: "]; fflush[stdin]; gets[sv2.MSV]; printf["Ho ten: "]; fflush[stdin]; gets[sv2.hoten]; printf["Diem toan, tin, anh: "]; fflush[stdin]; scanf["%lf %lf %lf", &sv2.toan, &sv2.tin, &sv2.anh]; printf["\n --------- Thong tin sinh vien -----\n"]; printf["%-20s %-30s %-7s %-7s %-7s\n", "MSV", "Ho ten", "Toan", "Tin", "Anh"]; printf["%-20s %-30s %-7.2lf %-7.2lf %-7.2lf\n", sv1.MSV, sv1.hoten, sv1.toan, sv1.tin, sv1.anh]; printf["%-20s %-30s %-7.2lf %-7.2lf %-7.2lf\n", sv2.MSV, sv2.hoten, sv2.toan, sv2.tin, sv2.anh]; return 0; }

Kết quả:

Nhap du lieu cho sv1: MSV: DTC1 Ho ten: Pham Thi Ha Diem toan, tin, anh: 9 9 8 Nhap du lieu cho sv2: MSV: DTC2 Ho ten: Nguyen Van Quan Diem toan, tin, anh: 9 9 8 --------- Thong tin sinh vien ----- MSV Ho ten Toan Tin Anh DTC1 Pham Thi Ha 9.00 9.00 8.00 DTC2 Nguyen Van Quan 9.00 9.00 8.00

Ở VD mở đầu này, chúng ta có rất nhiều điểu phải bàn 🙂

1.2 Xây dựng kiểu cấu trúc, khai báo biến cấu trúc

Như VD trên, để xây dựng 1 kiểu cấu trúc ta thực hiện theo cú pháp:

struct TenKieuCauTruc { Khai báo các thành phần của kiểu; };

Sau khi có kiểu cấu trúc rồi thì cái kiểu đó nó tương tự như 1 kiểu bình thường [int, float, char,…] và ta chỉ việc khai báo biến nữa là xong. Tuy nhiên khai báo biến thì cần có thêm từ khóa struct ở trước: [Đối với C++ thì không cần].

struct TenKieuCauTruc TenBienCauTruc;

Ngoài ta chúng ta còn một số cách xây dựng kiểu cấu trúc và khai báo biến cấu trúc như sau:

struct TenKieuCauTruc { Khai báo các thành phần của kiểu; } danh sách các biến thuộc kiểu cấu trúc;

Hoặc

struct { Khai báo các thành phần của kiểu; } danh sách các biến thuộc kiểu cấu trúc ;

Với cách khai báo này, ta bắt buộc phải khai báo các biến cấu trúc ở ngay sau cấu trúc vì không có tên kiểu cấu trúc để cho ta khai báo ở các vị trí khác nữa.
Trong phần này ta cần đề cập đến 1 từ khóa quan trọng nữa, đó là typedef. Từ khóa này dùng để định nghĩa 1 kiểu dữ liệu mới.

typedef struct sinhvien { char MSV[20]; // ma sinh vien char hoten[30]; // ho ten sinh vien double toan, tin, anh; // cac diem toan, tin, anh } kieuSinhVien;

Khi này ta có kieuSinhVien là 1 kiểu dữ liệu [như int, double, …] và ta có thể khai báo các biến cấu trúc thông qua nó. Trong này có vài điều các bạn cần chú ý:

  • Với sinhvien [kiểu cấu trúc được đặt sau từ khóa struct] thì khi khai báo biến thuộc kiểu này ta vẫn phải có từ struct ở trước nó. [VD: sinhvien svA; -> Sai còn struct sinhvien svA; -> đúng], [chú ý trong C++ thì không cần].
  • Với kieuSinhVIen thì khi khai báo biến thuộc kiểu này ta không được có từ struct ở trước nó. [VD: struct kieuSinhVIen svA; -> sai, kieuSinhVIen svA; -> đúng].

Ngoài ra ta còn có thể khai báo kiểu cấu trúc lồng nhau: VD như trong 1 sinh viên có ngày sinh, trong ngày sinh lại có ngày, tháng, năm sinh.

struct ngaysinh { int ngay, thang, nam; } typedef struct sinhvien { char MSV[20]; // ma sinh vien char hoten[30]; // ho ten sinh vien double toan, tin, anh; // cac diem toan, tin, anh struct ngaysinh ns; } kieuSinhVien;

Hoặc ta khai báo ngay trong cấu trúc:

typedef struct sinhvien { char MSV[20]; // ma sinh vien char hoten[30]; // ho ten sinh vien double toan, tin, anh; // cac diem toan, tin, anh struct ngaysinh { int ngay, thang, nam; } ns; } kieuSinhVien;

1.3 Truy cập đên các thành phần của cấu trúc

Để truy nhập đến thành phần của cấu trúc ta sử dụng toán tử chấm [.].

TenBienCauTruc.TenThanhPhan;

Như VD trên ta truy cập như sau: sv1.hoten; sv1.toan; // truy xuất tới họ tên, điểm toán sv1.ns.ngay; sv1.ns.thang; // truy xuất tới ngày sinh và tháng sinh.

Khi đã truy xuất được tới các thành phần của cấu trúc thì mỗi thành phần đó là 1 biến bình thường và ta gán giá trị hoặc nhập xuất giá trị cho chúng như cách bình thường mà chúng ta vẫn làm.

Ngoài ra nếu thành phần nào đó dài dòng thì ta có thể tránh việc dài dòng này bằng cách sử dụng từ khóa define.
VD thay vì viết:

sv1.ns.thang; sv1.ns.nam;

Ta viết:

#define p sv1.ns p.thang; p.nam;

1.4 Gán các biến có cùng kiểu cấu trúc

//code by nguyenvanquan7826 #include #include struct sinhvien { char MSV[20]; // ma sinh vien char hoten[30]; // ho ten sinh vien double toan, tin, anh; // cac diem toan, tin, anh }; /* Hay thay tat ca fflush[stdin]; thanh __fpurge[stdin] khi ban lam tren linux*/ int main[] { /* khai bao 2 bien sv1, sv2 va 1 mang * CNPMK10A gom 100 sinh vien */ struct sinhvien sv1, sv2, CNPMK10A[100]; printf["Nhap du lieu cho sv1:\n"]; printf["MSV: "]; fflush[stdin]; gets[sv1.MSV]; printf["Ho ten: "]; fflush[stdin]; gets[sv1.hoten]; printf["Diem toan, tin, anh: "]; fflush[stdin]; scanf["%lf %lf %lf", &sv1.toan, &sv1.tin, &sv1.anh]; sv2 = sv1; // gan gia tri cua sv1 cho sv2 printf["\n --------- Thong tin sinh vien -----\n"]; printf["%-20s %-30s %-7s %-7s %-7s\n", "MSV", "Ho ten", "Toan", "Tin", "Anh"]; printf["%-20s %-30s %-7.2lf %-7.2lf %-7.2lf\n", sv2.MSV, sv2.hoten, sv2.toan, sv2.tin, sv2.anh]; return 0; }

Sau khi gán sv2 = sv1 thì mọi thông tin của sv1 có thì sv2 cũng có. Ngoài ra ta còn có thể gán giá trị khởi đầu cho cấu trúc.

struct sinhvien sv1 = {"ABC", "Nguyen Van Quan", 9, 9, 8, {4, 5, 1992}};

Khi đó ta có các dữ liệu ban đầu của sv1 là:

MSV: ABC hoten: Nguyen Van Quan toan: 9 tin: 9 anh: 8 ngày sinh: 4/5/1992.

2. Mảng cấu trúc

Bên trên ta đã tìm hiểu cơ bản về kiểu cấu trúc và một vài ví dụ về cấu trúc sinhvien. Bây giờ ta tìm hiểu cách biểu diễn 1 mảng 50 sinh viên của 1 lớp học có kiểu cấu trúc như trên. Ta xét VD:

//code by nguyenvanquan7826 #include #include struct sinhvien { char MSV[20]; // ma sinh vien char hoten[30]; // ho ten sinh vien double diemTB; // diem trung binh struct ngaysinh { int ngay, thang, nam; } ns; }; int main[] { int n = 2, i; struct sinhvien CNPMK10A[n]; for [i = 0; i < n; i++] { #define sv CNPMK10A[i] printf["Nhap du lieu cho sinh vien thu %d:\n", i + 1]; printf["MSV: "]; fflush[stdin] gets[sv.MSV]; printf["Ho ten: "]; fflush[stdin]; gets[sv.hoten]; printf["Diem TB: "]; fflush[stdin] scanf["%lf", &sv.diemTB]; printf["Ngay sinh: "]; scanf["%d/%d/%d", &sv.ns.ngay, &sv.ns.thang, &sv.ns.nam]; } printf["\n --------- Thong tin sinh vien -----\n"]; printf["%-20s %-30s %-7s %-10s\n", "MSV", "Ho ten", "Diem Tb", "Ngay sinh"]; for [i = 0; i < n; i++] { #define sv CNPMK10A[i] printf["%-20s %-30s %-7.2lf %02d/%02d/%4d\n", sv.MSV, sv.hoten, sv.diemTB, sv.ns.ngay, sv.ns.thang, sv.ns.nam]; } return 0; }

Kết quả:

Nhap du lieu cho sinh vien thu 1: MSV: DTC1 Ho ten: Pham Thi Ha Diem TB: 9.2 Ngay sinh: 21/01/1993 Nhap du lieu cho sinh vien thu 2: MSV: DTC2 Ho ten: Nguyen Van Quan Diem TB: 9.2 Ngay sinh: 31/12/1992 --------- Thong tin sinh vien ----- MSV Ho ten Diem Tb Ngay sinh DTC1 Pham Thi Ha 9.20 21/01/1993 DTC2 Nguyen Van Quan 9.20 31/12/1992

3. Con trỏ cấu trúc

//code by nguyenvanquan7826 #include #include struct sinhvien { char MSV[20]; // ma sinh vien char hoten[30]; // ho ten sinh vien double diemTB; // diem trung binh struct ngaysinh { int ngay, thang, nam; } ns; }; int main[] { int n = 2, i; // cap phat bo nho struct sinhvien *CNPMK10A = [struct sinhvien*] malloc[n * sizeof[struct sinhvien]]; for [i = 0; i < n; i++] { printf["Nhap du lieu cho sinh vien thu %d:\n", i + 1]; printf["MSV: "]; fflush[stdin]; gets[CNPMK10A[i].MSV]; printf["Ho ten: "]; fflush[stdin]; gets[CNPMK10A[i].hoten]; printf["Diem TB: "]; fflush[stdin]; scanf["%lf", &[CNPMK10A+i]->diemTB]; printf["Ngay sinh: "]; scanf["%d/%d/%d", &[CNPMK10A+i]->ns.ngay, &[CNPMK10A+i]->ns.thang, &[CNPMK10A+i]->ns.nam]; } printf["\n --------- Thong tin sinh vien -----\n"]; printf["%-20s %-30s %-7s %-10s\n", "MSV", "Ho ten", "Diem Tb", "Ngay sinh"]; for [i = 0; i < n; i++] { #define ns CNPMK10A[i].ns printf["%-20s %-30s %-7.2lf %02d/%02d/%4d\n", CNPMK10A[i].MSV, [*[CNPMK10A+i]].hoten, [CNPMK10A+i]->diemTB, ns.ngay, ns.thang, ns.nam]; } return 0; }

Truy cập các thành phần cấu trúc

Để truy cập để lấy dữ liệu các thành phần của con trỏ cấu trúc ta có 3 cách sau:

  • Cách 1: CNPMK10A[i].diemTB;
  • Cách 2: [*[CNPMK10A+i]].diemTB;
  • Cách 3: [CNPMK10A+i] ->diemTB;

Cả 3 cách trên đều truy cập tới DTB.

Để lấy địa chỉ ta cũng có 2 cách:

  • Cách 1: &CNPMK10A[i].DTB;
  • Cách 2: &[CNPMK10A+i]->diemTB

Video liên quan

Chủ Đề