Struct trong C – Kiểu cấu trúc trong C | Ironhack Việt Nam

1. Struct trong C

Trong phần này, bạn sẽ được tìm hiểu các kiểu struct trong C. Bên cạnh đó, bạn cũng được học cách định nghĩa và sử dụng các cấu trúc (ngôn ngữ lập trình C) thông qua các ví dụ.

Struct là gì? Kiểu struct trong C (hay cấu trúc trong C) chính là một tập hợp các biến (có thể có nhiều kiểu khác nhau) trong cùng một tên duy nhất.

kiểu struct trong c1.1 Làm thế nào để xác định cấu trúc trong C?

Trước khi tạo ra những biến cấu trúc trong C, bạn cần phải xác lập kiểu tài liệu của nó. Để định nghĩa cấu trúc trong C, bạn cầu sử dụng từ khóa struct .

Cú pháp của cấu trúc trong C (ngôn ngữ lập trình)

struct structureName
{
dataType member1 ;
dataType member2 ;

} ;
Dưới đây là ví dụ :
struct Person
{
char name [ 50 ] ;
int citNo ;
float salary ;
} ;
Kiểu dẫn xuất struct Person được định nghĩa. Lúc này, bạn hoàn toàn có thể tạo ra những biến thuộc kiểu này .

1.2 Tạo các biến cấu trúc trong C

Khi một kiểu struct C được khai báo, chúng không được cấp phép bộ nhớ hoặc bộ tàng trữ. Để cấp phép bộ nhớ cho kiểu cấu trúc này và thao tác với nó, bạn cần tạo thêm những biến .

Dưới đây là cách tôi tạo ra các biến struct trong C:

struct Person
{
char name [ 50 ] ;
int citNo ;
float salary ;
} ;
int main ( )
{
struct Person person1, person2, p [ 20 ] ;
return 0 ;
}
Có thể tạo biến cấu trúc trong C theo cách khác như sau :
struct Person
{
char name [ 50 ] ;
int citNo ;
float salary ;
} person1, person2, p [ 20 ] ;
Trong cả 2 trường hợp trên, 2 biến person1, person2, và biến mảng p có 20 thành phần thuộc kiểu struct Person được tạo ra .

1.3 Truy cập vào các thành viên của một cấu trúc

Sử dụng 2 kiểu toán tử dưới đây để truy vấn vào những thành viên của struct C .

  1. . – Toán tử thành viên dot
  2. -> –Toán tử thành viên arrow (sẽ được giới thiệu trong những phần tiếp theo)

Giả sử bạn muốn truy vấn vào salary của person2, bạn cần triển khai như sau :
person2.salary
Ví dụ : Thêm hai khoảng cách
/ / Program to add two distances ( feet-inch )

#include

struct Distance
{
int feet ;
float inch ;
} dist1, dist2, sum ;
int main ( )
{
printf ( “ 1 st distance \ n ” ) ;
printf ( “ Enter feet : “ ) ;
scanf ( “ % d ”, và dist1.feet ) ;
printf ( “ Enter inch : “ ) ;
scanf ( “ % f ”, và dist1.inch ) ;
printf ( “ 2 nd distance \ n ” ) ;
printf ( “ Enter feet : “ ) ;
scanf ( “ % d ”, và dist2.feet ) ;
printf ( “ Enter inch : “ ) ;
scanf ( “ % f ”, và dist2.inch ) ;
/ / adding feet
sum.feet = dist1.feet + dist2.feet ;
/ / adding inches
sum.inch = dist1.inch + dist2.inch ;
/ / changing to feet if inch is greater than 12
while ( sum.inch > = 12 )
{
+ + sum.feet ;
sum.inch = sum.inch – 12 ;
}
printf ( “ Sum of distances = % d \ ’ – %. 1 f \ ” ”, sum.feet, sum.inch ) ;
return 0 ;
}
Đầu ra
1 st distance
Enter feet : 12
Enter inch : 7.9
2 nd distance
Enter feet : 2
Enter inch : 9.8
Sum of distances = 15 ′ – 5.7 ″

