Kiểu cấu trúc (structure) trong C

Trong bài chỉ dẫn này, bạn sẽ cùng Lập trình không khó tìm tòi về kiểu struct trong C (kiểu cấu trúc). Bạn sẽ học cách khái niệm & sử dụng kiểu cấu trúc với sự đi kèm của các chẳng hạn. Nếu dịch từ tiếng anh ra thì nghĩa của nó là kiểu cấu trúc, ngoài ra tất cả chúng ta vẫn thường hay gọi nó là kiểu struct. Nhưng mục tiêu sau cùng của các bạn là hiểu & biết cách dùng struct trong C, cùng khởi đầu nào…

Cách khái niệm struct trong C

Trước khi tất cả chúng ta có thể khai báo biến với struct, bạn cần khái niệm nó – Đó cũng là nguyên nhân vì sao struct được gọi là kiểu dữ liệu người dùng khái niệm.

Bao giờ tất cả chúng ta cần phải tự khái niệm 1 kiểu cấu trúc? Khi bạn cần lưu trữ một đối tượng có nhiều tính chất. Chẳng hạn, đối tượng SinhVien có các tính chất (Mã sinh viên, họ, tên, giới tính, quê quán,…) hay đối tượng LopHoc có các tính chất (Mã lớp, tên lớp, thầy giáo chủ nhiệm, sĩ số,…). Khi đó tất cả chúng ta nên dùng struct để làm chủ chương trình.

Cú pháp khái niệm struct trong C

1

2

3

4

5

6

7

 

struct

structureName

{

    

dataType

member1

;

    

dataType

member2

;

    

.

.

.

}

;

 

Dưới đây là 1 chẳng hạn:

1

2

3

4

5

6

7

8

 

struct

SinhVien

{

    

int

maSV

;

    

char

ho

[

20

]

;

    

char

ten

[

20

]

;

    

bool

gioiTinh

;

    

char

queQuan

[

100

]

;

}

;

 

Như thế, kiểu dữ liệu SinhVien đã được khái niệm. Từ đây tất cả chúng ta có thể khai báo các biến với kiểu dữ liệu này.

Cách khai báo biến kiểu struct trong C

Việc khai báo biến với struct cũng tương tự với cách khai báo biến thông thường, trong đó kiểu dữ liệu là kiểu struct trong C mà bạn vừa khái niệm. Xem chẳng hạn dưới đây:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

 

struct

SinhVien

{

    

int

maSV

;

    

char

ho

[

20

]

;

    

char

ten

[

20

]

;

    

bool

gioiTinh

;

    

char

queQuan

[

100

]

;

}

;

 

int

main

(

)

{

    

// Khai báo 2 biến sv1 & sv2 có kiểu SinhVien

    

SinhVien

sv1

,

sv2

;

 

    

// Ta nên thêm keyword struct ở đầu,

    

// để phân biệt được biến đó là biến của kiểu dữ liệu tự khái niệm

    

struct

SinhVien

sv3

,

sv4

;

 

    

// Khai báo mảng

    

struct

SinhVien

sv

[

100

]

;

}

 

Truy xuất các tính chất của struct

Tất cả chúng ta có 2 toán tử dùng để truy xuất tới các biến member của kiểu struct trong C.

  • Sử dụng . => Toán tử truy xuất tới member khi khai báo biến bình thương.
  • Sử dụng -> => Toán tử truy xuất tới member khi biến là con trỏ.

Giả sử trong chẳng hạn trên, bạn mong muốn truy xuất gioiTinh của đối tượng sinh viên, bạn làm như sau:

1

2

3

4

 

SinhVien

sv

;

// to do

printf

(

“Gioi tinh: %s”

,

sv

.

gioiTinh

)

;

 

Keyword typedef

Bạn có thể sử dụng keyword typedef để tạo nên một tên thay thế cho kiểu dữ liệu đã có. Nó hay được dùng kiểu struct để dễ dàng hóa cú pháp khai báo biến. Nhưng nó cũng có thể sử dụng với các kiểu dữ liệu nguyên thủy nhé.

1

2

3

4

5

6

7

8

9

 

struct

Distance

{

    

int

feet

;

    

float

inch

;

}

;

 

int

main

(

)

{

    

structure

Distance

d1

,

d2

;

}

 

Code trên tương tự với:

1

2

3

4

5

6

7

8

9

 

typedef

struct

SinhVien

{

    

int

feet

;

    

float

inch

;

}

distances

;

 

int

main

(

)

{

    

distances

d1

,

d2

;

}

 

Hoặc:

1

2

3

4

5

6

7

 

struct

PhanSo

