ĐẠI HỌC QUỐC GIA TP. HCHÍ MINH
TRƯỜNG ĐI HỌC CÔNG NGHTHÔNG TIN
IT001
-
NHẬP N LẬP TRÌNH
CHƯƠNG 9: CẤU TRÚC STRUCT
Khoa Khoa học Máy tính
N go à i nhng kiu d l i u cơ b n , t r o n g q u á trình xâ y d n g c h ư ơ n g tr ì n h , c h ún g t a c n p h i đ n h ng h ĩ a k i u d l i u
m i , đ ò i h i đ p h c t p ca o h ơ n . T r o n g ch ư ơ n g n à y, ch ú n g t a s đ ư c cu n g c p c á c ki ế n t h c c ơ b n v c á c h đ n h
ng h ĩ a m t ki u d li u m i v à cá c h s d n g c h ún g t r o n g l p tr ìn h. Ph n ki ế n t h c n à y s gi ú p c h ú n g ta hi u t t hơ n v
c á c ki u d li u c u tr ú c k h á c ( n h ư d a n h s á c h l i ê n kế t , c u tr ú c c â y ) v à p hư ơ n g p há p l p tr ì n h hư ng đ i tư n g .
Thực hiện bởi Trường Đại học Công nghệ Thông tin, ĐHQG-HCM
June 2024
1
9.1 Đặt vấn đề
9.2 Khai báo khởi tạo biến cấu trúc
9.3 Kích thước của cấu trúc
9.4 Truy xuất thuộc tính của kiểu cấu trúc
9.5 Phép Gán dữ liệu kiểu cấu trúc
9.6 Mảng cấu trúc, Cấu trúc phức hợp, Cấu trúc tự trỏ
9.7 Kiểu hợp nhất union
9.8 Cấu trúc và con trỏ
9.9 Truyền cấu trúc cho hàm
9.10 dụ minh họa
Bài tập
NỘI DUNG
Thực hiện bởi Trường Đại học Công nghệ Thông tin, ĐHQG-HCM
June 2024
2
9.1 Đt vn đ
Thực hiện bởi Trường Đại học Công nghệ Thông tin, ĐHQG-HCM June 2024
3
9.1 Đặt vấn đề
Thông tin 1 sinh viên (SV)
MSSV: kiểu chuỗi
Tên SV: kiểu chuỗi
Ngày tháng năm sinh: kiểu chuỗi
Giới tính: tự
Điểm toán, lý, Anh văn: số thực
Yêu cầu
Lưu thông tin cho N sinh viên ?
Truyền thông tin N sinh viên vào một hàm ?
Thực hiện bởi Trường Đại học Công nghệ Thông tin, ĐHQG-HCM June 2024
4
9.1 Đặt vấn đề
Khai báo các biến để lưu trữ 1 SV
char mssv[8]; // dụ: 07520045
char hoten[30]; // dụ: “Luong Bao Yen”
char ngaysinh[10]; // dụ: 27/05/1989
char gioitinh; // dụ:‘F’ Nữ (‘M’ Nam)
float toan, ly, anhvan; // dụ: Toán: 9.5, : 9.25, Anh: 10
Truyền thông tin 1 SV cho hàm:
void xuat(char mssv[], char hoten[], char ngaysinh[],
char gioitinh, float toan, float ly, float anhvan);
Thực hiện bởi Trường Đại học Công nghệ Thông tin, ĐHQG-HCM June 2024
5
9.1 Đặt vấn đề
Nhận xét:
Đặt tên biến khó khăn và khó quản lý
Truyền tham số cho hàm quá nhiều
Tìm kiếm, sắp xếp, sao chép,… khó khăn
Tốn nhiều bộ nhớ
Ý tưởng:
Gom những thông tin của cùng 1 SV thành một kiểu dữ liệu mới
Kiểu struct
Thực hiện bởi Trường Đại học Công nghệ Thông tin, ĐHQG-HCM June 2024
6
9.2 Khai báo và khi to biến cu trúc
Thực hiện bởi Trường Đại học Công nghệ Thông tin, ĐHQG-HCM June 2024
7
pháp 1:
Trong đó:
<tên_kiểu_cấu_trúc>: Đặt theo
tên/định danh
<kiểu_dữ_liệu>: kiểu dữ liệu
<tên_thành_phần_1>: tên biến có
<kiểu dữ liệu> tương ứng
<tên_biến>: biến có kiểu cấu trúc
Ví dụ:
struct Point {
float x, y;
};
struct Point A, B;
(lưu ý: C++ có thể bỏ từ khóa struct ở khai báo biến A, B)
struct NgaySinh {
int ngay, thang, nam;
};
NgaySinh date;
struct <tên_kiểu_cấu_trúc> {
<kiểu_dữ_liệu> <tên_thành_phần_1>;
<kiểu_dữ_liệu> <tên_thành_phần_n>;
};
<tên_kiểu_cấu_trúc> <tên_biến>;
Thực hiện bởi Trường Đại học Công nghệ Thông tin, ĐHQG-HCM June 2024
8
Sử dụng typedef
pháp 2:
dụ:
typedef struct {
<kiểu_dữ_liệu> <tên_thành_phần_1>;
<kiểu_dữ_liệu> <tên_thành_phần_n>;
} <tên_kiểu_cấu_trúc>;
<tên_kiểu_cấu_trúc> <tên_biến>;
typedef struct {
float x, y;
} Point;
Point A, B;
typedef struct {
int ngay, thang, nam;
} NgaySinh;
NgaySinh date;
Thực hiện bởi Trường Đại học Công nghệ Thông tin, ĐHQG-HCM June 2024
9
Khởi tạo cho biến cấu trúc
pháp 3:
dụ:
struct <tên kiểu cấu trúc> {
<kiểu dữ liệu> <tên thành phần 1>;
<kiểu dữ liệu> <tên thành phần n>;
} <tên biến> = {<giá_trị_1>, …, <giá_trị_n>};
struct Point {
float x, y;
} A = { 20.5, 10 }, B;
struct NgaySinh {
int ngay, thang, nam;
} date = {27, 5, 1989};
Thực hiện bởi Trường Đại học Công nghệ Thông tin, ĐHQG-HCM June 2024
10
Khởi tạo cho biến cấu trúc
pháp 4:
Lưu ý: Cấu trúc vừa khai báo sẽ chỉ được dùng để khai báo kiểu dữ liệu
cho các <tên_biến>.
dụ:
struct {
<kiểu dữ liệu> <tên thành phần 1>;
<kiểu dữ liệu> <tên thành phần n>;
} <tên biến>;
struct {
float x, y;
} A = { 20.5, 10 }, B;
// Với A, B là biến có cấu trúc gồm 2
thành phần float x, y;
struct {
int ngay, thang, nam;
} date = {27, 5, 1989}, date1;
// Với date, date1 là 2 biến có cấu trúc gồm 3
thành phần int ngay, thang, nam;
Thực hiện bởi Trường Đại học Công nghệ Thông tin, ĐHQG-HCM June 2024
11
9.3 Kích thưc ca cu trúc
Thực hiện bởi Trường Đại học Công nghệ Thông tin, ĐHQG-HCM June 2024
12
9.3 Kích thước của cấu trúc
struct B {
int a;
double b;
int c;
};
sizeof (B) = ??
struct C {
int a;
int b;
double c;
};
sizeof (C) = ??
Sự khác biệt đến từ thứ tự khai báo các biến biên kích thước (tính theo
byte) của cấu trúc.
Ví dụ:
24 bytes
struct A {
double a;
int b;
int c;
};
sizeof (A) = ??
16 bytes
a a a a b b b b
c
c
c c c c c c
a a a a a a a a
b
b
b b c c c c
a a a a padding
b
b
b b b b b b
c
c
c c padding
16 bytes
Thực hiện bởi Trường Đại học Công nghệ Thông tin, ĐHQG-HCM June 2024
13
9.3 Kích thước của cấu trúc
Hoặc tối ưu biên cho cấu trúc (alignment of struct). dụ trên nếu thay
đổi biên cấu trúc thành 1 hoặc 4 thì sizeof(B) = 16.
Điều chỉnh biên cấu trúc: Project settings Compile Option C/C++
Code Generation Structure Alignment.
Biên nhỏ mặc giúp giảm kích thước của cấu trúc nhưng làm tăng thời
gian xử của tác vụ memory allocator Cần điều phối thích hợp giữa
kích thước cấu trúc và tốc độ xử .
Chương trình dùng nhiều cấu trúc thành phần khác nhau điều chỉnh
biên tốt nhất sẽ khó khăn
Ưu tiên: tối ưu bằng cách khai báo thứ tự các thành phần cấu trúc
phù hợp với biên cấu trúc (tối ưu cục bộ trên cấu trúc)
Thực hiện bởi Trường Đại học Công nghệ Thông tin, ĐHQG-HCM June 2024
14
Chỉ thị #pragma pack
Chỉ thị #pragma pack(n)
n = 1, 2, 4, 8, 16 (byte)
Biên lớn nhất của các thành phần trong struct
BC n mặc định 1
VC++ n mặc định 8
Canh biên cho 1 cấu trúc:
#pragma pack(push, 1)
struct MYSTRUCT {
};
#pragma pack(pop)
Thực hiện bởi Trường Đại học Công nghệ Thông tin, ĐHQG-HCM June 2024
15
9.3 Kích thước của cấu trúc
// struct_not_pragm_pack.cpp
#include <iostream>
using namespace std;
// #pragma pack (1)
struct A { double x; int y; int z; } a;
struct B { int x; double y; int z; } b;
struct C { int x; int y; double z; } c;
int main() {
cout << "sizeof: " << sizeof(a) << "\t" << sizeof(b) << "\t" << sizeof(c) << endl;
cout << "Xuat dia chi:" << endl;
cout << "a : " << &(a.x) << "\t" << &(a.y) << "\t" << &(a.z) << endl;
cout << "b : " << &(b.x) << "\t" << &(b.y) << "\t" << &(b.z) << endl;
cout << "c : " << &(c.x) << "\t" << &(c.y) << "\t" << &(c.z) << endl;
return 0; }
Kết quả thực thi:
sizeof: 16 24 16
Xuat dia chi:
a : 0x407030 0x407038 0x40703c
b : 0x407040 0x407048 0x407050
c : 0x407060 0x407064 0x407068
Thực hiện bởi Trường Đại học Công nghệ Thông tin, ĐHQG-HCM June 2024
16
9.3 Kích thước của cấu trúc
// struct_pragma.cpp
#include <iostream>
using namespace std;
#pragma pack (1)
struct A { double x; int y; int z; } a;
struct B { int x; double y; int z; } b;
struct C { int x; int y; double z; } c;
int main() {
cout << "sizeof: " << sizeof(a) << "\t" << sizeof(b) << "\t" << sizeof(c) << endl;
cout << "Xuat dia chi:" << endl;
cout << "a : " << &(a.x) << "\t" << &(a.y) << "\t" << &(a.z) << endl;
cout << "b : " << &(b.x) << "\t" << &(b.y) << "\t" << &(b.z) << endl;
cout << "c : " << &(c.x) << "\t" << &(c.y) << "\t" << &(c.z) << endl;
return 0; }
Kết quả thực thi:
sizeof: 16 16 16
Xuat dia chi:
a : 0x407030 0x407038 0x40703c
b : 0x407040 0x407044 0x40704c
c : 0x407050 0x407054 0x407058
Thực hiện bởi Trường Đại học Công nghệ Thông tin, ĐHQG-HCM June 2024
17
9.4 Truy xut thuc tính ca kiu cu trúc
Thực hiện bởi Trường Đại học Công nghệ Thông tin, ĐHQG-HCM June 2024
18
9.4 Truy xuất thuộc nh của kiểu cấu trúc
Đặc điểm: Các trường dữ liệu trong cấu trúc Không thể truy xuất trực tiếp
phải thông qua biến cấu trúc.
Các biến cấu trúc truy xuất dữ liệu thông qua toán tử thành phần cấu trúc
“.” hay còn gọi toán tử chấm (dot operation)
Ví dụ:
<tên_biến_cấu_trúc>.<tên_thành_phần>
struct Point {
float x, y;
} A;
cout << A.x;
cout << A.y;
Thực hiện bởi Trường Đại học Công nghệ Thông tin, ĐHQG-HCM June 2024
19
9.4 Truy xuất thuộc nh của kiểu cấu trúc
Biến cấu trúc kiểu con trỏ:
Thông qua toán tử thành phần cấu trúc -> hay còn gọi toán tử dấu
mũi tên (arrow operation)
dụ:
<tên_biến_cấu_trúc> -> <tên_thành_phần>
struct Point {
float x, y;
} *A;
cout << A->x;
cout << A->y;
Thực hiện bởi Trường Đại học Công nghệ Thông tin, ĐHQG-HCM June 2024
* Lưu ý biến con trỏ A cần xác
định được vùng nhớ tr đến
trươc khi truy xuất các thuộc
tính của A.
20