1.4 Từ khóa typedef trong C

Tôi sử dụng từ khóa typedef trong C để tạo tên bí danh cho các kiểu dữ liệu. Nó thường được sử dụng với các kiểu cấu trúc trong C để làm đơn giản hóa cú pháp khai báo biến.

Mã dưới đây

struct Distance {
int feet ;
float inch ;
} ;
int main ( ) {
struct Distance d1, d2 ;
}
Tương đương với
typedef struct Distance {
int feet ;
float inch ;
} distances ;
int main ( ) {
distances d1, d2 ;
}

1.5 Cấu trúc Struct lồng nhau

Bạn hoàn toàn có thể tạo một cấu trúc lồng trong một cấu trúc khác trong lập trình C. Ví dụ ,
struct complex
{
int imag ;
float real ;
} ;
struct number
{
struct complex comp ;
int integers ;
} num1, num2 ;
Giả sử bạn muốn setup imag của biến num2 là 11. Dưới đây là phương pháp thực thi :
num2.comp.imag = 11 ;

1.6 Tại sao lại cần cấu trúc trong C?

Giả sử nếu bạn muốn tàng trữ thông tin về một người : tên, số CMND, mức lương. Bạn hoàn toàn có thể tạo ra những biến name, IdNo và salary khác nhau để tàng trữ những thông tin này .
Vậy nếu bạn muốn tàng trữ thông tin của nhiều người thì sao ? Trong trường hợp này, bạn cần tạo nhiều biến cho từng thông tin của từng người : name1, IdNo1, salary1, name2, IdNo2, salary2, …
Một cách tiếp cận tốt hơn chính là nên tạo ra một bộ sưu tập chứa những thông tin tương quan trong một cấu trúc đơn lé Person và sử dụng nó cho toàn bộ mọi người .

Tìm hiểu thêm về kiểu cấu trúc trong C:

  • Cấu trúc và biến pointer trong C
  • Truyền cấu trúc vào hàm

2. Cấu trúc và biến pointer trong C

Trong phần này, bạn sẽ được tìm hiểu và khám phá cách sử dụng biến con trỏ để truy vấn vào những thành viên của struct trong C. Bên cạnh đó, bạn cũng sẽ biết được cách cấp phép bộ nhớ một cách tự động hóa của những kiểu cấu trúc trong C .
Nhưng trước đó, bạn cần xem qua những phần dưới đây để khám phá biến pointer được sử dụng như thế nào với cấu trúc :

  • Biến pointer trong C
  • Cấu trúc trong C

2.1 Tạo biến pointer trỏ đến cấu trúc trong C

Dưới đây là cách mà bạn có thể tạo biến pointer trỏ đến struct trong C

struct name {
member1 ;
member2 ;
.
.
} ;
int main ( )
{
struct name * ptr, Harry ;
}
Trong trường hợp này, ptr là một biến pointer trỏ đến struct .

Ví dụ: Truy cập vào các thành viên bằng biến pointer

Để truy vấn vào những thành viên của một cấu trúc bằng cách sử dụng biến pointer, bạn cần sử dụng toán tử -> .

#include

struct person
{
int age ;
float weight ;
} ;
int main ( )
{
struct person * personPtr, person1 ;
personPtr = và person1
printf ( “ Enter age : “ ) ;
scanf ( “ % d ”, và personPtr -> age ) ;
printf ( “ Enter weight : “ ) ;
scanf ( “ % f ”, và personPtr -> weight ) ;
printf ( “ Displaying : \ n ” ) ;
printf ( “ Age : % d \ n ”, personPtr -> age ) ;
printf ( “ weight : % f ”, personPtr -> weight ) ;
return 0 ;
}
Trong ví dụ này, địa chỉ của person1 được tàng trữ trong biến pointer personPtr bằng cách sử dụng personPtr = và person1 .
Bây giờ, bạn hoàn toàn có thể truy vấn vào những thành viên của person1 bằng cách sử dụng biến pointer personPtr .
Bên cạnh đó ,

  • personPtr->age tương đương với (*personPtr).age
  • personPtr->weight tương đương với (*personPtr).weight