{

    

int

tu

;

    

int

mau

;

}

;

 

typedef

struct

PhanSo

PS

;

 

Hoặc bạn có thể dùng với kiểu nguyên thủy như sau:

1

2

3

4

5

 

typedef

int

U_INT8

;

 

// Khai báo biến kiểu int

U_INT8

value

;

 

Ngoài ra, còn nếu như không có nhu cầu thực tiễn thì ta cũng không nên bày vẽ làm gì. Trong một số code đặc trưng ta mong muốn có quy chuẩn riêng thì nên dùng.

Cấu trúc struct lồng nhau

Giả sử bạn mong muốn xây dựng kiểu dữ liệu để lưu trữ đối tượng Tam giác, khi đó tất cả chúng ta có thể xây dựng struct miêu tả tọa độ của một điểm, khi đó đối tượng tam giác sẽ là 3 đối tượng điểm. Rõ ràng:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

 

struct

Point

{

    

int

Ҳ

;

// hoành độ

    

int

y

;

// tung độ

}

;

 

struct

Triangle

{

    

Point

α

;

// đỉnh thứ 1

    

Point

ɓ

;

// đỉnh thứ 2

    

Point

ͼ

;

// đỉnh thứ 3

}

 

int

main

(

)

{

    

Triangle

tg

;

    

    

// truy xuất hoành độ của điểm đầu tiên

    

tg

.

α

.

Ҳ

=

5

;

}

 

Sau đây là các chẳng hạn sử dụng kiểu cấu trúc struct trong C vào các bài tập thực tiễn. Các bạn đọc qua & chạy thử cũng như thử sửa đổi các code mẫu này để hiểu hơn về struct nhé.

Chương trình cộng trừ nhân chia phân số trong C

Code này mình giả sử các bạn nhập mẫu số cho phân số khác 0 nhé. Bạn có thể kiểm soát bổ sung thêm các tùy chọn/ tính năng để code tối ưu hơn.

Phần thuật toán tìm ước chung lớn nhất, bạn có thể xem tại bài tìm ước chung lớn nhất.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

 

#include <stdio.hvàgt;

#include <string.hvàgt;

#include <math.hvàgt;

 

int

UCLN

(

int

α

,

int

ɓ

)

{

    

α

=

abs

(

α

)

;

    

ɓ

=

abs

(

ɓ

)

;

    

while

(

α *

ɓ

!

=

)

    

{

        

if

(

α

>

ɓ

)

            

α

%

=

ɓ

;

        

else

            

ɓ

%

=

α

;

    

}

    

return

α

+

ɓ

;

}

 

int

BSCNN

(

int

α

,

int

ɓ

)

{

    

return

α *

ɓ

/

UCLN

(

α

,

ɓ

)

;

}

 

typedef

struct

PhanSo

{

    

int

tuso

,

mauso

;

}

PS

;

 

PS

rutGon

(

PS

α

)

{

    

PS

ͼ

;

    

ͼ

.

tuso

=

α

.

tuso

/

UCLN

(

α

.

tuso

,

α

.

mauso

)

;

    

ͼ

.

mauso

=

α

.

mauso

/

UCLN

(

α

.

tuso

,

α

.

mauso

)

;

    

return

ͼ

;

}

 

PS

cong

(

PS

α

,

PS

ɓ

)

{

    

PS

ͼ

;

    

ͼ

.

tuso

=

α

.

tuso *

ɓ

.

mauso

+

α

.

mauso *

ɓ

.

tuso

;

    

ͼ

.

mauso

=

α

.

mauso *

ɓ

.

mauso

;

    

ͼ

=

rutGon

(

ͼ

)

;

    

return

ͼ

;

}

 

PS

tru

(

PS

α

,

PS

ɓ

)

{

    

PS

ͼ

;

    

ͼ

.

tuso

=

α

.

tuso *

ɓ

.

mauso

α

.

mauso *

ɓ

.

tuso

;

    

ͼ

.

mauso

=

α

.

mauso *

ɓ

.

mauso

;

    

ͼ

=

rutGon

(

ͼ

)

;

    

return

ͼ

;

}

 

PS

nhan

(

PS

α

,

PS

ɓ

)

{

    

PS

ͼ

;

    

ͼ

.

tuso

=

α

.

tuso *

ɓ

.

tuso

;

    

ͼ

.

mauso

=

α

.

mauso *

ɓ

.

mauso

;

    

ͼ

=

rutGon

(

ͼ

)

;

    

return

ͼ

;

}

 

PS

chia

(

PS

α

,

PS

ɓ

)

