seo網(wǎng)站買電腦速成班短期電腦培訓班
第7天:結構體與聯(lián)合體 - 復雜數(shù)據(jù)類型
一、📚 今日學習目標
- 🎯 掌握結構體(struct)的定義與使用
- 🔧 理解聯(lián)合體(union)的特性與適用場景
- 💡 完成圖書館管理系統(tǒng)實戰(zhàn)(結構體數(shù)組操作)
- 🛠? 學會使用typedef簡化類型定義
二、?? 核心知識點詳解
1. 結構體(Struct)
定義與初始化
// 定義結構體
struct Book {string title;string author;int publicationYear;double price;
};// 初始化方式
Book book1 = {"C++ Primer", "Stanley B. Lippman", 2012, 129.99};
Book book2{"Effective C++", "Scott Meyers", 2005}; // 自動填充默認值
成員函數(shù)
struct Circle {double radius;double area() const { // 常成員函數(shù)return 3.14159 * radius * radius;}
};Circle c;
cout << "圓的面積:" << c.area() << endl;
2. 聯(lián)合體(Union)
定義與內(nèi)存分配
union DateTime {int timestamp; // 秒級時間戳struct {int year;int month;int day;} date;
};// 聯(lián)合體所有成員共享同一塊內(nèi)存
DateTime dt;
dt.timestamp = 1672531200; // 2023-01-01 00:00:00
cout << "日期:" << dt.date.year << "-" << dt.date.month << "-" << dt.date.day << endl;
3. 類型別名(typedef)
簡化復雜類型
typedef pair<string, int> StudentID; // C++標準庫類型
typedef vector<pair<string, double>> StockPortfolio;StudentID sid = {"S12345", 2023};
StockPortfolio portfolio = {{"AAPL", 185.5}, {"GOOGL", 2780.3}};
三、🔧 代碼實戰(zhàn):圖書館管理系統(tǒng)
1. 功能需求
- 錄入圖書信息(書名/作者/ISBN/價格)
- 查詢圖書是否存在
- 刪除指定圖書
- 顯示所有圖書信息
2. 實現(xiàn)步驟
#include <iostream>
#include <vector>
#include <string>
using namespace std;struct LibraryBook {string isbn;string title;string author;double price;bool operator<(const LibraryBook& other) const {return isbn < other.isbn; // 按ISBN排序}
};int main() {vector<LibraryBook> books;const int MAX_BOOKS = 100;while (books.size() < MAX_BOOKS) {LibraryBook book;cout << "請輸入圖書ISBN(輸入q退出):";cin >> book.isbn;if (book.isbn == "q") break;cin.ignore(numeric_limits<streamsize>::max(), '\n');getline(cin, book.title);getline(cin, book.author);cout << "請輸入價格:";cin >> book.price;books.push_back(book);}// 查詢功能string queryIsbn;cout << "\n🔍 查詢圖書(輸入q退出):" << endl;while (cin >> queryIsbn && queryIsbn != "q") {bool found = false;for (const auto& book : books) {if (book.isbn == queryIsbn) {cout << "📖 圖書信息:" << endl;cout << "ISBN: " << book.isbn << endl;cout << "書名: " << book.title << endl;cout << "作者: " << book.author << endl;cout << "價格: $" << book.price << endl;found = true;break;}}if (!found) {cout << "📝 未找到該圖書!" << endl;}}return 0;
}
四、🛠? 進階技巧
1. 結構體數(shù)組排序
vector<Student> students = {...};
sort(students.begin(), students.end(), [](const Student& a, const Student& b) {return a.score > b.score; // 按成績降序排列
});
2. 聯(lián)合體在位操作中的應用
union Byte {unsigned char uc;int i;
};Byte b;
b.uc = 0xAA; // 二進制10101010
cout << "十六進制表示:" << hex << b.i << endl; // 輸出0xaa
3. 匿名結構體
struct {int x;int y;
} point = {10, 20}; // 直接使用無需typedef
五、? 常見問題解答
Q:結構體和類有什么區(qū)別??
→ 結構體默認public訪問權限,類默認private;結構體通常用于數(shù)據(jù)聚合,類強調(diào)封裝和繼承
Q:聯(lián)合體如何保證數(shù)據(jù)完整性??
→ 需要手動記錄當前存儲的是哪種類型的數(shù)據(jù)
Q:typedef和using有什么區(qū)別??
→ C++中using可以替代typedef的所有功能,還支持模板參數(shù)推導
六、📝 今日總結
? 成功掌握:
- 📚 結構體的定義與成員函數(shù)
- 💡 聯(lián)合體的內(nèi)存共享特性
- 🔄 圖書館管理系統(tǒng)的完整實現(xiàn)
- 🔧 類型別名的靈活運用
? 明日預告:
- 面向?qū)ο缶幊倘腴T(類與對象/封裝/繼承)
七、📝 課后挑戰(zhàn)任務
1. 🌟 擴展圖書館系統(tǒng):
- 添加借閱功能(記錄借閱人信息)
- 實現(xiàn)按價格區(qū)間篩選圖書
2.🔍 聯(lián)合體應用:
// 完成時間格式轉(zhuǎn)換程序
union Time {int totalSeconds;struct {int hours;int minutes;int seconds;};
};Time t;
t.totalSeconds = 3661;
cout << "時間表示:" << t.hours << "小時"<< t.minutes << "分鐘" << t.seconds << "秒" << endl;
3. 📝 技術總結:
- 繪制結構體與聯(lián)合體的內(nèi)存對比圖
- 列舉5個典型結構體應用場景(如Point/Rectangle/Student等
🔍 上一天課后挑戰(zhàn)任務答案
任務1:改進學生管理系統(tǒng)(帶等級判定和姓名查詢)
#include <iostream>
#include <iomanip>
#include <algorithm>
#include <vector>
using namespace std;struct Student {string name;double score;char grade; // 新增等級字段
};// 計算等級的輔助函數(shù)
char calculateGrade(double score) {if (score >= 90) return 'A';else if (score >= 80) return 'B';else if (score >= 70) return 'C';else if (score >= 60) return 'D';else return 'F';
}int main() {const int N = 5;vector<Student> students(N);// 錄入學生信息并計算等級for (int i = 0; i < N; ++i) {cin >> students[i].name >> students[i].score;students[i].grade = calculateGrade(students[i].score);}// 按姓名查詢成績string queryName;cout << "\n🔍 按姓名查詢成績:" << endl;cin >> queryName;bool found = false;for (const auto& s : students) {if (s.name == queryName) {cout << "姓名:" << s.name << " | 成績:" << s.score << " | 等級:" << s.grade << endl;found = true;break;}}if (!found) {cout << "📝 未找到該學生的記錄!" << endl;}// 輸出完整信息(含等級)cout << "\n📊 學生成績單:" << endl;for (const auto& s : students) {cout << setw(10) << left << s.name << setw(8) << right << s.score << setw(4) << right << s.grade << endl;}return 0;
}
任務2:指針迷宮修正
原錯誤代碼
int arr[] = {1,2,3,4,5};
void update(int* p) {p = new int[10];for (int i=0; i<10; i++) {p[i] = i*10;}
}
int main() {int* p = arr;update(p);cout << *p << endl;return 0;
}
錯誤分析
- 函數(shù)
update
內(nèi)部重新綁定了指針p
,但并未修改原始指針的值 main
函數(shù)的p
仍然指向原數(shù)組,未指向新分配的內(nèi)存
修正版本
#include <iostream>
using namespace std;void update(int*& p) { // 傳遞指針的引用p = new int[10];for (int i=0; i<10; i++) {p[i] = i*10;}
}int main() {int arr[] = {1,2,3,4,5};int* p = arr;update(p); // 傳遞指針的引用cout << *p << endl; // 輸出10delete[] p; // 釋放內(nèi)存return 0;
}
任務3:技術總結
指針與內(nèi)存地址關系示意圖
假設存在以下指針操作:
int num = 42;
int* p = #
int**? pp = &p;內(nèi)存布局:
+--------+-------+------+
| num | p | pp |
+--------+-------+------+
| 42 | 0x100 | 0x200|
+--------+-------+------+
地址: 0x100 0x200 0x300
常見內(nèi)存錯誤類型
錯誤類型 | 現(xiàn)象 | 預防方法 |
---|---|---|
內(nèi)存泄漏 | 程序占用內(nèi)存持續(xù)增長 | 使用智能指針/delete及時釋放 |
野指針 | 訪問未初始化或失效內(nèi)存 | 初始化指針為nullptr |
越界訪問 | 數(shù)組/指針越界 | 嚴格檢查下標范圍 |
內(nèi)存重復釋放 | 運行時崩潰 | 為每個new分配唯一delete |