Title Text
Struct
(大量)參考2022竹區第8週投影片
目錄
Struct是什麼
Struct的語法
Nested Struct
struct *ptr
為什麼需要Struct
酷酷的補充
Struct是什麼
Struct是什麼
簡單來說,struct能幫助我們將一些相關的資料儲存在同一個變數底下!
Struct是什麼
Struct是什麼
char students_name[40][10] ;
int students_ID[40] ;
double students_height[40] ;
bool students_alive[40] ;
好麻煩喔!
來用struct吧!
Struct的語法
Struct的語法-定義
struct student{
char name[10] ;
int ID ;
double height ;
bool alive ;
} ;
//記得最後面要加分號!
name, ID, height, alive 稱為 student 的屬性
struct student{
char name[10] ;
int ID ;
double height ;
bool alive ;
} ;
int main() {
student student_1, student_2 ;
}
將 student 視為一個新的變數型態
Struct的語法-宣告
struct student{
char name[10] ;
int ID ;
double height ;
bool alive ;
} ;
int main() {
//第1種初始化的方法
student student_1 = {
.name = "Alice",
.ID = 887,
.height = 190.7,
.alive = false
} ;
//第2種初始化的方法
student_2 = {"Bob", 112, 185.4, true} ;
}
將 student 視為一個新的變數型態
Struct的語法-初始化
struct student{
char name[10] ;
int ID ;
double height ;
bool alive ;
} ;
int main() {
student student_1 ;
student_1.name = "Alice" ;
student_1.ID = 887 ;
student_1.height = 163.3 ;
student_1.alive = false ;
}
變數名稱.屬性 = value
Struct的語法-賦值
struct student{
char name[10] ;
int ID ;
double height ;
bool alive ;
} ;
int main() {
student student_1 = {"Alice", 887, 163.3, false} ;
cout << student_1.name << "'s ID : " << student_1.ID ;
student_1.height += student_1.ID ;
student_1.alive = true ;
}
Struct的語法-取值
struct student{
char name[10] ;
int ID ;
double height ;
bool alive ;
} ;
int main() {
student class_204[40] ;
for (int i = 0; i < 40; i++) {
cin >> class_204[i].name ;
cin >> class_204[i].ID ;
cin >> class_204[i].height ;
cin >> class_204[i].alive ;
}
}
陣列名稱[k].屬性 = value
Struct的語法-陣列
struct student{
char name[10] ;
int ID ;
double height ;
bool alive ;
} ;
int main() {
student class_204[3] = {
{"Alice", 1, 170.3, true} ,
{"Bob", 2, 166.9, true} ,
{"Carol", 3, 190.7, false}
} ;
}
變數型別 陣列名稱[N] = {{}, {}, {}, ..., {}}
Struct的語法-陣列初始化(1)
struct student{
char name[10] ;
int ID ;
double height ;
bool alive ;
} ;
int main() {
student class_204[2] =
{
{
.name = "Alice",
.ID = 998,
.height = 190.0,
.alive = false
},
{
.name = "Bob",
.ID = 887,
.height = 160.0,
.alive = true
}
} ;
}
變數型別 陣列名稱[N] =
{
{
.a = val_1,
.b = val_2
},
{
.a = val_3,
.b = val_4
},
...,
{
.a = val_101,
.b = val_102
} ;
}
Struct的語法-陣列初始化(2)
Sprout OJ no.895 成績統計II
Struct的語法-練習
double girls_average(Student ss[],int size) {
//do something
}
double boys_average(Student ss[],int size) {
//do something
}
void print(Student s) {
//do something
}
Struct的語法-練習
for i = 0 to size - 1 :
if (ss[i].gender is female) :
sum += ss[i].score
if (female_num is 0) :
return -1
else :
return sum / female_num
Struct的語法-練習
為什麼需要Struct
為什麼需要Struct
Task: 給你3對情侶,他們各自有各自的CE(Combatting Effectiveness),想請你依據女方的CE,由小到大對情侶們進行排序。
為什麼需要Struct
還沒學struct的你:
boys_CE[3] = {
,
,
}
girls_CE[3] = {
,
,
}
為什麼需要Struct
sort:
不是今天的重點,但是C++中有個好用的sort函式:
//記得引入標頭檔
#include <algorithm>
using namespace std ;
int main() {
int num[6] = {1, 4, 2, 5, 3, 6} ;
sort(num, num + 6) ;
// sort 函式的預設是由小排到大
//所以 num = {1, 2, 3, 4, 5, 6}
}
為什麼需要Struct
sort:
用在我們的情侶身上可能會變成:
//記得引入標頭檔
#include <algorithm>
using namespace std ;
int main() {
int boys_CE[3] = {33, 9, 50} ;
int girls_CE[3] = {44, 9999, 4} ;
sort(girls_CE, girls_CE + 3) ;
}
為什麼需要Struct
交換伴侶!? BAD!
boys_CE[3] = {
girls_CE[3] = {
,
,
,
,
,
,
}
}
為什麼需要Struct
struct couple{
int female_CE ;
int male_CE ;
} ;
bool cmp(couple a, couple b) {
return a.female_CE < b.female_CE ;
}
int main() {
couple couple_arr[3] = {{44, 33}, {9999, 9}, {4, 50}} ;
sort(couple_arr, couple_arr + 3, cmp) ;
}
解決方法:Struct!
為什麼需要Struct
,
}
}
{
,
,
}
{
}
,
,
{
{
couple couples[3]=
為什麼需要Struct
其他可能需要用struct的情境:
1.(x, y)座標
2.圖裡面的節點
node
head
node
node
node
NULL
Linked list
Nested Struct
Nested Struct
struct animal{
char name[10] ;
int leg_num ;
double height ;
bool alive ;
} ;
struct student{
char name[10] ;
int ID ;
double height ;
bool alive ;
animal pet ;
} ;
如果student養了寵物:
Nested Struct
struct animal{
char name[10] ;
int leg_num ;
double height ;
bool alive ;
} ;
struct student{
char name[10] ;
int ID ;
double height ;
bool alive ;
animal pet ;
} ;
如果student養了寵物:
cout << Bob.pet.name ;
如果今天有一個學生Bob,並且我們想要知道他寵物的名字:
取用student中的屬性pet中的屬性name
Nested Struct
struct animal{
char name[10] ;
int leg_num ;
double weight ;
double height ;
bool alive ;
} ;
struct student{
char name[10] ;
int ID ;
double height ;
bool alive ;
animal pet[40] ;
} ;
int main() {
student class_204[40] ;
}
如果student養了寵物:
如果我們想要知道class_204中索引值A的學生的索引值B的pet的height:
(A) class_204[B].height[A].pet
(B) class_204[A].height[B].pet
(C) class_204[A].pet[B].height
(D) class_204.pet[A].height[B]
Nested Struct
struct student{
char name[10] ;
int ID ;
double height ;
bool alive ;
student hate ;
} ;
可以這樣嗎?
如果student討厭別的student:
Nested Struct
student
hate
student
student
student
...
student 的屬性hate為student型別,因此hate底下又有hate..
不知道要分配給student多少記憶體!
//Compile Error
struct student{
char name[10] ;
int ID ;
double height ;
bool alive ;
student hate ;
} ;
hate
hate
hate
Nested Struct
用指標來儲存hate!
struct *ptr
struct *ptr
struct student{
char name[10] ;
int ID ;
double height ;
bool alive ;
student *hate ; //指向這個student討厭的student
} ;
如果student討厭別的student:
student
*hate
student
*hate
student
*hate
student
*hate
struct *ptr
struct student{
char name[10] ;
int ID ;
double height ;
bool alive ;
student *hate ;
} ;
取用student_1的屬性:
student_1.height = 190.8 ;
取用student_1討厭的人的屬性:
(*student_1.hate).height = 130.7 ;
or
student_1.hate -> height = 130.7 ;
struct *ptr
struct node{
int data ;
node *next //指向下一個node
} ;
node
*next
*head
node
*next
node
*next
node
*next
NULL
還記得剛剛提過的linked list 嗎?
只是這是你們第14週的上課內容 可以不用學得太認真XD
酷酷的補充
酷酷的補充-記憶體對齊
struct test1{
short a ; //2 byte
short b ; //2 byte
int c ; //4 byte
} ;
struct test2{
short a ; //2 byte
int c ; //4 byte
short b ; //2 byte
} ;
struct test3{
int c ; //4 byte
short a ; //2 byte
short b ; //2 byte
} ;
test1 t1 ;
test2 t2 ;
test3 t3 ;
cout << "sizeof(t1) : "<< sizeof(t1) << "\n" ;
cout << "sizeof(t2) : "<< sizeof(t2) << "\n" ;
cout << "sizeof(t3) : "<< sizeof(t3) << "\n" ;
?
三個屬性相同,但定義struct時順序不同的struct:
酷酷的補充-記憶體對齊
test1 t1 ;
test2 t2 ;
test3 t3 ;
cout << "sizeof(t1) : "<< sizeof(t1) << "\n" ;
cout << "sizeof(t2) : "<< sizeof(t2) << "\n" ;
cout << "sizeof(t3) : "<< sizeof(t3) << "\n" ;
WHY?
酷酷的補充-記憶體對齊
電腦的cpu抓資料一次通常是抓4byte的資料(要看電腦的規格,32位元的cpu一次抓4byte的資料,64位元的則是一次抓8byte的資料)
0
1
2
3
做4次存取太慢了!
}
integer
4
5
6
7
酷酷的補充-記憶體對齊
電腦的cpu抓資料一次通常是抓4byte的資料(要看電腦的規格,32位元的cpu一次抓4byte的資料,64位元的則是一次抓8byte的資料)
0
1
2
3
所以就一次存取4byte的資料!
}
integer
4
5
6
7
酷酷的補充-記憶體對齊
0
1
2
3
}
4
5
6
7
integer
這樣要做兩次存取!BAD!
要做記憶體對齊(Alignment)
酷酷的補充-記憶體對齊
記憶體對齊的大原則:
在存取同一個資料的時候,確保我不需要做多餘的存取。
struct test1{
short a ; //2 byte
short b ; //2 byte
int c ; //4 byte
} ;
1
0
2
3
4
5
6
7
struct test3{
int c ; //4 byte
short a ; //2 byte
short b ; //2 byte
} ;
1
0
2
3
4
5
6
7
酷酷的補充-記憶體對齊
記憶體對齊的大原則:
在存取同一個資料的時候,確保我不需要做多餘的存取。
struct test2{
short a ; //2 byte
int c ; //4 byte
short b ; //2 byte
} ;
1
0
2
3
4
5
6
7
8
9
10
11
酷酷的補充-記憶體對齊
想知道細節可以去看這篇:記憶體管理、對齊及硬體特性
Title TextArray
By cswagger
Title TextArray
- 234