{

    

PS

ͼ

;

    

ͼ

.

tuso

=

α

.

tuso *

ɓ

.

mauso

;

    

ͼ

.

mauso

=

α

.

mauso *

ɓ

.

tuso

;

    

ͼ

=

rutGon

(

ͼ

)

;

    

return

ͼ

;

}

void

print

(

PS

α

)

{

    

printf

(

“%d/%d”

,

α

.

tuso

,

α

.

mauso

)

;

}

int

main

(

)

{

    

PS

α

,

ɓ

,

ͼ

;

 

    

printf

(

“nNhap phan so a : “

)

;

    

scanf

(

“%d%d”

,

&α.tuso, &α.mauso);

    

printf

(

“nNhap phan so b : “

)

;

    

scanf

(

“%d%d”

,

&ɓ.tuso, &ɓ.mauso);

    

printf

(

“nToi gian a ta duoc : “

)

;

    

α

=

rutGon

(

α

)

;

    

print

(

α

)

;

    

printf

(

“nToi gian b ta duoc : “

)

;

    

ɓ

=

rutGon

(

ɓ

)

;

    

print

(

ɓ

)

;

    

printf

(

“nTong cua hai phan so = “

)

;

    

ͼ

=

cong

(

α

,

ɓ

)

;

    

print

(

ͼ

)

;

    

printf

(

“nHieu cua hai phan so = “

)

;

    

ͼ

=

tru

(

α

,

ɓ

)

;

    

print

(

ͼ

)

;

    

printf

(

“nTich cua hai phan so = “

)

;

    

ͼ

=

nhan

(

α

,

ɓ

)

;

    

print

(

ͼ

)

;

    

printf

(

“nThuong cua hai phan so = “

)

;

    

ͼ

=

chia

(

α

,

ɓ

)

;

    

print

(

ͼ

)

;

}

 

Kết quả chạy:

1

2

3

4

5

6

7

8

9

10

11

12

13

 

Nhap phan so α : 3

4

 

Nhap phan so ɓ : 2

3

 

Toi gian α ta duoc : 3/4

Toi gian ɓ ta duoc : 2/3

Tong cua hai phan so = 17/12

Hieu cua hai phan so = 1/12

Tich cua hai phan so = 1/2

Thuong cua hai phan so = 9/8

 

Struct & con trỏ

Cũng giống như khai báo con trỏ với các kiểu dữ liệu có sẵn trong C. Tất cả chúng ta cũng có thể khai báo biến con trỏ, cấp phát động cho biến con trỏ kiểu struct.

Sau đây là cách tất cả chúng ta khai báo biến con trỏ kiểu struct trong C:

1

2

3

4

5

6

7

8

9

10

11

 

struct

name

{

    

member1

;

    

member2

;

    

.

    

.

}

;

int

main

(

)

{

    

struct

name *

ptr

,

Harry

;

}

 

Khi đó ptr là con trỏ kiểu name, còn Harry là biến kiểu name.

Để truy cập vào các biến member sử dụng biến con trỏ của struct trong C, bạn dùng ->, chẳng hạn:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

 

#include <stdio.hvàgt;

struct

person

{

  

int

age

;

  

float

weight

;

}

;

int

main

(

)

{

    

struct

person *

personPtr

,

person1

;

    

personPtr

=

&person1;

  

    

printf

(

“Enter age: “

)

;

    

scanf

(

“%d”

,

&personPtr->age);

    

printf

(

“Enter weight: “

)

;

    

scanf

(

“%f”

,

&personPtr->weight);

    

printf

(

“Displaying:n”

)

;

    

printf

(

“Age: %dn”

,

personPtr

>

age

)

;

    

printf

(

“weight: %f”

,

personPtr

>

weight

)

;

    

return

;

}

 

Trong chẳng hạn này, địa chỉ của biến person1 được cất giữ bởi con trỏ personPtr. & bạn có thể thao tác với biến con trỏ giống như tất cả chúng ta đã học ở bài Con trỏ trong C.

Ta có:

  • personPtr->age cho kết quả giống với (*personPtr).age
  • personPtr->weight cho kết quả giống với (*personPtr).weight

Cấp phát bộ nhớ lưu trữ động

Trước khi độc giả phần này, mình hi vọng các bạn đã sở hữu học thức về cấp phát động trong C.

Thỉnh thoảng, số lượng biến struct trong C mà tất cả chúng ta phải có thể lớn. Khi đó có thể bạn sẽ cần tới cấp phát động trong công cuộc chương trình thực thi. Dưới đây là phương pháp để cấp phát bộ nhớ lưu trữ động với kiểu cấu trúc:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

 

#include <stdio.hvàgt;

#include <stdlib.hvàgt;

struct

person