Preview text:

ĐẠI HỌC QUỐC GIA TP. HỒ CHÍ MINH
TRƯỜNG ĐẠI HỌC CÔNG NGHỆ THÔNG TIN
IT001 - NHẬP MÔN LẬP TRÌNH
CHƯƠNG 9: CẤU TRÚC STRUCT
N g o à i n h ữ n g k i ể u d ữ l i ệ u c ơ b ả n , t r o n g q u á t r ì n h x â y d ự n g c h ư ơ n g t r ì n h , c h ú n g t a c ầ n p h ả i đ ị n h n g h ĩ a k i ể u d ữ l i ệ u
m ớ i , đ ò i h ỏ i đ ộ p h ứ c t ạ p c a o h ơ n . T r o n g c h ư ơ n g n à y , c h ú n g t a s ẽ đ ư ợ c c u n g c ấ p c á c k i ế n t h ứ c c ơ b ả n v ề c á c h đ ị n h
n g h ĩ a m ộ t k i ể u d ữ l i ệ u m ớ i v à c á c h s ử d ụ n g c h ú n g t r o n g l ậ p t r ì n h . P h ầ n k i ế n t h ứ c n à y s ẽ g i ú p c h ú n g t a h i ể u t ố t h ơ n v ề
c á c k i ể u d ữ l i ệ u c ấ u t r ú c k h á c ( n h ư d a n h s á c h l i ê n k ế t , c ấ u t r ú c c â y ) v à p h ư ơ n g p h á p l ậ p t r ì n h h ư ớ n g đ ố i t ư ợ n g .
Khoa Khoa học Máy tính
Thực hiện bởi Trường Đại học Công nghệ Thông tin, ĐHQG-HCM June 2024 1 NỘI DUNG 9.1 Đặt vấn đề
9.2 Khai báo và khởi tạo biến cấu trúc
9.3 Kích thước của cấu trúc
9.4 Truy xuất thuộc tính của kiểu cấu trúc
9.5 Phép Gán dữ liệu kiểu cấu trúc
9.6 Mảng cấu trúc, Cấu trúc phức hợp, Cấu trúc tự trỏ 9.7 Kiểu hợp nhất union 9.8 Cấu trúc và con trỏ
9.9 Truyền cấu trúc cho hàm 9.10 Ví dụ minh họa Bài tập June 2024
Thực hiện bởi Trường Đại học Công nghệ Thông tin, ĐHQG-HCM 2 9.1 Đặt vấn đề
Thực hiện bởi Trường Đại học Công nghệ Thông tin, ĐHQG-HCM June 2024 3 9.1 Đặt vấn đề
• Thông tin 1 sinh viên (SV) • MSSV: kiểu chuỗi • Tên SV: kiểu chuỗi
• Ngày tháng năm sinh: kiểu chuỗi • Giới tính: ký tự
• Điểm toán, lý, Anh văn: số thực • Yêu cầu
• Lưu thông tin cho N sinh viên ?
• Truyền thông tin N sinh viên vào một hàm ?
Thực hiện bởi Trường Đại học Công nghệ Thông tin, ĐHQG-HCM June 2024 4 9.1 Đặt vấn đề
• Khai báo các biến để lưu trữ 1 SV char mssv[8]; // Ví dụ: “07520045” char hoten[30];
// Ví dụ: “Luong Bao Yen” char ngaysinh[10]; // Ví dụ: “27/05/1989” char gioitinh;
// Ví dụ:‘F’ → Nữ (‘M’ →Nam)
float toan, ly, anhvan; // Ví dụ: Toán: 9.5, Lý: 9.25, Anh: 10
• Truyền thông tin 1 SV cho hàm:
void xuat(char mssv[], char hoten[], char ngaysinh[],
char gioitinh, float toan, float ly, float anhvan);
Thực hiện bởi Trường Đại học Công nghệ Thông tin, ĐHQG-HCM June 2024 5 9.1 Đặt vấn đềNhận xét:
• Đặt tên biến khó khăn và khó quản lý
• Truyền tham số cho hàm quá nhiều
• Tìm kiếm, sắp xếp, sao chép,… khó khăn • Tốn nhiều bộ nhớ • … • Ý tưởng:
• Gom những thông tin của cùng 1 SV thành một kiểu dữ liệu mới ➔ Kiểu struct
Thực hiện bởi Trường Đại học Công nghệ Thông tin, ĐHQG-HCM June 2024 6
9.2 Khai báo và khởi tạo biến cấu trúc
Thực hiện bởi Trường Đại học Công nghệ Thông tin, ĐHQG-HCM June 2024 7 Khai báo cấu trúcCú pháp 1:Ví dụ: struct { struct Point { ; float x, y; … ; }; }; struct Point A, B; ;
(lưu ý: C++ có thể bỏ từ khóa struct ở khai báo biến A, B) • Trong đó: • : Đặt theo struct NgaySinh { tên/định danh • : kiểu dữ liệu int ngay, thang, nam; • : tên biến có }; tương ứng NgaySinh date;
• : biến có kiểu cấu trúc
Thực hiện bởi Trường Đại học Công nghệ Thông tin, ĐHQG-HCM June 2024 8 Sử dụng typedefCú pháp 2: typedef struct { ; … ; } ; ; • Ví dụ: typedef struct { typedef struct { float x, y; int ngay, thang, nam; } Point; } NgaySinh; Point A, B; NgaySinh date;
Thực hiện bởi Trường Đại học Công nghệ Thông tin, ĐHQG-HCM June 2024 9
Khởi tạo cho biến cấu trúcCú pháp 3: struct { ; … ; } = {, …, }; • Ví dụ: struct Point { struct NgaySinh { float x, y; int ngay, thang, nam; } A = { 20.5, 10 }, B; } date = {27, 5, 1989};
Thực hiện bởi Trường Đại học Công nghệ Thông tin, ĐHQG-HCM June 2024 10
Khởi tạo cho biến cấu trúc
Cú pháp 4: struct { ; … ; } ;
Lưu ý: Cấu trúc vừa khai báo sẽ chỉ được dùng để khai báo kiểu dữ liệu cho các . • Ví dụ: struct { struct { float x, y; int ngay, thang, nam; } A = { 20.5, 10 }, B; } date = {27, 5, 1989}, date1;
// Với A, B là biến có cấu trúc gồm 2
// Với date, date1 là 2 biến có cấu trúc gồm 3 thành phần float x, y;
thành phần int ngay, thang, nam;
Thực hiện bởi Trường Đại học Công nghệ Thông tin, ĐHQG-HCM June 2024 11
9.3 Kích thước của cấu trúc
Thực hiện bởi Trường Đại học Công nghệ Thông tin, ĐHQG-HCM June 2024 12
9.3 Kích thước của cấu trúc • Ví dụ: struct A { struct B { struct C { double a; int a; int a; int b; double b; int b; int c; int c; double c; }; }; }; sizeof (A) = ?? 16 bytes sizeof (B) = ?? 24 bytes sizeof (C) = ?? 16 bytes a a a a padding a a a a a a a a a a a a b b b b b b b b b b b b b b b b c c c c c c c c c c c c c c c c padding
➔Sự khác biệt đến từ thứ tự khai báo các biến biên kích thước (tính theo byte) của cấu trúc.
Thực hiện bởi Trường Đại học Công nghệ Thông tin, ĐHQG-HCM June 2024 13
9.3 Kích thước của cấu trúc
• Hoặc tối ưu biên cho cấu trúc (alignment of struct). Ví dụ trên nếu thay
đổi biên cấu trúc thành 1 hoặc 4 thì sizeof(B) = 16.
• Điều chỉnh biên cấu trúc: Project settings → Compile Option C/C++
→ Code Generation → Structure Alignment.
• Biên nhỏ mặc dù giúp giảm kích thước của cấu trúc nhưng làm tăng thời
gian xử lý của tác vụ memory allocator ➔ Cần điều phối thích hợp giữa
kích thước cấu trúc và tốc độ xử lý.
• Chương trình dùng nhiều cấu trúc có thành phần khác nhau ➔ điều chỉnh
biên tốt nhất sẽ khó khăn
Ưu tiên: tối ưu bằng cách khai báo thứ tự các thành phần cấu trúc
phù hợp với biên cấu trúc (tối ưu cục bộ trên cấu trúc)
Thực hiện bởi Trường Đại học Công nghệ Thông tin, ĐHQG-HCM June 2024 14
Chỉ thị #pragma pack
• Chỉ thị #pragma pack(n) • n = 1, 2, 4, 8, 16 (byte)
• Biên lớn nhất của các thành phần trong struct • BC n mặc định là 1 • VC++ n mặc định là 8
• Canh biên cho 1 cấu trúc: #pragma pack(push, 1) struct MYSTRUCT { … }; #pragma pack(pop)
Thực hiện bởi Trường Đại học Công nghệ Thông tin, ĐHQG-HCM June 2024 15
9.3 Kích thước của cấu trúc // struct_not_pragm_pack.cpp Kết quả thực thi: #include using namespace std; sizeof: 16 24 16 // #pragma pack (1) Xuat dia chi:
struct A { double x; int y; int z; } a; a : 0x407030 0x407038 0x40703c
struct B { int x; double y; int z; } b;
b : 0x407040 0x407048 0x407050
struct C { int x; int y; double z; } c; c : 0x407060 0x407064 0x407068 int main() {
cout << "sizeof: " << sizeof(a) << "\t" << sizeof(b) << "\t" << sizeof(c) << endl;
cout << "Xuat dia chi:" << endl;
cout << "a : " << &(a.x) << "\t" << &(a.y) << "\t" << &(a.z) << endl;
cout << "b : " << &(b.x) << "\t" << &(b.y) << "\t" << &(b.z) << endl;
cout << "c : " << &(c.x) << "\t" << &(c.y) << "\t" << &(c.z) << endl; return 0; }
Thực hiện bởi Trường Đại học Công nghệ Thông tin, ĐHQG-HCM June 2024 16
9.3 Kích thước của cấu trúc // struct_pragma.cpp Kết quả thực thi: #include using namespace std; sizeof: 16 16 16 #pragma pack (1) Xuat dia chi:
struct A { double x; int y; int z; } a; a : 0x407030 0x407038 0x40703c
struct B { int x; double y; int z; } b;
b : 0x407040 0x407044 0x40704c
struct C { int x; int y; double z; } c; c : 0x407050 0x407054 0x407058 int main() {
cout << "sizeof: " << sizeof(a) << "\t" << sizeof(b) << "\t" << sizeof(c) << endl;
cout << "Xuat dia chi:" << endl;
cout << "a : " << &(a.x) << "\t" << &(a.y) << "\t" << &(a.z) << endl;
cout << "b : " << &(b.x) << "\t" << &(b.y) << "\t" << &(b.z) << endl;
cout << "c : " << &(c.x) << "\t" << &(c.y) << "\t" << &(c.z) << endl; return 0; }
Thực hiện bởi Trường Đại học Công nghệ Thông tin, ĐHQG-HCM June 2024 17
9.4 Truy xuất thuộc tính của kiểu cấu trúc
Thực hiện bởi Trường Đại học Công nghệ Thông tin, ĐHQG-HCM June 2024 18
9.4 Truy xuất thuộc tính của kiểu cấu trúc
Đặc điểm: Các trường dữ liệu trong cấu trúc Không thể truy xuất trực tiếp
mà phải thông qua biến cấu trúc.
• Các biến cấu trúc truy xuất dữ liệu thông qua toán tử thành phần cấu trúc
“.” hay còn gọi là toán tử chấm (dot operation) . • Ví dụ: struct Point { float x, y; } A; cout << A.x; cout << A.y;
Thực hiện bởi Trường Đại học Công nghệ Thông tin, ĐHQG-HCM June 2024 19
9.4 Truy xuất thuộc tính của kiểu cấu trúc
Biến cấu trúc kiểu con trỏ:
• Thông qua toán tử thành phần cấu trúc “->” hay còn gọi là toán tử dấu mũi tên (arrow operation) -> • Ví dụ: struct Point {
* Lưu ý biến con trỏ A cần xác float x, y;
định được vùng nhớ trỏ đến } *A;
trươc khi truy xuất các thuộc tính của A. cout << A->x; cout << A->y;
Thực hiện bởi Trường Đại học Công nghệ Thông tin, ĐHQG-HCM June 2024 20