2.2 Cấp phát bộ nhớ động của cấu trúc

Trước khi tìm hiểu và khám phá phần này, tôi khuyên bạn nên xem lại phần cấp phép bộ nhớ động .
Đôi khi, số lượng biến cấu trúc mà bạn đã khai báo hoàn toàn có thể không đủ. Bạn cần cấp phát bộ nhớ trong quy trình lập trình chạy. Dưới đây là cách để thực thi điều đó trong lập trình C .

Ví dụ: Cấp phát bộ nhớ động của cấu trúc

#include

#include

struct person {
int age ;
float weight ;
char name [ 30 ] ;
} ;
int main ( )
{
struct person * ptr ;
int i, n ;
printf ( “ Enter the number of persons : “ ) ;
scanf ( “ % d ”, và n ) ;
/ / allocating memory for n numbers of struct person
ptr = ( struct person * ) malloc ( n * sizeof ( struct person ) ) ;
for ( i = 0 ; i < n ; + + i ) { printf ( “ Enter first name and age respectively : “ ) ; / / To access members of 1 st struct person , / / ptr -> name and ptr -> age is used
/ / To access members of 2 nd struct person ,
/ / ( ptr + 1 ) -> name and ( ptr + 1 ) -> age is used
scanf ( “ % s % d ”, ( ptr + i ) -> name, và ( ptr + i ) -> age ) ;
}
printf ( “ Displaying Information : \ n ” ) ;
for ( i = 0 ; i < n ; + + i ) printf ( “ Name : % s \ tAge : % d \ n ”, ( ptr + i ) -> name, ( ptr + i ) -> age ) ;
return 0 ;
}
Khi bạn chạy lập trình, tác dụng đầu ra sẽ là :
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 ví dụ này, n biến cấu trúc được tạo ra. Lưu ý, n là do người dùng nhập vào .
Để cấp phép bộ nhớ cho n biến struct person, tôi đã sử dụng ,
ptr = ( struct person * ) malloc ( n * sizeof ( struct person ) ) ;
Sau đó, tôi sử dụng biến pointer ptr để truy vấn vào những thành phần của person .

3. Cấu trúc và hàm trong lập trình C

Trong phần này, bạn sẽ được khám phá về cách truyền biến cấu trúc dưới dạng đối số vào hàm. Bên cạnh đó, bạn cũng sẽ biết được cách lấy lại cấu trúc từ hàm trải qua những ví dụ .
Tương tự như những biến thuộc kiểu kiến thiết xây dựng sẵn, bạn cũng hoàn toàn có thể truyền những biến struct trong C vào hàm .

3.1 Truyền cấu trúc vào hàm

Trước tiên, bạn cần xem lại những phần dưới đây trước khi tìm hiểu và khám phá cách truyền cấu trúc vào hàm

  • Cấu trúc trong C
  • Hàm trong lập trình CC
  • Hàm do người dùng định nghĩa

Dưới đây là cách mà bạn hoàn toàn có thể truyền những cấu trúc vào một hàm

#include

struct student {
char name [ 50 ] ;
int age ;
} ;
/ / function prototype
void display ( struct student s ) ;
int main ( ) {
struct student s1 ;
printf ( “ Enter name : “ ) ;
/ / read string input from the user until \ n is entered
/ / \ n is discarded
scanf ( “ % [ ^ \ n ] % * c ”, s1.name ) ;
printf ( “ Enter age : “ ) ;
scanf ( “ % d ”, và s1.age ) ;
display ( s1 ) ; / / passing struct as an argument
return 0 ;
}
void display ( struct student s ) {
printf ( “ \ nDisplaying information \ n ” ) ;
printf ( “ Name : % s ”, s.name ) ;
printf ( “ \ nAge : % d ”, s.age ) ;
}
Đầu ra
Enter name : Bond
Enter age : 13
Displaying information
Name : Bond
Age : 13
Biến cấu trúc s1 của kiểu struct student được tạo ra. Biến này sẽ được truyền vào hàm display ( ) bằng cách sử dụng câu lệnh display ( s1 ) ;