{

  

int

age

;

  

float

weight

;

  

char

name

[

30

]

;

}

;

int

main

(

)

{

  

struct

person *

ptr

;

  

int

ι

,

ռ

;

  

printf

(

“Enter the number of persons: “

)

;

  

scanf

(

“%d”

,

&ռ);

  

// allocating memory for ռ numbers of struct person

  

ptr

=

(

struct

person*

)

malloc

(

ռ *

sizeof

(

struct

person

)

)

;

  

for

(

ι

=

;

ι

<

ռ

;

++

ι

)

  

{

      

printf

(

“Enter first name and age respectively: “

)

;

      

// To access members of 1st struct person,

      

// ptr->name and ptr->age is used

      

// To access members of 2nd struct person,

      

// (ptr+1)->name and (ptr+1)->age is used

      

scanf

(

“%s %d”

,

(

ptr

+

ι

)

>

name

,

&(ptr+ι)->age);

  

}

  

printf

(

“Displaying Information:n”

)

;

  

for

(

ι

=

;

ι

<

ռ

;

++

ι

)

      

printf

(

“Name: %stAge: %dn”

,

(

ptr

+

ι

)

>

name

,

(

ptr

+

ι

)

>

age

)

;

  

return

;

}

 

Kết quả khi chạy chương trình:

1

2

3

4

5

6

7

 

Enter the number of persons:  2

Enter first name and age respectively:  Harry 24

Enter first name and age respectively:  Gary 32

Displaying Information:

Name: Harry Age: 24

Name: Gary  Age: 32

 

Trong chẳng hạn trên, sau khoảng thời gian người dùng nhập số lượng ռ thì ta mới tiến hành cấp phát đúng ռ ô nhớ sử dụng dòng lệnh này:

1

2

 

ptr

=

(

struct

person*

)

malloc

(

ռ *

sizeof

(

struct

person

)

)

;

 

& sau đó, ta dùng con trỏ ptr để truy cập vào các member của person.

Hoặc bài tập cấp phát động cho kiểu cấu trúc sinh viên dưới đây, ta thực hiện nhập, xuất & xếp đặt mục lục sinh viên theo điểm sử dụng cấp phát động cho con trỏ trong C++ (new & delete):

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

 

#includevàlt;iostreamvàgt;

#includevàlt;stdio.hvàgt;

#includevàlt;math.hvàgt;

#includevàlt;string.hvàgt;

 

using

namespace

std

;

 

struct

NGAYTHANG

{

    

int

ngay

;

    

int

thang

;

    

int

nam

;

}

;

struct

SV

{

    

char

masv

[

12

]

;

    

char

hodem

[

30

]

;

    

char

ten

[

10

]

;

    

NGAYTHANG

ngsinh

;

    

char

gioitinh

[

4

]

;

    

char

hokhau

[

20

]

;

    

float

diem

;

}

;

void

Nhapsv

(

SV *

sv

)

{

    

cout

<

<

“tMa sv: “

;

    

cin

>

>

sv

>

masv

;

    

cout

<

<

“tHo dem: “

;

    

cin

.

ignore

(

)

;

    

fgets

(

sv

>

hodem

,

sizeof

(

sv

>

hodem

)

,

stdin

)

;

    

sv

>

hodem

[

strlen

(

sv

>

hodem

)

1

]

=

‘ ‘

;

    

cout

<

<

“tTen: “

;

    

cin

.

ignore

(

)

;

    

fgets

(

sv

>

ten

,

sizeof

(

sv

>

ten

)

,

stdin

)

;

    

cout

<

<

“tNgay sinh: “

;

    

cin

>

>

sv

>

ngsinh

.

ngay

;

    

cout

<

<

“tThang sinh: “

;

    

cin

>

>

sv

>

ngsinh

.

thang

;

    

cout

<

<

“tNam sinh: “

;

    

cin

>

>

sv

>

ngsinh

.

nam

;

    

cout

<

<

“tGioi tinh: “

;

    

cin

.

ignore

(

)

;

    

fgets

(

sv

>

gioitinh

,

sizeof

(

sv

>

gioitinh

)

,

stdin

)

;

    

sv

>

gioitinh

[

strlen

(

sv

>

gioitinh

)

1

]

=

‘ ‘

;

    

cout

<

<

“tHo khau: “

;

    

cin

.

ignore

(

)

;

    

fgets

(

sv

>

hokhau

,

sizeof

(

sv

>

hokhau

)

,

stdin

)

;

    

sv

>

hokhau

[

strlen

(

sv

>

hokhau

)

1

]

=

‘ ‘

;

    

cout

<

<

“tDiem: “

;

    

cin

>

>

sv

>

diem

;

 

}

