# C++ 自主學習的紀錄 #include <iostream> 跟 using namespace std: 筆記中省略 ## 指標 ```cpp= int n; //&n 表n的位址 int *p=&n; //*p為指標且p是n的位址 *p=10; //用*p提取p處的值,若修改*p則n亦改變 int *p=0; //不知為何定義時似乎只能用0或是&n //p+1:0x4 int每次+4(16進位),而double則是8,etc.,陣列中亦然 int **pp=&p; //指標的指標 int arr[1][2][3]={{...},{...}}; int (*p)[2][3]=arr;//n層陣列的指標,要宣告n-1層的陣列,但其實有點看不太懂,上面也說用auto比較方便 int *p = new int(100); //建立位址並賦予儲存值用new delete p; //刪除該項空間用delete ``` ## vector 線性、長度可變 ```cpp= #include <vector> vector <int> v={1,2,3}; //有點像陣列 vector <int> v0(v); //複製一個一樣的,同......v0=v s=v.size();// 得知元素個數 e=v.empty();// 得知是否為空 f=v.front();// 取得第一個元素 b=v.back();// 取得最後的元素 v.push_back(n)// 新增元素到最後 v.pop_back();// 取出back v.clear();// 清空 //主題外學到的 auto n=10 //自動判斷資料型態 auto a[]={...} //也可以用向量 vector <auto> a{...} for (auto b:a) //每次的b分別對應a的值,做a的長度次 { cout << b << endl; 輸出a的每一項 } #include <algorithm> //其中的sort跟find的部分用法 sort (a.begin(),a.end()) //把a排序,兩個位置是起點跟終點 f=find (a.begin(),a.end(),1); //在a中找1,起點終點和目標,若a中無1,則f將為a的最後一項 ``` ## stack 堆疊,可變、線性、可從最後面拿出or放入資料 ```cpp= stack<int> s,s1;//宣告stack s.push(z);從最後放入z s.pop();拿掉最後的 e=s.empty();檢查是否為空 s.swap(s1);交換兩組數據 si=s.size();查看數量 t=s.top();看最後一項 ``` ## array 線性、長度不變 ```cpp= #include <array> array<int,5> number; //長度5的array s=a.size();// 得知元素個數 e=a.empty();// 得知是否為空,可是不知為何,只有在長度為0時會被判斷為空 f=a.front();// 取得第一個元素 b=a.back();// 取得最後的元素 a.fill(n);// 設定a中元素為n //大致上跟vector差不多,但是無法改變長度,宣告時要宣告長度,無改變長度的方法 ``` ## string ```cpp= #include <string> string s1; //空的 string s2("abc"); //內容是abc string s3(s2); //內容跟s2一樣 意思同 string s3=s2; string s4="abc"; //內容是abc /* s.size()、s.length() 取得字串長度 s.empty() 是否為空 可用==比較兩string內容是否相同 */ //可string=char[],但不可char[]=string s2=s2+"xyz" //s2會變成abcxyz s2=s2+"/n" //變成abcxyz換行 s2[0]//a s2[1]//b用法同char[] for (auto n:s2) { cout << n; }//可用for range 語法 ``` ## algoriyhm(有與vector的組合) ```cpp= #include <algorithm> #inlcude <vector> //互換(swap) swap(a,b);//交換a&b值 //排序(sort)及反轉(reverse)vector vector <int> v; v={1,2,6,7,85,201,35,67}; sort(v.begin(),v.end()); reverse(v.begin(),v.end()); //v.begin()跟v.end()是指標 //排序及反轉陣列 int v[]={1,2,6,7,85,201,35,67}; sort(v,v+sizeof(v)/sizeof(int)); reverse(v,v+sizeof(v)/sizeof(int)); /*sort&reverse 括號中前面的v好像是因為v[]是陣列,所以v會等同於&v[0], 該v會變成指該陣列的第一個數字的指標而sizeof(v)則會看v用了多少空間(4*8), 除以sizeof(int)也就是4以後就會陣列長度,所以此處也可以直接輸入v+8。*/ //upper bound & lower bound //陣列版本 int v[]={1,2,6,7,85,201,35,67}; sort(v,v+sizeof(v)/sizeof(int)); int x=85; int *l = lower_bound(v,v+sizeof(v)/sizeof(int),x); int *u = upper_bound(v,v+sizeof(v)/sizeof(int),x); cout << "lower bound is " << *l << endl; cout << "upper bound is " << *u << endl; //lower bound 是找v至v+sizeof(v)/sizeof(int)中,>=x的值,upper bound則是>x的 //需先將v由小至大排序 //vector版本 vector <int> v; v={1,2,6,7,85,201,35,67}; v.begin(),v.end()); int x=85; auto l = lower_bound(v.begin(),v.end(),x); auto u = upper_bound(v.begin(),v.end(),x); cout << "lower bound is " << *l << endl; endl; ``` ## 算交點 輸入n條線 然後分別輸入每條線的a,b,c(ax+by=c) 輸出每個交點 ```cpp= #include <iostream> using namespace std; int main() { int n,i,j,k; cin >> n; float a[n],b[n],c[n]; for (i=0;i<n;i++) { cin >> a[i] >> b[i] >> c[i]; } for (i=0;i<n;i++) { for (j=i+1;j<n;j++) { cout << "(" << (c[i]*b[j]-b[i]*c[j])/(a[i]*b[j]-b[i]*a[j]) << "," << (c[i]*a[j]-a[i]*c[j])/(b[i]*a[j]-a[i]*b[j]) << ")" << endl; } } return 0; } ``` 結果呈現: ![](https://i.imgur.com/1MHt9sm.jpg) ##遞迴:河內塔 三根柱子(A、B、C),一開始有由大到小n個圓盤(1,2,3,4,5...n)在A上,求如何將所有移動到C。 大盤不得在小盤之上 一次只能移動一個 非移動中的盤子需在柱子上 輸入:n(n為不超過15的自然數) ```cpp= #include <iostream> using namespace std; void f(int n,int a,int b) { char ch[3]={'A','B','C'}; int c=1; for(int i=0;i<2;i++) { if (c==a||c==b) c++; } if(n==1) cout << "move ring" << n << " from " << ch[a-1] << " to " << ch[b-1] << endl; else { f(n-1,a,c); cout << "move ring" << n << " from " << ch[a-1] << " to " << ch[b-1] << endl; f(n-1,c,b); } } int main() { int in=0; while (in>15||in<1) { cin >> in; } f(in,1,3); return 0; } ``` 結果呈現:(6以上程序過於複雜,會超出畫面,便用5舉例) ![](https://i.imgur.com/zGaKrm5.jpg) 解題重點: 1:要先用紙張輔助去想,如何用數學遞迴式表達每層的關係 2:了解子程式可以這樣用,來寫遞迴