[Powered by Google Translate] Chúng ta hãy nói về cấu trúc.
Cấu trúc cung cấp cho chúng tôi với một cách để nhóm một loạt các biến với nhau
thành một gói đẹp.
Đây có thể là đơn giản nhất để xem một ví dụ ngay,
vì vậy chúng tôi nói cấu trúc,
sau đó mở xoăn cú đúp,
và trong cấu trúc này, chúng tôi sẽ có một tuổi int,
một tên char *,
và đó là nó.
Nó có thể có vẻ lạ với một dấu chấm phẩy sau một cú đúp xoăn,
nhưng đó là trong thực tế, cần thiết với cấu trúc.
Bất kỳ loại hợp lệ có thể đi trong định nghĩa struct.
Ở đây, chúng tôi đã sử dụng một int và một char *,
nhưng bạn cũng có thể sử dụng một mảng, nói, 100 phần tử
hoặc thậm chí một struct.
Khi bạn đang sử dụng cấu trúc trong C,
bạn đang tạo ra các loại mới
trong một bộ sưu tập các loại khác.
Ở đây, chúng tôi đang thực hiện một loại mới
trong số một số nguyên và một char *.
Như chúng ta sẽ thấy sau này, một cấu trúc kiểu
là trong rất nhiều cách khác nhau tương đương với bất kỳ loại khác mà bạn đang sử dụng để.
Thông thường, tôi sẽ được so sánh như thế nào một cấu trúc kiểu
là tương tự như một loại số nguyên.
Trong khi các mã chúng tôi đã viết là hợp lệ C,
nó không phải là rất hữu ích,
và kêu vang sẽ cho chúng ta một cảnh báo.
Hãy nhớ cấu trúc của nó như thế nào tương tự?
Vâng, chúng tôi về cơ bản chỉ nói
int,
mà không phải là một dòng rất hữu ích.
Vì vậy, chúng ta hãy thực sự khai báo một biến của loại đó
bằng cách cho nó một cái tên trước khi dấu chấm phẩy.
Chúng tôi sẽ gọi học sinh biến.
Bây giờ chúng tôi đã tuyên bố một sinh viên biến được gọi là
với các loại hình được đưa ra bởi các cấu trúc.
Làm thế nào để chúng ta có được các biến bên trong cấu trúc?
Về mặt kỹ thuật, các tên cho các biến
là thành viên.
Để truy cập vào bất kỳ thành viên nào cụ thể trong một cấu trúc sinh viên,
bạn nối thêm một dấu chấm tên biến,
tiếp theo là tên của các thành viên mà bạn muốn.
Vì vậy, ở đây, khả năng 2 chỉ có giá trị
là student.age
và student.name.
Và chúng ta có thể làm một cái gì đó như
student.age = 12
và student.name = học sinh.
Bây giờ những gì nếu chúng ta muốn làm cho một học sinh thứ hai?
Bạn có thể nghĩ để sao chép và dán những dòng này
và thay đổi sinh viên học sinh 2 hoặc một cái gì đó,
và điều đó sẽ làm việc,
nhưng về mặt kỹ thuật, sinh viên và học sinh 2
không có cùng loại.
Hãy xem, bạn sẽ không thể giao cho người khác.
Điều này là bởi vì, cho đến nay,
cấu trúc của bạn đã được ẩn danh.
Chúng ta cần phải cung cấp cho nó một cái tên.
Để làm điều đó, chúng ta chèn tên của cấu trúc
sau khi các cấu trúc từ.
sinh viên,
tiếp theo là định nghĩa.
Chúng tôi vẫn có thể ngay lập tức tuyên bố một biến của loại
struct sinh viên, như chúng ta đã làm trước đây.
Chúng tôi sẽ gọi nó là S1
Bằng cách đưa ra các cấu trúc một tên,
bây giờ chúng ta có thể sử dụng cấu trúc sinh viên
trong gần như cùng một cách chính xác, chúng tôi sẽ sử dụng int.
Vì vậy, chúng ta có thể khai báo một biến struct loại của học sinh,
như
struct sinh viên S2.
Giống như mảng, cấu trúc cung cấp một cú pháp khởi tạo shortcut,
vì vậy chúng ta có thể nói, cấu trúc sinh viên S2
bằng
trái xoăn cú đúp 3, S2.
Ở đây, S2.age sẽ là 3,
và S2.name sẽ trỏ đến S2.
Hãy suy nghĩ về tất cả những điều bạn có thể làm với một kiểu int
và hầu hết trong số họ bạn có thể làm với một loại sinh viên struct.
Chúng tôi có thể sử dụng cấu trúc một sinh viên như là một loại của một tham số chức năng.
Chúng tôi có thể sử dụng sinh viên cấu trúc bên trong của một cấu trúc mới.
Chúng tôi có thể có một con trỏ đến cấu trúc một sinh viên.
Chúng tôi có thể làm kích thước của sinh viên struct.
Struct sinh viên là một loại
giống như int là một loại.
Chúng ta cũng có thể gán S1 đến S2
vì cả hai đều cùng loại, vì vậy chúng tôi có thể làm
S1 = S2.
Điều gì sẽ xảy ra nếu chúng ta làm như vậy
S1.age = 10?
Có thay đổi S2 ở tất cả?
Một lần nữa, suy nghĩ của các cấu trúc giống như là số nguyên thường xuyên.
Nếu chúng ta chỉ định một số X int Một số Y int,
như X = Y
và sau đó thay đổi X,
như trong X + +,
Y không thay đổi ở tất cả?
Y không thay đổi ở đây, và cũng như thế S2 trên.
S2.age vẫn còn 3.
Nhưng lưu ý rằng khi gán một cấu trúc khác,
tất cả các con trỏ trỏ đến cùng một điều,
kể từ khi họ chỉ cần sao chép.
Nếu bạn không muốn các con trỏ được chia sẻ,
bạn sẽ cần phải tự xử lý mà,
có lẽ bằng cách malicking một khối bộ nhớ cho một trong các con trỏ để trỏ đến
và sao chép dữ liệu trên.
Nó có thể là khó chịu khi phải viết struct sinh viên ở khắp mọi nơi.
Sử dụng một def loại, chúng ta có thể làm
loại def
struct
và chúng tôi sẽ gọi nó là sinh viên.
Bây giờ, chúng ta có thể sử dụng sinh viên ở khắp mọi nơi
mà chúng tôi sử dụng để sử dụng struct sinh viên.
Def loại là một cấu trúc vô danh
và gọi nó là sinh viên.
Nhưng nếu chúng ta cũng tiếp tục nhận dạng sinh viên
bên cạnh các cấu trúc từ, như trong sinh viên typedef struct,
chúng ta có thể sử dụng struct cả sinh viên và học sinh thay thế cho nhau.
Họ thậm chí không phải có cùng tên.
Chúng ta có thể loại sinh viên struct def Bob
và sau đó cấu trúc của học sinh và Bob
sẽ là các loại hoán đổi cho nhau.
Bất kể loại def,
chúng ta cần nhận dạng tiếp theo để cấu trúc
nếu định nghĩa của cấu trúc
là đệ quy.
Ví dụ,
loại def struct node
và nó sẽ được định nghĩa như là một val int
và nó sẽ có một con trỏ trỏ đến một nút khác struct.
như trong struct node * next.
Và sau đó chúng tôi sẽ gọi nó là nút.
Struct này là đệ quy,
kể từ khi định nghĩa của nút struct chứa bên trong nó
một con trỏ đến cấu trúc một nút.
Chú ý rằng chúng ta phải nói struct node * next
bên trong định nghĩa của các nút struct,
kể từ khi def loại đã không hoàn thành được nêu ra để cho phép chúng tôi để đơn giản hóa
* nút chỉ tiếp theo.
Bạn sẽ tìm hiểu thêm về cấu trúc tương tự như sau
khi giao dịch với danh sách liên kết và cây.
Điều gì về cấu trúc trong một chức năng?
Điều này cũng hoàn toàn hợp lệ.
Chúng ta có thể có
void func
trong đó có như một tham số,
sinh viên s
và làm một cái gì đó với học sinh đó.
Và sau đó chúng tôi có thể vượt qua nó như là struct sinh viên như vậy.
Func của S1 từ trước.
Cấu trúc này hoạt động
chính xác như một số nguyên khi chuyển đến một chức năng.
Func nhận được một bản sao của S1
và do đó không có thể sửa đổi S1;
thay vào đó, chỉ có các bản sao của nó được lưu trữ trong S.
Nếu bạn muốn các chức năng để có thể sửa đổi S1,
func sẽ cần để có một sinh viên * S,
và bạn sẽ phải vượt qua S1 theo địa chỉ, như vậy.
Sinh viên * S, func S1.
Có một lý do khác để vượt qua theo địa chỉ ở đây.
Điều gì sẽ xảy ra nếu cấu trúc của chúng tôi có 100 các lĩnh vực?
Mỗi lần duy nhất chúng tôi vượt qua một học sinh func,
chương trình của chúng tôi cần để sao chép tất cả các số 100 trường vào S đối số chức năng,
ngay cả khi nó không bao giờ sử dụng phần lớn trong số họ.
Vì vậy, ngay cả khi chức năng không có kế hoạch sửa đổi các học sinh,
nếu vẫn còn có thể có giá trị để vượt qua theo địa chỉ.
Được rồi, điều gì sẽ xảy ra nếu chúng tôi muốn tạo ra một con trỏ đến một cấu trúc?
Chúng ta có thể làm một cái gì đó như thế
sinh viên * S
bằng malloc
kích thước của học sinh.
Chú ý rằng kích thước vẫn còn làm việc ở đây.
Vậy làm thế nào bây giờ chúng ta truy cập các thành viên tuổi
của khối S điểm?
Trước tiên, bạn có thể nghĩ rằng để làm
* S.age = 4,
nhưng điều này sẽ không làm việc khá.
Kể từ khi điều này thực sự sẽ được hiểu là
* S.age trong ngoặc đơn = 4,
thậm chí sẽ không biên dịch,
S không phải là một cấu trúc hay đúng hơn là một con trỏ đến một cấu trúc,
và do đó, các dấu chấm sẽ không làm việc ở đây.
Chúng ta có thể làm
(* S) = 4 tuổi
nhưng các dấu ngoặc đơn có thể được gây phiền nhiễu và khó hiểu.
Rất may, chúng tôi có một nhà điều hành mũi tên đặc biệt
trông giống như
S-> = 4 tuổi.
Đây là 2 cách tham khảo tuổi
là tương đương
và chúng tôi không thực sự bao giờ cần các nhà điều hành mũi tên,
nhưng nó làm cho mọi thứ trông đẹp hơn.
Kể từ khi S là một con trỏ đến một số khối bộ nhớ có chứa các cấu trúc,
bạn có thể nghĩ tuổi> S như sau mũi tên con trỏ
và lấy các thành viên tuổi.
Vậy tại sao chúng ta nên sử dụng cấu trúc?
Nó chắc chắn có thể nhận được ngay với các số nguyên nguyên thủy,
ký tự, con trỏ và các loại tương tự
mà chúng tôi đang sử dụng để;
thay vì S1 và S2 trước khi,
chúng ta có thể có age1, age2, name1, và name2
tất cả đều biến riêng biệt.
Điều này là tốt với chỉ có 2 học sinh,
nhưng những gì nếu chúng tôi đã có 10 người trong số họ?
Và điều gì sẽ xảy ra nếu thay vì chỉ có 2 lĩnh vực,
các cấu trúc sinh viên đã có 100 trường?
GPA, các khóa học, màu tóc, giới tính, và do đó trên.
Thay vì chỉ có 10 cấu trúc, chúng ta cần 1.000 biến riêng biệt.
Ngoài ra, hãy xem xét một chức năng
mất rằng cấu trúc với 100 lĩnh vực với đối số duy nhất của nó
và in ra tất cả các lĩnh vực.
Nếu chúng ta không sử dụng một cấu trúc,
mỗi lần duy nhất chúng tôi gọi là chức năng,
chúng ta cần phải vượt qua tất cả 100 biến,
và nếu chúng ta có 100 biến cho học sinh 1,
và 100 biến cho học sinh 2,
chúng ta cần phải chắc chắn rằng chúng tôi không vô tình vượt qua một số biến từ học sinh 1
và một số biến từ học sinh 2.
Nó không thể để làm cho rằng sai lầm với một cấu trúc,
vì tất cả 100 biến được chứa trong một gói duy nhất.
Chỉ cần một vài ghi chú cuối cùng:
Nếu bạn đã hiểu tất cả mọi thứ lên đến thời điểm này, tuyệt vời.
Phần còn lại của đoạn video chỉ là vì lợi ích đầy đủ '.
Bởi vì cấu trúc có thể chứa bất kỳ loại của con trỏ,
họ cũng có thể giữ con trỏ hàm.
Nếu bạn đã quen thuộc với lập trình hướng đối tượng,
cung cấp một cách để sử dụng cấu trúc chương trình trong một phong cách hướng đối tượng.
Thêm về chức năng con trỏ vào một thời điểm khác.
Ngoài ra, đôi khi bạn có thể có 2 cấu trúc
có định nghĩa phụ thuộc vào nhau.
Ví dụ,
chúng ta có thể có một cấu trúc,
được định nghĩa là
một con trỏ đến cấu trúc B,
struct B * X,
và bây giờ chúng tôi có thể có một cấu trúc B
được định nghĩa là một con trỏ
một cấu trúc A,
struct A * Y.
Nhưng điều này sẽ không biên dịch,
kể từ khi struct B không tồn tại ở thời gian mà struct A đang được biên soạn.
Và nếu chúng ta trao đổi struct A và cấu trúc B,
sau đó chúng tôi chỉ muốn được trái với cùng một vấn đề;
thời gian này, với một cấu trúc hiện tại không.
Để giải quyết vấn đề này, chúng ta có thể viết
struct B;
trước khi định nghĩa của cấu trúc A.
Điều này được gọi là một tờ khai chuyển tiếp.
Điều này chỉ cho phép trình biên dịch biết rằng
struct B là một loại hợp lệ sẽ được xác định đầy đủ sau hoặc ở nơi khác.
Tên tôi là Rob Bowden, và đây là CS50.
[CS50.TV]