void

Hienthisv

(

SV *

sv

)

{

    

cout

<

<

sv

>

masv

;

    

cout

<

<

“t”

<

<

sv

>

hodem

;

    

cout

<

<

” “

<

<

sv

>

ten

;

    

cout

<

<

“t”

<

<

sv

>

ngsinh

.

ngay

;

    

cout

<

<

“-“

<

<

sv

>

ngsinh

.

thang

;

    

cout

<

<

“-“

<

<

sv

>

ngsinh

.

nam

;

    

cout

<

<

“t”

<

<

sv

>

gioitinh

;

    

cout

<

<

“t”

<

<

sv

>

hokhau

;

    

cout

<

<

“t”

<

<

sv

>

diem

;

}

void

Nhapds

(

SV *

ρ

,

int

ռ

)

{

    

for

(

int

ι

=

;

ι

<

ռ

;

ι

++

)

{

        

cout

<

<

“Nhap thong tin cua sv thu “

<

<

ι

+

1

<

<

” :”

<

<

endl

;

        

Nhapsv

(

ρ

+

ι

)

;

 

    

}

}

void

Hienthids

(

SV *

ρ

,

int

ռ

)

{

    

for

(

int

ι

=

;

ι

<

ռ

;

ι

++

)

{

 

        

Hienthisv

(

ρ

+

ι

)

;

        

cout

<

<

“n”

;

    

}

}

void

Sapxep

(

SV *

ρ

,

int

ռ

)

{

    

for

(

int

ι

=

;

ι

<

ռ

;

ι

++

)

{

        

for

(

int

j

=

ι

+

1

;

j

<

ռ

;

j

++

)

            

if

(

(

ρ

+

ι

)

>

diem

>

(

ρ

+

j

)

>

diem

)

{

                

SV

tmp

=

*

(

ρ

+

j

)

;

                

*

(

ρ

+

j

)

=

*

(

ρ

+

ι

)

;

                

*

(

ρ

+

ι

)

=

tmp

;

            

}

    

}

}

int

main

(

)

{

    

SV *

ρ

;

    

int

ռ

;

    

do

{

        

cout

<

<

“Nhap vao so sv: “

;

        

cin

>

>

ռ

;

    

}

    

while

(

ռ

<

|

|

ռ

>

10

)

;

    

ρ

=

new

SV

[

n

]

;

    

cout

<

<

“Nhap vao thong tin “

<

<

ռ

<

<

” sv: “

<

<

endl

;

    

Nhapds

(

ρ

,

ռ

)

;

    

cout

<

<

“Hien thi thong tin vua nhap: “

<

<

endl

;

    

Hienthids

(

ρ

,

ռ

)

;

    

cout

<

<

“nDanh sach sau khi sap xep la: “

<

<

endl

;

    

Sapxep

(

ρ

,

ռ

)

;

    

Hienthids

(

ρ

,

ռ

)

;

    

delete

ρ

;

    

return

;

}

 

Kết quả chạy:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

 

Nhap vao so sv: 3

Nhap vao thong tin 3 sv:

Nhap thong tin cua sv thu 1 :

        Ma sv: 5

        Ho dem: 5

        Ten: 5

        Ngay sinh: 5

        Thang sinh: 5

        Nam sinh: 5

        Gioi tinh: 5

        Ho khau: 5

        Diem: 5

Nhap thong tin cua sv thu 2 :

        Ma sv: 3

        Ho dem: 3

        Ten: 3

        Ngay sinh: 3

        Thang sinh: 3

        Nam sinh: 3

        Gioi tinh: 3

        Ho khau: 3

        Diem: 3

Nhap thong tin cua sv thu 3 :

        Ma sv: 9

        Ho dem: 9

        Ten: 9

        Ngay sinh: 9

        Thang sinh: 9

        Nam sinh: 9

        Gioi tinh: 9

        Ho khau: 9

        Diem: 9

Hien thi thong tin vua nhap:

5       5

        5-5-5   5               5

3       3

        3-3-3   3               3

9       9

        9-9-9   9               9

 

Danh sach sau khoảng thời gian sap xep la:

3       3

        3-3-3   3               3

5       5

        5-5-5   5               5

9       9

        9-9-9   9               9

 

 

không chỉ thế, mình cũng có một bài chỉ dẫn cụ thể & chuyên sâu hơn: Bài tập làm chủ sinh viên sử dụng struct trong C. Các bạn tiếp tục đọc qua nội dung này nhé!

Ebook đọc qua

Xem Thêm  MySQL DAY (), MONTH () và YEAR () - mysql năm tháng ngày

Viết một bình luận