chap 15 struct n.
Download
Skip this Video
Loading SlideShow in 5 Seconds..
Chap 15 struct 與資料結構 PowerPoint Presentation
Download Presentation
Chap 15 struct 與資料結構

Loading in 2 Seconds...

play fullscreen
1 / 64

Chap 15 struct 與資料結構 - PowerPoint PPT Presentation


  • 95 Views
  • Uploaded on

Chap 15 struct 與資料結構. struct 可以在同一個名稱下擁有多種資料型態。使用 struct 能讓資料的存取和處理更為靈活。. struct 與資料結構. 15.1 struct 的宣告和使用 15.2  由 struct 構成的陣列 15.3 struct 資料型態與函數參數的傳遞 15.4 struct 實例的動態宣告 15.5  指標成員與資料結構 15.6 union 資料型態 15.7 enum 資料型態. struct 的宣告和使用. 組成份子稱為 成員 (member) 或 資料欄位 (data field) 。

loader
I am the owner, or an agent authorized to act on behalf of the owner, of the copyrighted work described.
capcha
Download Presentation

Chap 15 struct 與資料結構


An Image/Link below is provided (as is) to download presentation

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.


- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -
Presentation Transcript
chap 15 struct

Chap 15 struct與資料結構

struct 可以在同一個名稱下擁有多種資料型態。使用struct能讓資料的存取和處理更為靈活。

struct
struct與資料結構
  • 15.1struct的宣告和使用
  • 15.2 由struct構成的陣列
  • 15.3struct資料型態與函數參數的傳遞
  • 15.4struct實例的動態宣告
  • 15.5 指標成員與資料結構
  • 15.6union資料型態
  • 15.7enum資料型態
struct1
struct的宣告和使用
  • 組成份子稱為成員(member) 或資料欄位(data field)。
  • 成員可以是各種不同的資料型態 (複合式資料型態)。
  • 關鍵字struct是英文 structure (結構) 的縮寫,此種資料結構又稱為記錄(record)。
struct2
struct資料型態的宣告範例
  • Employee包括的資料成員有Name (姓名)、Phone (電話號碼) 以及Id (編號) 三種:

struct Employee

{

char Name[20];

char Phone[10];

int Id;

}; // 注意這要用到「;」!

struct3
Struct 在記憶體中的儲存方式
  • 各成員的儲存位置是連續的:
struct4
使用struct 資料型態定義變數
  • 可以使用標準的定義敘述。例如:

Employee Ea, Eb;

  • 定義了兩個名稱分別為Ea和Eb的Employee變數。
  • 由某一資料型態定義的變數稱為該資料型態的實例 (instance)。
slide7
定義變數時一併給予初始值
  • 例如,上面的敘述可進一步寫成:

EmployeeEa = {"Ann", "02384125", 105};

EmployeeEb = {"Joanne", "03544132", 106};

employee
要存取Employee變數的個別資料欄位
  • 必需同時給定變數名稱和資料成員名稱,中間用一個成員運算符號(member operator)「.」隔開。例如:

Ea.Name // 其值目前分別為 “Ann”

Eb.Phone // 其值目前分別為“02384125”

Ea.Id // 其值目前分別為105

  • 分別用來代表Ea這個Employee變數的三個成員,其值目前分別為“Ann”,“02384125”和105。這個語法基本上和我們在10.1節介紹的成員函數的語法是一致的。
teststruct cpp
範例程式TestStruct.cpp
  • 如何使用struct宣告自訂的資料型態,以及各欄位內的資料如何存取。
teststruct cpp1
範例程式 檔案 TestStruct.cpp

// TestStruct.cpp

#include <iostream>

using namespace std;

struct Employee

{

char Name[20];

char Phone[10];

int Id;

};

// ----- 主程式 ----------------------------

slide11
int main()

{

EmployeeEa= {"Ann", "02384125", 105};

Employee Eb = {"Joanne", "03544132", 106};

cout << "Ea 的資料是:\n"

<< "姓名 : " << Ea.Name << '\n'

<< "電話號碼: " << Ea.Phone << '\n'

<< "編號 : " << Ea.Id << endl;

cout << "Eb 的資料是:\n"

<< "姓名 : " << Eb.Name << '\n'

<< "電話號碼: " << Eb.Phone << '\n'

<< "編號 : " << Eb.Id << endl;

return 0;

}

struct5
合併struct資料型態的宣告和變數的定義
  • 例如:

struct

{

char Name[20];

char Phone[10];

int Id;

} Ea, Eb;

  • 由於粗體字的部份本身就是已經是新定義的資料型態之具體內容,不用再取個名稱來代表它。
struct6
由struct構成的陣列
  • 結合陣列和struct,可以一次完成很多具有相同結構的struct變數的定義。
  • 例如,可以使用

Employee Officer[50];

  • 同時定義從Officer[0] 到Officer[49],共50個Employee變數
struct7
struct陣列各欄位的資料

cout << Officer[8].Name << endl;

cout << Officer[12].Phone << endl;

cout << Officer[40].Id << endl;

structarray cpp
範例程式StructArray.cpp
  • 允許使用者逐一輸入各陣列元素的各成員值 (每輸入一個項目後,要按兩次Enter鍵)。
structarray cpp1
範例程式 檔案 StructArray.cpp

// StructArray.cpp

#include <iostream>

using namespace std;

const int NameSize = 20;

const int PhoneSize = 10;

struct Employee

{

char Name[NameSize];

char Phone[PhoneSize];

};

int main()

{

const int Size = 2;

Employee Officer[Size];

cout << "共 " << Size << " 個 Officers:\n";

slide19
for (int i=0; i<Size; i++)

{

cout << "請輸入 Officer[" << I<< "] 的姓名: ";

cin.getline(Officer[i].Name, NameSize, '\n');

cout << "電話號碼: ";

cin.getline(Officer[i].Phone, PhoneSize, '\n');

}

for (int i=0; i<Size; i++)

{

cout << "Officer[" << i << "] 的資料是:\n"

<< "姓名 : " << Officer[i].Name << '\n'

<< "電話號碼: " << Officer[i].Phone << '\n';

}

return 0;

}

struct8
struct資料型態與函數參數的傳遞
  • 由struct所定義的實例被用來做為參數傳遞時,其預設的語意是傳值(pass-by-value)。
  • 也就是說,在「被呼叫函數」內部將另外產生一個複製資料,而不會影響「呼叫函數」內的資料。
struct9
用struct所定義的實例來傳遞參數
  • 例如,呼叫敘述可以寫成:

ShowMember(Ea);

  • 而被呼叫函數則可以定義成:

void ShowMember(Employee A)

{

cout << "資料的詳細內容是:\n"

<< "姓名 : " << A.Name << '\n'

<< "電話號碼: " << A.Phone << '\n'

<< "編號 : " << A.Id << endl;

return;

}

pass by reference struct
使用傳參照 (pass by reference) 改變struct實例的內容
  • 例如:

ChangeName(Ea, “Jackson”);

  • 對應的「被呼叫函數」則定義成:

void ChangeName (Employee& A, char NewName[])

{

strcpy(A.Name, NewName);

return;

}

structfnc cpp
範例程式 檔案 StructFnc.cpp

// StructFnc.cpp

#include <iostream>

using namespace std;

struct Employee

{

char Name[20];

char Phone[10];

int Id;

};

void ShowMember(Employee A)

{

cout << "資料的詳細內容是:\n"

<< "姓名 : " << A.Name << '\n'

<< "電話號碼: " << A.Phone << '\n'

<< "編號 : " << A.Id << endl; return;

}

slide25
void ChangeName (Employee& A, char NewName[])

{ strcpy(A.Name, NewName); return; }

// ============= 主程式 ========================

int main()

{

Employee Ea = {"Ann", "02384125", 105};

Employee Eb = {"Joanne", "03544132", 106};

ShowMember(Ea);

ShowMember(Eb);

ChangeName(Ea, "Jackson");

cout << "執行 ChangeName() 後:\n";

ShowMember(Ea);

return 0;

}

struct10
使用指標改變struct實例的內容
  • 使用傳址(pass-by-address) 來達到使用參照的目的:

ChangeId(&Ea, 00128);

  • 「被呼叫函數」則定義為

void ChangeId(Employee* pE, int NewId)

{

(*pE).Id=NewId;

return;

}

slide29
C++ 的具象指標符號 ->
  • 將 (*pE).Name寫成:

pE->Name

  • 表示「由pE指向的struct變數內的成員 Name」。
changeid
進一步改寫 ChangeId()

void ChangeId(Employee* pE, int NewId)

{

pE->Id = NewId;

return;

}

structfnc2 cpp
範例程式 檔案 StructFnc2.cpp

