#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
void string_basics() {
string s1 = "craig david";
string s2("7 days");
string s3 = s2;
string s4(10, 'a'); // "aaaaaaaaaa"
cout << s4 << endl;
}
void string_traversal() {
string s1 = "craig david";
// 1. 陣列式
for (int i = 0; i < s1.length(); ++i) cout << s1[i] << endl;
// 2. 迭代器
for (auto it = s1.begin(); it != s1.end(); ++it) cout << *it << " ";
cout << endl;
// 3. at() 含邊界檢查
try {
for (int i = 0; i < s1.length() + 3; ++i) cout << s1.at(i) << " ";
} catch (...) { cout << "例外" << endl; }
}
void string_conversion() {
string s1 = "walking away";
const char* c = s1.c_str(); // string → C 字串
printf("%s\n", c);
char arr[50] = {0};
s1.copy(arr, 4, 0); // 複製前 4 字元到 char 陣列
cout << arr << endl; // "walk"
}
void string_concat() {
string s1 = "alan", s2 = "jackson";
string s3 = s1 + s2;
s3.append(" pray"); // "alanjackson pray"
cout << s3 << endl;
}
void string_find_replace() {
string s1 = "apple google apple iphone";
int idx = s1.find("google", 0); // 6
// 統計 "apple" 出現次數
int cnt = 0, pos = s1.find("apple", 0);
while (pos != string::npos) {
++cnt; pos += 5; pos = s1.find("apple", pos);
}
// 替換第一個 "apple" 為 "jobs"
s1.replace(0, 5, "jobs");
// 替換所有 "apple"
pos = s1.find("apple", 0);
while (pos != string::npos) {
s1.replace(pos, 5, "jobs");
pos += 5; pos = s1.find("apple", pos);
}
}
void string_erase_insert() {
string s1 = "apple google apple iphone";
auto it = find(s1.begin(), s1.end(), 'g');
s1.erase(it); // 刪除單一字元
s1.insert(0, "macos"); // 開頭插入
s1.insert(s1.length(), " facebook"); // 結尾插入
cout << s1 << endl;
}
void string_case_convert() {
string s1 = "JASON";
transform(s1.begin(), s1.end(), s1.begin(), ::tolower); // "jason"
transform(s1.begin(), s1.end(), s1.begin(), ::toupper); // "JASON"
}
#include <vector>
void printVector(const vector<int>& v) {
for (int i = 0; i < v.size(); ++i) cout << v[i] << endl;
}
void vector_basics() {
vector<int> v1;
v1.push_back(20); v1.push_back(40); v1.push_back(15); v1.push_back(7);
vector<int> v2 = v1; // 複製建構
vector<int> v3(v1.begin(), v1.begin()+2); // 部分複製
printVector(v3);
}
void vector_modify() {
vector<int> v1 = {20, 40, 15, 7};
v1.front() = 11; // 修改首元素
v1.back() = 90; // 修改尾元素
v1.pop_back(); // 刪除尾元素
while (!v1.empty()) {
cout << "末尾: " << v1.back() << endl;
v1.pop_back();
}
}
void vector_array_access() {
vector<int> v1 = {20, 40, 15, 7};
v1[2] += 10; // 隨機存取
vector<int> v2(10); // 預設大小 10
for (int i = 0; i < v2.size(); ++i) v2[i] = i + 1;
printVector(v2);
}
void vector_iterators() {
vector<int> v1 = {20, 40, 15, 7};
// 正向
for (auto it = v1.begin(); it != v1.end(); ++it) cout << *it << endl;
// 反向
for (auto it = v1.rbegin(); it != v1.rend(); ++it) cout << *it << endl;
}
void vector_erase_insert() {
vector<int> v1(10);
iota(v1.begin(), v1.end(), 1); // 1..10
auto it = v1.begin() + 3;
v1.erase(it); // 刪除單一位置
v1.erase(v1.begin(), v1.begin()+3); // 刪除區間 [begin, begin+3)
// 邊遍歷邊刪除(注意 erase 返回下一個有效迭代器)
for (auto it = v1.begin(); it != v1.end(); ) {
if (*it == 5) it = v1.erase(it);
else ++it;
}
v1.insert(v1.begin() + 2, 100); // 插入單一元素
v1.insert(v1.end() - 1, 200);
printVector(v1);
}
#include <deque>
void printDeque(const deque<int>& q) {
for (int i = 0; i < q.size(); ++i) cout << q[i] << endl;
}
void deque_demo() {
deque<int> d1;
d1.push_back(2); d1.push_back(10); // 尾部插入
d1.push_front(-90); d1.push_front(-30); // 頭部插入
printDeque(d1);
// 查找 -90 的索引
auto it = find(d1.begin(), d1.end(), -90);
if (it != d1.end()) {
cout << "索引: " << distance(d1.begin(), it) << endl;
}
}
#include <stack>
#include <queue>
#include <functional>
void stack_demo() {
stack<int> s;
for (int i = 0; i < 10; ++i) s.push(i+1);
while (!s.empty()) { cout << s.top() << endl; s.pop(); }
}
void queue_demo() {
queue<int> q;
q.push(78); q.push(18); q.push(20); q.push(33);
while (!q.empty()) { cout << q.front() << endl; q.pop(); }
}
void priority_queue_demo() {
// 最大堆(預設)
priority_queue<int> pq1;
pq1.push(12); pq1.push(3); pq1.push(40); pq1.push(15);
while (!pq1.empty()) { cout << pq1.top() << endl; pq1.pop(); }
// 最小堆
priority_queue<int, vector<int>, greater<int>> pq2;
pq2.push(12); pq2.push(3); pq2.push(40); pq2.push(15);
while (!pq2.empty()) { cout << pq2.top() << endl; pq2.pop(); }
}
#include <list>
void printList(const list<int>& lst) {
for (auto it = lst.begin(); it != lst.end(); ++it) cout << *it << endl;
}
void list_demo() {
list<int> lst;
for (int i = 0; i < 10; ++i) lst.push_back(i);
lst.push_front(80); lst.push_front(90);
// list 不支援隨機存取,不可 it + 3
auto it = lst.begin(); ++it; // 第二個元素
lst.erase(it); // 刪除單一
lst.erase(lst.begin(), next(lst.begin(), 3)); // 刪除區間
lst.remove(5); // 依值刪除所有 5
lst.insert(next(lst.begin()), 100); // 指定位置插入
printList(lst);
}
#include <set>
#include <functional>
void printSet(const set<int>& s) {
for (auto it = s.begin(); it != s.end(); ++it) cout << *it << endl;
}
void set_demo() {
set<int> s;
for (int i = 0; i < 10; ++i) s.insert(i+1);
s.insert(20); s.insert(15); s.insert(15); // 重複值被忽略
auto it = s.begin(); ++it; s.erase(it); // 刪除第二個
// 自訂排序:由大到小
set<int, greater<int>> s2;
s2.insert(10); s2.insert(5); s2.insert(20); s2.insert(99);
// 99, 20, 10, 5
// 自訂類別排序
struct Teacher { char* name; int age; };
struct AgeCmp { bool operator()(const Teacher& a, const Teacher& b) { return a.age < b.age; } };
set<Teacher, AgeCmp> s3;
s3.insert({"jack", 18}); s3.insert({"rose", 20}); s3.insert({"jason", 22});
// 依年齡排序,相同年齡視為相同(不會插入)
// 查找範圍
auto range = s.equal_range(4); // pair<lower_bound, upper_bound>
}
#include <map>
#include <string>
void printMap(const map<int, string>& m) {
for (auto it = m.begin(); it != m.end(); ++it)
cout << it->first << "," << it->second << endl;
}
void map_demo() {
map<int, string> m;
m.insert({1, "jack"});
m.insert(make_pair(2, "rose"));
m.insert(map<int,string>::value_type(3, "jason"));
m[4] = "alan"; // 運算子[]:不存在則插入,存在則覆蓋
// 刪除
auto it = m.begin(); ++it; m.erase(it);
// 檢查插入結果
auto res = m.insert({3, "alan"});
if (res.second) cout << "成功" << endl; else cout << "失敗(key已存在)" << endl;
// equal_range 查找
auto range = m.equal_range(2);
if (range.first != m.end()) {
cout << range.first->first << range.first->second << endl; // key=2
cout << range.second->first << range.second->second << endl; // key>2
}
}
struct Employee { char* name; int age; };
void multimap_demo() {
multimap<string, Employee> dept;
dept.insert({"開發", {"擱淺", 20}});
dept.insert({"開發", {"彪哥", 20}});
dept.insert({"財務", {"小穎", 16}});
dept.insert({"財務", {"rose", 20}});
// 遍歷所有
for (auto it = dept.begin(); it != dept.end(); ++it)
cout << it->first << "," << it->second.name << "," << it->second.age << endl;
// 僅取得「財務」部門員工
int cnt = dept.count("財務");
auto it = dept.find("財務");
for (int i = 0; i < cnt && it != dept.end(); ++it, ++i)
cout << it->first << "," << it->second.name << "," << it->second.age << endl;
}
含指標成員的類別若未自訂拷貝建構函數與指派運算子,預設淺拷貝會導致雙重釋放錯誤:
class Employee {
char* name;
int age;
public:
Employee(const char* n, int a) {
name = new char[strlen(n)+1];
strcpy(name, n);
age = a;
}
~Employee() { delete[] name; }
// 深拷貝建構函數
Employee(const Employee& obj) {
name = new char[strlen(obj.name)+1];
strcpy(name, obj.name);
age = obj.age;
}
// 深拷貝指派運算子
Employee& operator=(const Employee& obj) {
if (this != &obj) {
delete[] name;
name = new char[strlen(obj.name)+1];
strcpy(name, obj.name);
age = obj.age;
}
return *this;
}
};
將此類物件放入 vector 時,push_back 會觸發拷貝建構,深拷貝確保各物件擁有獨立記憶體,析構時不會重複釋放。