1 / 64

Chap 15 struct 與資料結構

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) 。

zora
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. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


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

  2. struct與資料結構 • 15.1struct的宣告和使用 • 15.2 由struct構成的陣列 • 15.3struct資料型態與函數參數的傳遞 • 15.4struct實例的動態宣告 • 15.5 指標成員與資料結構 • 15.6union資料型態 • 15.7enum資料型態

  3. struct的宣告和使用 • 組成份子稱為成員(member) 或資料欄位(data field)。 • 成員可以是各種不同的資料型態 (複合式資料型態)。 • 關鍵字struct是英文 structure (結構) 的縮寫,此種資料結構又稱為記錄(record)。

  4. struct資料型態的宣告範例 • Employee包括的資料成員有Name (姓名)、Phone (電話號碼) 以及Id (編號) 三種: struct Employee { char Name[20]; char Phone[10]; int Id; }; // 注意這要用到「;」!

  5. Struct 在記憶體中的儲存方式 • 各成員的儲存位置是連續的:

  6. 使用struct 資料型態定義變數 • 可以使用標準的定義敘述。例如: Employee Ea, Eb; • 定義了兩個名稱分別為Ea和Eb的Employee變數。 • 由某一資料型態定義的變數稱為該資料型態的實例 (instance)。

  7. 定義變數時一併給予初始值 • 例如,上面的敘述可進一步寫成: EmployeeEa = {"Ann", "02384125", 105}; EmployeeEb = {"Joanne", "03544132", 106};

  8. 要存取Employee變數的個別資料欄位 • 必需同時給定變數名稱和資料成員名稱,中間用一個成員運算符號(member operator)「.」隔開。例如: Ea.Name // 其值目前分別為 “Ann” Eb.Phone // 其值目前分別為“02384125” Ea.Id // 其值目前分別為105 • 分別用來代表Ea這個Employee變數的三個成員,其值目前分別為“Ann”,“02384125”和105。這個語法基本上和我們在10.1節介紹的成員函數的語法是一致的。

  9. 範例程式TestStruct.cpp • 如何使用struct宣告自訂的資料型態,以及各欄位內的資料如何存取。

  10. 範例程式 檔案 TestStruct.cpp // TestStruct.cpp #include <iostream> using namespace std; struct Employee { char Name[20]; char Phone[10]; int Id; }; // ----- 主程式 ----------------------------

  11. 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; }

  12. 執行結果

  13. 合併struct資料型態的宣告和變數的定義 • 例如: struct { char Name[20]; char Phone[10]; int Id; } Ea, Eb; • 由於粗體字的部份本身就是已經是新定義的資料型態之具體內容,不用再取個名稱來代表它。

  14. 比較資料型態變數的語法

  15. 由struct構成的陣列 • 結合陣列和struct,可以一次完成很多具有相同結構的struct變數的定義。 • 例如,可以使用 Employee Officer[50]; • 同時定義從Officer[0] 到Officer[49],共50個Employee變數

  16. struct陣列各欄位的資料 cout << Officer[8].Name << endl; cout << Officer[12].Phone << endl; cout << Officer[40].Id << endl;

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

  18. 範例程式 檔案 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";

  19. 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; }

  20. 執行結果

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

  22. 用struct所定義的實例來傳遞參數 • 例如,呼叫敘述可以寫成: ShowMember(Ea); • 而被呼叫函數則可以定義成: void ShowMember(Employee A) { cout << "資料的詳細內容是:\n" << "姓名 : " << A.Name << '\n' << "電話號碼: " << A.Phone << '\n' << "編號 : " << A.Id << endl; return; }

  23. 使用傳參照 (pass by reference) 改變struct實例的內容 • 例如: ChangeName(Ea, “Jackson”); • 對應的「被呼叫函數」則定義成: void ChangeName (Employee& A, char NewName[]) { strcpy(A.Name, NewName); return; }

  24. 範例程式 檔案 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; }

  25. 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; }

  26. 執行結果

  27. 使用指標改變struct實例的內容 • 使用傳址(pass-by-address) 來達到使用參照的目的: ChangeId(&Ea, 00128); • 「被呼叫函數」則定義為 void ChangeId(Employee* pE, int NewId) { (*pE).Id=NewId; return; }

  28. pE與Ea之間的關係

  29. C++ 的具象指標符號 -> • 將 (*pE).Name寫成: pE->Name • 表示「由pE指向的struct變數內的成員 Name」。

  30. 進一步改寫 ChangeId() void ChangeId(Employee* pE, int NewId) { pE->Id = NewId; return; }

  31. 範例程式 檔案 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; }

  32. 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; }

  33. 執行結果

  34. struct實例的動態宣告 • 亦即struct實例的動態記憶體配置(dynamic memory allocation)。 • 下列敘述則可以在執行時才臨時決定陣列的大小: int Size; cin >> Size; Employee* pE = new Employee[Size];

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

  36. 使用陣列下標或指標算數存取內部成員 • 例如,要取用第k個陣列元素內的成員Id,下述語法都是正確的: Labor[k].Id (*(Labor + k)).Id (Labor + k)->Id pE[k].Id (*(pE + k)).Id (pE + k)->Id

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

  38. 範例程式 檔案 DynStruct.cpp // DynStruct.cpp #include <iostream> using std::cin; using std::cout; struct Employee { char Name[20]; char Phone[10]; int Id; }; // --------- 主程式 ------------------------

  39. int main() { int Size; cout << "請輸入 Employee 的數目:\n"; cin >> Size; Employee* pE = new Employee[Size]; delete [] pE; return 0; }

  40. 指標成員與資料結構 • struct所宣告的資料型態可以使用「指標」做為成員。 • 指標成員可以指向自己所在的struct資料型態,稱為「自我參照」(auto-reference)。例如: Struct Data { int Id; Data* pD; };

  41. 串列 (lists) • 定義一串的Data變數: Data D1, D2, D3; D1.pD = &D2; D2.pD = &D3; • 圖示如下: • 串列最後一個元素內的指標值為NULL (亦即 ‘\0’),用來做為檢查串列是否「到此為止」的根據。

  42. 串列 (lists) • 「節點」(node): 每一個用來儲存資料的元素第一個節點稱為 • 「開頭」(head): 第一個節點。 • 「結尾」(tail): 最後的節點。

  43. 在陣列插入一個元素 int* V = new int [Size]; • 必需同時將V[1] 及其之後的所有元素往右移,且無法應付陣列因長度增加而記憶空間可能不足的問題。

  44. 「串列」可以帶來的便利 • 使用串列(linked list) 可以較有效率地完成元素增刪的動作。 • 設想原先有A, B, C 三個元素串接在一起形成一個串列:

  45. 一個串列的範例 • 假設使用struct宣告了一個名叫 Element 的自訂資料形態: struct Element { int Value; Element* Next; };

  46. 動態產生任意數目的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;

  47. 顯示現有串列元素 Element* pShow; for (pShow = pE; pShow != NULL; pShow=pShow->Next) cout << pShow->Value << ' '; • 不斷更換指標使它指向下一個元素的位址。

  48. 以while迴圈顯示現有串列元素 Element* pShow=pE; while (pShow != NULL) { cout << pShow->Value << ' '; pShow = pShow->Next; }

  49. 將顯示串列內容的功能封裝到函數中 void ShowElement(Element* pShow) { while (pShow != NULL) { cout << pShow->Value << ' '; pShow = pShow->Next; } }

  50. 範例程式 檔案 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; } }

More Related