// StructFnc2.cpp

#include <iostream>

using namespace std;

struct Employee

{

char Name[20];

char Phone[10];

int Id;

};

void ShowMember(Employee A)

{

cout << "資料的詳細內容是:\n"

<< "姓名 : " << A.Name << '\n'

<< "電話號碼: " << A.Phone << '\n'

<< "編號 : " << A.Id << endl; return;

}

slide32
void ChangeName (Employee& A, char NewName[])

{ strcpy(A.Name, NewName); return; }

void ChangeId(Employee* pE, int NewId)

{ pE->Id = NewId; return;}

// ========= 主程式 ========================

int main()

{

Employee Ea = {"Ann", "02384125", 105};

Employee Eb = {"Joanne", "03544132", 106};

ShowMember(Ea);

ShowMember(Eb);

ChangeId(&Ea, 208);

cout << "執行 ChangeId() 後:\n";

ShowMember(Ea);

return 0;

}

struct11
struct實例的動態宣告
  • 亦即struct實例的動態記憶體配置(dynamic memory allocation)。
  • 下列敘述則可以在執行時才臨時決定陣列的大小:

int Size;

cin >> Size;

Employee* pE = new Employee[Size];

struct12
struct實例的動態記憶體配置和回收
  • 執行後會依指定的大小在記憶體的特殊區域,稱為記憶堆(heap) 的地方,規劃出需要的記憶空間,並把第一個變數的開頭位址存入指標內。
  • 如果此陣列不再需要,可以執行下列的敘述回收記憶體空間:

delete [] pE;

slide36
使用陣列下標或指標算數存取內部成員
  • 例如,要取用第k個陣列元素內的成員Id,下述語法都是正確的:

Labor[k].Id

(*(Labor + k)).Id

(Labor + k)->Id

pE[k].Id

(*(pE + k)).Id

(pE + k)->Id

dynstruct cpp
範例程式DynStruct.cpp
  • 示範動態產生由struct實例所構成的陣列,稱為Employee,之完整語法,並在事後回收記憶空間。
dynstruct cpp1
範例程式 檔案 DynStruct.cpp

// DynStruct.cpp

#include <iostream>

using std::cin;

using std::cout;

struct Employee

{

char Name[20];

char Phone[10];

int Id;

};

// --------- 主程式 ------------------------

slide39
int main()

{

int Size;

cout << "請輸入 Employee 的數目:\n";

cin >> Size;

Employee* pE = new Employee[Size];

delete [] pE;

return 0;

}

slide40
指標成員與資料結構
  • struct所宣告的資料型態可以使用「指標」做為成員。
  • 指標成員可以指向自己所在的struct資料型態,稱為「自我參照」(auto-reference)。例如:

Struct Data

{

int Id;

Data* pD;

};

lists
串列 (lists)
  • 定義一串的Data變數:

Data D1, D2, D3;

D1.pD = &D2;

D2.pD = &D3;

  • 圖示如下:
  • 串列最後一個元素內的指標值為NULL (亦即 ‘\0’),用來做為檢查串列是否「到此為止」的根據。
lists1
串列 (lists)
  • 「節點」(node): 每一個用來儲存資料的元素第一個節點稱為
  • 「開頭」(head): 第一個節點。
  • 「結尾」(tail): 最後的節點。
slide43
在陣列插入一個元素

int* V = new int [Size];

  • 必需同時將V[1] 及其之後的所有元素往右移,且無法應付陣列因長度增加而記憶空間可能不足的問題。
slide44
「串列」可以帶來的便利
  • 使用串列(linked list) 可以較有效率地完成元素增刪的動作。
  • 設想原先有A, B, C 三個元素串接在一起形成一個串列:
slide45
一個串列的範例
  • 假設使用struct宣告了一個名叫 Element 的自訂資料形態:

struct Element

{

int Value;

Element* Next;

};

element 0 2 4 6
動態產生任意數目的Element (各實例的值在此為0, 2, 4, 6, …):

cout << "請輸入 Element 的數目:\n";

cin >> Size;

Element* pE = new Element[Size];

for (int i=0; i<(Size-1); i++)

pE[i].Next = pE + i +1;

pE[Size-1].Next = NULL;

for (int i=0; i<(Size); i++)

pE[i].Value = i*2;

slide47
顯示現有串列元素

Element* pShow;

for (pShow = pE; pShow != NULL; pShow=pShow->Next)