3.2 Lấy lại cấu trúc từ một hàm

Dưới đây là cách bạn hoàn toàn có thể lấy lại cấu trúc từ một hàm :

#include

struct student
{
char name [ 50 ] ;
int age ;
} ;
/ / function prototype
struct student getInformation ( ) ;
int main ( )
{
struct student s ;
s = getInformation ( ) ;
printf ( “ \ nDisplaying information \ n ” ) ;
printf ( “ Name : % s ”, s.name ) ;
printf ( “ \ nRoll : % d ”, s.age ) ;
return 0 ;
}
struct student getInformation ( )
{
struct student s1 ;
printf ( “ Enter name : “ ) ;
scanf ( “ % [ ^ \ n ] % * c ”, s1.name ) ;
printf ( “ Enter age : “ ) ;
scanf ( “ % d ”, và s1.age ) ;
return s1 ;
}
Hàm getInformation ( ) được gọi bằng cách sử dụng câu lệnh s = getInformation ( ) ;. Hàm này trả về một cấu trúc của kiểu struct student. Cấu trúc trả về sẽ được hiển thị từ hàm main ( ) .
Lưu ý, kiểu trả về của hàm getInformation ( ) cũng là struct student .

3.3 Truyền cấu trúc bằng cách tham chiếu

Bạn cũng hoàn toàn có thể truyền cấu trúc bằng cách tham chiếu ( tựa như như cách mà bạn truyền biến thuộc kiểu kiến thiết xây dựng sẵn bằng cách tham chiếu ). Tôi khuyên bạn nên xem lại phần truyền bằng cách tham chiếu trước khi xem những thông tin tiếp theo .
Trong quy trình truyền bằng cách tham chiếu, địa chỉ bộ nhớ của những biến struct trong C được truyền vào hàm .

#include

typedef struct Complex
{
float real ;
float imag ;
} complex ;
void addNumbers ( complex c1, complex c2, complex * result ) ;
int main ( )
{
complex c1, c2, result ;
printf ( “ For first number, \ n ” ) ;
printf ( “ Enter real part : “ ) ;
scanf ( “ % f ”, và c1.real ) ;
printf ( “ Enter imaginary part : “ ) ;
scanf ( “ % f ”, và c1.imag ) ;
printf ( “ For second number, \ n ” ) ;
printf ( “ Enter real part : “ ) ;
scanf ( “ % f ”, và c2.real ) ;
printf ( “ Enter imaginary part : “ ) ;
scanf ( “ % f ”, và c2.imag ) ;
addNumbers ( c1, c2, và result ) ;
printf ( “ \ nresult.real = %. 1 f \ n ”, result.real ) ;
printf ( “ result.imag = %. 1 f ”, result.imag ) ;
return 0 ;
}
void addNumbers ( complex c1, complex c2, complex * result )
{
result -> real = c1.real + c2.real ;
result -> imag = c1.imag + c2.imag ;
}
Đầu ra
For first number ,
Enter real part : 1.1
Enter imaginary part : – 2.4
For second number ,
Enter real part : 3.4
Enter imaginary part : – 3.2
result.real = 4.5
result.imag = – 5.6
Trong lập trình trên, ba biến cấu trúc c1, c2 và địa chỉ của result được truyền vào hàm addNumbers ( ). Tại đây, result được truyền bằng cách tham chiếu .
Khi biến result trong hàm addNumbers ( ) bị đổi khác thì biến result trong hàm main ( ) cũng đổi khác theo .

4. Liên minh trong C

