# C++語法, 筆記整理 [toc] ## 語法 ### Vector #### 特性 集合尾端增刪元素很快 : O(1) 集合中間增刪元素比較費時 : O(n) #### Code Example * vec.push_back() - 新增元素至 vector 的尾端,必要時會進行記憶體配置。 * vec.pop_back() - 刪除 vector 最尾端的元素。 * [vec.insert() - 插入一個或多個元素至 vector 內的任意位置。](https://vimsky.com/zh-tw/examples/usage/vector-insert-function-in-c-stl.html) * vec.erase() - 刪除 vector 中一個或多個元素。 * vec.clear() - 清空所有元素。 * 初始化宣告`vector<int> v = {1, 2, 3}` `vector<int> v(3, 1)\\v={1,1,1}` ``` 參數: size - 多少個數字要被新增 value - 建一個充滿value的1D vector declare 1D vector ``` ```C++= #include <iostream> #include <vector> using namespace std; int main(){ vector<int> vect{ 10, 20, 30 }; //vector大小 cout<<"vect size:"<<vect.size()<<'\n'; for (int x : vect) cout << x << " "; return 0; } ``` declare 1D vector with initial size ```C++= #include <iostream> #include <vector> using namespace std; int main(){ vector<int> vect(10); //vector大小 cout<<"vect size:"<<vect.size()<<'\n'; for (int x : vect) cout << x << " "; return 0; } ``` declare 2D vector ```C++= #include <iostream> #include <vector> using namespace std; int main(){ vector<vector<int> > vect{ { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } }; // Displaying the 2D vector for (int i = 0; i < vect.size(); i++) { for (int j = 0; j < vect[i].size(); j++) cout << vect[i][j] << " "; cout << endl; } } ``` ### Stack ```C++ // CPP program to illustrate // Implementation of push() function #include <iostream> #include <stack> using namespace std; int main() { // Empty stack stack<int> mystack; mystack.push(0); mystack.push(1); mystack.push(2); // 获取并删除栈顶的元素 int topValue = myStack.top(); // 获取栈顶元素的值 myStack.pop(); // 删除栈顶元素 // Printing content of stack while (!mystack.empty()) { cout << ' ' << mystack.top(); mystack.pop(); } } ``` ### Array ```C++= //define int foo [5] = { 10,5,15,3,7}; //intialize array to zero int array[10] = {0}; //get array size //total byte / first byte int n = sizeof(foo) / sizeof(foo[0]); ``` ### Hashmap ```C++= #include <iostream> #include <unordered_map> using namespace std; int main() { unordered_map<string, int> umap; // inserting values by using [] operator umap["GeeksforGeeks"] = 10; umap["Practice"] = 20; umap["Contribute"] = 30; // Traversing an unordered map for (auto x : umap) cout << x.first << " " << x.second << endl; } ``` #### Hashmap erase ```C++= #include <iostream> #include <unordered_map> struct Node { int data; }; int main() { std::unordered_map<int, Node*> dict; // 创建一些键值对并插入到unordered_map中 Node* node1 = new Node{1}; Node* node2 = new Node{2}; Node* node3 = new Node{3}; dict.insert({1, node1}); dict.insert({2, node2}); dict.insert({3, node3}); // 删除指定键的元素 int keyToRemove = 2; size_t numRemoved = dict.erase(keyToRemove); // 检查是否成功删除了元素 if (numRemoved > 0) { std::cout << "元素删除成功。" << std::endl; // 可以在这里释放被删除节点的内存 } else { std::cout << "未找到要删除的元素。" << std::endl; } return 0; } ``` ### Unorderset + vector //功能與hashmap相同,加速查找 ```=C++ int main() { int n = 4; vector<vector<int>> roads{{0,1},{1,2},{2,3},{2,0}}; vector<unordered_set<int>> graph(n); // Building the graph (adjacency list). for (const auto& road: roads) { graph[road[0]].insert(road[1]); graph[road[1]].insert(road[0]); } for(int i=0;i<n;i++){ cout<<i<<":"<<graph[i].size()<<endl; } } ``` ### Tree ```C++= #include <iostream> using namespace std; //定義樹的結構 // root // / \ // left right struct TreeNode { int val; TreeNode *left; TreeNode *right; TreeNode(int x) : val(x), left(NULL), right(NULL) {} }; int main() { //產生一個node,並定義node數值 TreeNode* root = new TreeNode(10); //產生一個node,並定義node數值 TreeNode* rootleft = new TreeNode(5); //街上root左邊的node root->left = rootleft; //imshow cout<<root->val<<endl; //把root移到左方 root = root->left; //imshow cout<<root->val<<endl; return 0; } ``` ### string ```C++= string s ="ABCD"; int len = s.length(); ``` ### pointer ```C++= int b = 2; //從這個地址中取出變數b的值 //&是取出地址,*是取出地址裡面的值 //*&b == b printf("變數 b 的值:%d\n", b); printf("變數 b 的值:%d\n", *&b); //指標宣告方式 指標指向b的位置 int* pointer = &b int a; // 一個整型數 int *a; // 一個指向整數的指標 int **a; // 一個指向指標的指標,它指向的指標是指向一個整型數 int a[10]; // 一個有10個整數型的陣列 int *a[10]; // 一個有10個指標的陣列,該指標是指向一個整數型的 int (*a)[10]; // 一個指向有10個整數型陣列的指標 int (*a)(int); // 一個指向函數的指標,該函數有一個整數型參數並返回一個整數 int (*a[10])(int); // 一個有10個指標的陣列,該指標指向一個函數,該函數有一個整數型參數並返回一個整數 ``` ## ostringstream istringstream ``` C++= //ostringstream用法 ostringstream out; out << "123 " out << "456 " cout << out.str(); // "123 456 " //istringstream用法 string data = "123 456 "; istringstream in(data); string value = ""; in >> value; cout <<value; // "123" in >> value; cout <<value; // "456" ``` ## function ### Selection sort ```C++= void selectionSort(vector<int>& a,vector<int>& idx, int n) { int i, j, min, temp,tmp_idx; for (i = 0; i < n - 1; i++) { min = i; for (j = i + 1; j < n; j++) if (a[j] < a[min] || (a[j]==a[min] && idx[j]>idx[min])) min = j; temp = a[i]; a[i] = a[min]; a[min] = temp; tmp_idx = idx[i]; idx[i] = idx[min]; idx[min] = tmp_idx; } } ``` ### 判斷奇數(AND應用) ```C++= int num=10; if num & 1 ? cout<<"奇數": cout<<"偶數"; ``` ### 找出數列中的唯一數字(XOR應用) 預設數列內僅有一個數字出現一次,其他都是重複兩次 ```C++= #include <iostream> #include <vector> using namespace std; int main() { vector<int> nums{4,1,2,1,2}; for(int i=1;i<nums.size();i++){ nums[0] ^= nums[i]; } cout<<nums[0]; } ``` ### swap(XOR應用) ```=C++ void swap(int & a,int & b){ a^=b; b^=a; a^=b; } ``` # C與C++差異與其他語言差異 ## C & C++ 與其他新一代語言 * (a)C & C++: * 透過編譯器和連結器,直接產生原生的機器碼 * (b)新一代的程式語言(Java, C#): * 透過翻譯轉成 bytecode,然後再由虛擬機器(Virtual Machine)來執行 * 優缺點 * (b)的優點:技術先進,移植性 * 可能的缺點:效率(平台差異) * 本質上技術相同,C++ Complier可想成虛擬機器 * 虛擬機器的設定標準 * (a)是共同制定的標準 * (b)架構則是 Sun 或 MS 所制定的 * 框架差異 * 只學C/C++不能解決應用問題,因為它只有基本I/O,至少要學會一種GUI框架,或是database框架 * JAVA/C# 函式庫已包含在框架內 * 型別 * (a) 語言都是採用傳統的靜態型別系統 * 不強制改變使用者自訂型別(UDT: User-defined Type)的記憶體佈局 * 允許在 stack 中配置 UDT 變量(也就是「物件」,但由於在 C 語言中,沒有真正物件導向的觀念,因此以「變量」來指稱) * 你無法在編譯期產生變量,也不可能在執行期產生新的「型別」 * 使得執行期的效率高 * 零成本」原則:「使用者不該為他沒有用到的功能,付出執行期的效率代價」 * (b) 單根繼承的泛化型別系統 * 型別本身也可以當作變量 * 哲學觀點 * (a)把你當大人,給予最高彈性 * (a)不強迫限制或規範 * (a)不內建垃圾回收器(GC: Garbage Collection) ## C與C++差異 * C 語言是 C++ 的一個子集 * C++改進 * 引入 bool 型別 * 鼓勵以 0 而非自行定義的 NULL 巨集等代表空指標。 * 引入 const,讓「常數性」成為與型別不可分割的一部份,除了提升安全,讓編譯器承擔檢核的責任之外,也有助於代碼的優化。 * 引入 const, inline 等用法,減少非必要巨集的使用。(因為展開 巨集是預處理器的動作,沒有通過編譯器,也就沒有型別安全可言)。 * 引入 reference 機制,簡化指標的語法,並有效減少指標(尤其是 兩層以上的複雜指標)的使用。 ref:https://www.ptt.cc/man/C_and_CPP/DB9B/D3B0/M.1475403294.A.F90.html ## bitwise operation 找出Int 第n個bit值 ```C++= int find_bit_val(int num, int bits) { int res = (num & (int)pow(2, bits))>>bits; } ```