cout << pShow->Value << ' ';

  • 不斷更換指標使它指向下一個元素的位址。
while
以while迴圈顯示現有串列元素

Element* pShow=pE;

while (pShow != NULL)

{

cout << pShow->Value << ' ';

pShow = pShow->Next;

}

slide49
將顯示串列內容的功能封裝到函數中

void ShowElement(Element* pShow)

{

while (pShow != NULL)

{

cout << pShow->Value << ' ';

pShow = pShow->Next;

}

}

liststruct cpp
範例程式 檔案 ListStruct.cpp

// ListStruct.cpp

#include <iostream>

using namespace std;

struct Element

{

int Value;

Element* Next;

};

void ShowElement(Element* pShow)

{

while (pShow != NULL)

{

cout << pShow->Value << ' ';

pShow = pShow->Next;

}

}

slide51
// ---主程式------------------------

int main()

{

int Size;

cout << "請輸入 Element 的數目:\n";

cin >> Size;

Element* pE = new Element[Size];

for (int i=0; i<(Size-1); i++)

pE[i].Next = pE + i +1;

pE[Size-1].Next = NULL;

for (int i=0; i<(Size); i++)

pE[i].Value = i*2;

cout << "Element 的內容是:\n";

ShowElement(pE);

delete [] pE;

return 0;

}

doubly linked list
雙向鏈結串列 (doubly- linked list)
  • 能夠自由在串列中往返尋找。
  • 每個節點內都含有兩個指標,分別指向下一個節點及上一個節點。
slide54
「雙向鏈結串列」的宣告

struct Node

{

int Value;

Node* Previous;

Node* Next;

};

slide55
樹狀結構 (tree)
  • 二維結構。
  • 開頭的節點稱為「根」(root)。
  • 「層」(layer): 與根的距離相同的所有節點。
  • 「葉」(leaves): 不再指向下一層節點的所有節點。
binary tree
二元樹 (binary tree)
  • 由於每個節點都只有兩個指標向下一層的兩個節點,形成一個「品」字型的局部結構,因此稱為「二元樹」。
union
union資料型態
  • 可以在其內擁有多種資料型態,但一次只能有一種資料型態。例如:

union Data

{

float FloatValue;

double DoubleValue;

char CharValue;

int IntValue;

};

Data D1;

  • 每個Data變數擁有的記憶空間由佔有最大空間的成員 (此例為D1.DoubleValue) 所決定。使用union的目的在於節省記憶體。
slide58
enum資料型態
  • enum是enumerate (列舉) 的簡寫。
  • 由enum所定義的任何實例(instance) 只能擁有當初enum宣告時所列舉的值之一。例如:

enum Direction {Up, Down, Left, Right};

Direction x;

  • 我們只能把這四種可能的值指定給x。例如:

x = Right;

  • 在電腦內部 {Up, Down, Left, Right} 分別和 {0, 1, 2, 3} 比對。
slide59
可以在宣告enum 時給予各成員確定的數值
  • 例如:

enum Check {Error = -1, Suspicious, Acceptable = 5, OK = 10};

  • 沒有特別指定的的值為其前一個成員 (亦即Error) 的值加1,
  • 因此suspicious的內值為 –1 + 1 = 0。
slide60
enum資料型態
  • 使用enum型態的目的是為了增進程式的可讀性,常與switch和if等判斷式結合使用。例如:

int N;

cin >> N;

switch (N)

{

case Up:

cout << “Moving Up!\n”;

break;

case Down:

cout << “Moving Down!\n”;

break;

case Left:

cout << “Moving Left!\n”;

break;

slide61
case Right:

cout << “Moving Right!\n”;

break;

default:

cout << “Static\n”;

}

testenum cpp
範例程式 檔案 TestEnum.cpp

// TestEnum.cpp

#include <iostream>

using namespace std;

enum Direction {Up, Down, Left, Right};

// -------- 主程式 ------------------------

int main()

{

int N;

cout << "請輸入期望的運動方向\n";

cout << "(0=Up, 1=Down, 2=Left, 3=Right):\n";

cin >> N;

switch (N)

{

case Up:

cout << "Moving Up!\n";

break;

slide63
case Down:

cout << "Moving Down!\n";

break;

case Left:

cout << "Moving Left!\n";

break;

case Right:

cout << "Moving Right!\n";

break;

default:

cout << "Static\n";

}

return 0;

}