Thứ Ba, 28 tháng 9, 2021

15: Cấu trúc dữ liệu Struct và cách dùng Typedef trong C

Cấu trúc dữ liệu là gì

Trong quá trình xây dựng ứng dụng, ngoài các kiểu dữ liệu do ngôn ngữ lập trình C hỗ trợ, thì C còn cho phép các lập trình viên có thể tự định nghĩa các kiểu dữ liệu riêng của mình. Các kiểu dữ liệu này được gọi là kiểu dữ liệu do người dùng định nghĩa “Kiểu dữ liệu người dùng” hay kiểu dữ liệu hướng người dùng.

Cấu trúc dữ liệu là một nhóm các phần tử dữ liệu được nhóm lại với nhau trong một tên. Các phần tử dữ liệu này còn được gọi là các thành viên, có thể là các kiểu dữ liệu khác nhau và độ dài khác nhau.

Ví dụ như SinhVien là một tập dữ liệu bao gồm : Tên, ngày sinh, giới tính và số điện thoại, cân nặng … Các phần tử này có thể khác nhau về mặt dữ liệu, thế nên không thể sử dụng 1 kiểu dữ liệu đơn thuần để lưu được.

Khai báo dữ liệu cấu trúc Struct





Cú pháp khai báo


struct [ten cau truc] 

    phan dinh nghia thanh vien; 

    phan dinh nghia thanh vien; 

    ... 

    phan dinh nghia thanh vien; 

} [mot hoac nhieu bien cau truc];


Ví dụ, khai báo kiểu dữ liệu sinh viên, nhưng ko tạo ra biến nào.


struct SinhVien {

    int maSV;

    char ho[20];

    char ten[20];

    bool gioiTinh;

    char queQuan[100];

};


Để tạo ra 2 biến sinh viên 1 ta làm như sau:


struct SinhVien sv1, sv2;


Hoặc có thể khai báo luôn 2 biến đó, khi khai báo kiểu dữ liệu Struct


struct SinhVien

{

    int maSV;

    char ho[20];

    char ten[20];

    bool gioiTinh;

    char queQuan[100];

}sv1,sv2;


Khởi tạo giá trị ban đầu cho biến Struct

Struct có thể được khởi tạo qua nhiều cách khác nhau, điều này bao gồm cả việc như gán các hằng số giá trị cho các thành phần. Ngoài ra nếu không khởi tạo giá trị thì các biến có kiểu struct cũng sẽ khởi tạo theo kiểu không tường minh.

Ví dụ với các thành phần có kiểu integer và float sẽ tự thiết lập giá trị là 0, với char và string sẽ là ‘\0’.

Cấu trúc:


struct <structure_tag_name>

{

 <data_type member_name1>;

 <data_type member_name2>;  

}<structure_variable1> = {constant1,constant2, . .};


Ví dụ:


struct SinhVien

{

    int maSV;

    char ho[20];

    char ten[20];

    bool gioiTinh;

    char queQuan[100];

    float chieucao;

}sv1 = {1, "Nguyen", "Khue", "Nam", "ABCXYZ", 1,78};


Như trong ví dụ, trình biên dịch sẽ ngầm định giá trị phần từ từ trên xuống dưới tương ứng với giá trị từ trái sang phải. Nghĩa là maSV = 1, Họ = “Nguyen” …..

Ngoài ra chúng ta có thể khởi tạo một cách tường minh hơn đó là gán giá trị cho từng phần tử trong struct.

VD:


struct SinhVien

{

    int maSV;

    char ho[20];

    char ten[20];

    bool gioiTinh;

    char queQuan[100];

    float chieucao; 

}sv1 = {maSV = 1, ho = "Nguyen", ten = "Khue", gioitinh = "Nam", queQuan = "ABCXYZ", chieucao = 1.78};


Truy cập tới từng thành viên của Struct

Truy vấn từng thành viên trong biến bằng toán tử ” . “

Cú pháp:


< structure_variable >.< member_name > ;


VD:


struct myStruct

{

   int a;

   int b;

   int c;

} s1, s2;


Để truy vấn chúng là sử dụng : s1.a; s1.b

Xét theo kía cạnh lưu trữ trên bố nhớ (Giả sử int lưu trữ 2 bytes “thực tế có thể 4 bytes” và a, b, c được lưu trữ tại các ô nhớ liên tiếp “a, b, c không nhất thiết phải lưu trữ tại các ô nhớ liên tiếp” khi đó hình ảnh thể hiện như sau:




Truy cập vào từng phần tử trong Struct

Có thể thiết lập các giá trị cho các thành phần của struct.


s1.b = 12;


Để in giá trị các thành phần thì tùy thuộc vào kiểu dữ liệu của các thành ví dụ chúng ta muốn in thông tin của thành phần b thì chúng ta sử dụng câu lệnh :


printf(“%d”, s1.b);


Các thành phần có kiểu string, kiểu mảng thì chúng ta xử lý tương tự như chúng ta đã làm.


Con trỏ Struct

Một con trỏ trỏ đến cấu trúc hay biến con trỏ có kiểu cấu trúc (struct) chỉ đơn thuần là con trỏ đó trỏ đến địa chỉ của cấu trúc đó. Lưu ý con trỏ có kiểu struct không thể tự biến đổi biến con trỏ đó thành struct được.

Cú pháp:


struct <structure_tag_name >   /* Khai báo cấu trúc */

{

  <data_type member_name_1>;

  <data_type member_name_2>;

    .

    .

  <data_type member_name_n>;

} *ptr;


Để truy vấn đến các thành phần của cấu trúc. Chúng ta sử dụng cú pháp sau :

Cú pháp


(*ptr).member_name;


Hoặc


ptr-> member_name;


Copy và so sánh Struct

Một biến được khai báo có kiểu struct có thể gán cho một biến khác có cùng kiểu struct.

Ví dụ:


struct employee

{

  char grade;

  int basic;

  float allowance;

};

struct employee nam={‘b’, 6500, 812.5};

struct employee hung;

hung = nam; // Thực hiện phép gán biến hung = nam


Thực chất khi thực hiện phép gán hung = nam đó chính là quá trình sao chép dữ liệu các thành phần tương ứng của nam cho hung.


Phép so sánh cũng tương tự


Từ khóa typedef

Từ khóa typedef cho phép lập trình viên định nghĩa kiểu dữ liệu mới từ kiểu dữ liệu đã có trong chương trình.

Cú pháp


typedef <existing data type> <new data type ,….>;


Trong đó

  • existing data type : Kiểu dữ liệu đã tồn tại trong chương trình
  • new data type : Kiểu dữ liệu mới

VD:


typedef struct

{

    int maSV;

    char ho[20];

    char ten[20];

    bool gioiTinh;

    char queQuan[100];

}SinhVien;


Khi khai báo, chúng ta sẽ sử dụng.


SinhVien Sv1;

SinhVien Sv2;


Trong lập trình, nhiều khi các bạn sẽ thấy người ta sử dụng kiểu dữ liệu uint8_t, uint16_t, uint32_1, …. đó là kiểu dữ liệu được định nghĩa là từ unsigned int, unsigned long, ….

0 bình luận:

Đăng nhận xét