Trong phần này, bạn sẽ được khám phá về những liên minh trong lập trình C. Cụ thể là : Làm thế nào để tạo ra những liên minh, truy vấn vào những thành viên của nó và sự độc lạ giữa liên minh và cấu trúc .
Liên minh ( union ) là một kiểu do người dùng định nghĩa, tương tự như như cấu trúc trong C, nhưng cũng có một vài điểm độc lạ. Cấu trúc cấp phép đủ khoảng trống để tàng trữ toàn bộ những thành viên của nó, trong khi, liên minh chỉ cấp phép khoảng trống để tàng trữ những thành viên lớn nhất .

4.1 Làm thế nào để định nghĩa liên minh?

Tôi sử dụng từ khóa union để định nghĩa liên minh. Ví dụ ,
union car
{
char name [ 50 ] ;
int price ;
} ;
Đoạn mã trên đây định nghĩa kiểu dẫn xuất union car .

4.2 Tạo các biến liên minh

Khi một liên minh được định nghĩa, nó sẽ tạo ra một kiểu do người dùng định nghĩa. Thế nhưng, nó lại không được cấp phép bộ nhớ. Để cấp phép bộ nhớ cho một kiểu liên minh nhất định và thao tác với nó, tôi sẽ tạo những biến :
Dưới đây là cách để tạo những biến liên minh .
union car
{
char name [ 50 ] ;
int price ;
} ;
int main ( )
{
union car car1, car2, * car3 ;
return 0 ;
}
Một cách khác để tạo những biến liên minh là :
union car
{
char name [ 50 ] ;
int price ;
} car1, car2, * car3
Trong 2 trường hợp trên, biến liên minh car1, car2 và biến pointer car3 của kiểu union car được tạo ra .

4.3 Truy cập vào các thành viên của một liên minh

Tôi sử dụng toán tử. để truy vấn vào những thành viên của một liên minh. Để truy vấn những biến pointer, tôi sẽ sử dụng toán tử -> .
Trong ví dụ trên ,

  • Để truy cập price của car1, tôi sử dụng car1.price
  • Để truy cập price của car3, tôi sử dụng (*car3).price hoặc car3->price

4.4 Sự khác biệt giữa liên minh và cấu trúc

Hãy xem ví dụ dưới đây để hiểu rõ sự độc lạ giữa liên minh và cấu trúc :

#include

union unionJob
{
/ / defining a union
char name [ 32 ] ;
float salary ;
int workerNo ;
} uJob ;
struct structJob
{
char name [ 32 ] ;
float salary ;
int workerNo ;
} sJob ;
int main ( )
{
printf ( “ size of union = % d bytes ”, sizeof ( uJob ) ) ;
printf ( “ \ nsize of structure = % d bytes ”, sizeof ( sJob ) ) ;
return 0 ;
}
Đầu ra
size of union = 32
size of structure = 40

4.5 Tại sao lại có sự khác biệt về kích thước của biến liên minh và biến cấu trúc?

Kích thước của sJob là 40 byte vì

  • kích thước của name[32] là 32 byte
  • kích thước của salary là 4 byte
  • kích thước của workerNo là 4 byte

Tuy nhiên, size của uJob là 32 byte. Bởi vì size của biến liên minh thường sẽ là kích cỡ của thành phần lớn nhất của nó. Trong ví dụ trên, kích cỡ của thành phần lớn nhất, ( name [ 32 ] ), là 32 byte .
Tất cả những thành viên trong cùng một liên minh cùng chung một bộ nhớ giống nhau .

Ví dụ: Truy cập vào các thành viên của liên minh

#include

union Job {
float salary ;
int workerNo ;
} j ;
int main ( ) {
j.salary = 12.3 ;
/ / when j. workerNo is assigned a value ,
/ / j.salary will no longer hold 12.3
j. workerNo = 100 ;
printf ( “ Salary = %. 1 f \ n ”, j.salary ) ;
printf ( “ Number of workers = % d ”, j. workerNo ) ;
return 0 ;

}

Đầu ra
Salary = 0.0
Number of workers = 100