## 第四堂社課 --- ## 複習 ---- ## 遞增(```++```)與遞減(```--```)運算子 ```cpp= #include<iostream> using namespace std; int main(){ int a=1;//a=1 a++; cout<<a;//a=2 ++a; cout<<a;//a=3 a--; cout<<a;//a=2 --a; cout<<a;//a=1 } ``` ---- ## 前置(```++a```)與後置(```a++```)的區別 其實沒啥區別。 但在運算上會有些許的不同: ```cpp= int a,count=5; a=count+++5;//a=10 ``` ```cpp= int a,count=5; a=++count+5;//a=11 ``` ---- ## for 迴圈基本語法 ```cpp= for (初始;判斷;運算) { 陳述句; } ``` 初始:只在進入迴圈時執行 判斷:判斷是否繼續迴圈 運算:每次一個迴圈循環後執行 ---- ## scratch 解釋 ![image](https://hackmd.io/_uploads/Sk4JZhEx-x.png) ---- ## while 迴圈基本語法 ```cpp= while(判斷) { 陳述句; } ``` 判斷:判斷是否繼續迴圈 ---- ## scratch 解釋 ![image](https://hackmd.io/_uploads/SyrsM2ExZl.png) ---- ## do...while 迴圈基本語法 ```cpp= do{ 陳述句; }while(判斷); ``` 判斷:判斷是否繼續迴圈 ---- ## scartch 解釋 ![image](https://hackmd.io/_uploads/B187BnEg-g.png) ---- ## 略過迴圈迭代 當有一個迴圈你不想要執行時 你可以使用```continue```來跳過 ---- ## 中斷迴圈 當有一個迴圈之後的迴圈你都想要跳過時 你可以使用```break```來跳過 ---- ## 巢狀敘述 當你將多個條件判斷式或迴圈一層一層組合在一起 即稱之為**巢狀敘述** ![image](https://hackmd.io/_uploads/H1NAV3VeWe.png) --- ## APCS 初級題目挑戰!!! 今天我們來練習歷屆 APCS 的第一題 !!! 二十分鐘內只要寫出一題 AC ,就可以來拿獎品 !!! 只限前六名喔 !!! 以防還有人不知道課程代碼就先打在這裡了: ```+cYejX``` --- ## 陣列 ---- ## 陣列的意義 當我們需要存取許多性質與功用相同,且具有連續性的值時,我們可以使用陣列將他們整合在一起 ---- ## 不用陣列 ```cpp= #include<iostream> using namespace std; int main(){ int a0,a1,a2,a3,a4,a5,a6,a7,a8,a9; cin>>a0>>a1>>a2>>a3>>a4>>a5>>a6>>a7>>a8>>a9; cout<<a0<<'\n'<<a1<<'\n'<<a2<<'\n'<<a3<<'\n'<<a4<<'\n'<<a5<<'\n'<<a6<<'\n'<<a7<<'\n'<<a8<<'\n'<<a9<<'\n'; } ``` 很麻煩,手打得很酸 ---- ## 使用陣列 ```cpp= #include<iostream> using namespace std; int main(){ int a[10]; for(int i=0;i<10;i++)cin>>a[i]; for(inti=0;i<10;i++)cout<<a[i]<<'\n'; } ``` 簡潔有力,十分方便 --- ## C 風格陣列 ---- ## 資料型別 在學習陣列之前,先複習一下之前教過的資料型別 | 名稱 | 儲存值 | 例子 | | :--------: | :--------: | :--------: | | int | 整數 | 1 | | double | 浮點數(小數) | 1.1 | | bool | 布林值(1或0) | true | | char | 字母 | a | | string | 字串 | XiaoChengYi | ---- ## C 風格陣列的宣告與定義 ```cpp= 資料型別 陣列名稱[陣列長度]={第零項,第一項,...,第(陣列長度-1)項}; ``` 舉例: ```cpp= int a[3]={0,1,2}; bool b[4]={true,false,1,0}; char c[5]={'c','h','a','r','\0'}; //char 型態的陣列在末項以 '\0' 表示字串結束 double d[2]={3.14159,2.71828}; string e[3]={"Xiaochengyi","Rollingmaster","KaiKai"}; ``` ---- ## C 風格陣列的改變 當我們需要改變 C 風格陣列中的資料時,可以使用賦值運算子 ```=``` ```cpp= #include<iostream> using namespace std; int main(){ int a[3]={0,1,2};//0 1 2 //陣列的索引(項數)是從 0 開始的 a[0]=3;//3 1 2 a[1]=4;//3 4 2 a[2]=5;//3 4 5 } ``` ---- ## C 風格陣列的引用 當我們需要讀取資料的時候,就會需要引用 C 風格陣列中的值,所以我們會使用 ```[]operator``` ```cpp= #include<iostream> using namespace std; int main(){ int a[3]; //陣列的索引(項數)是從 0 開始的 for(int i=1;i<=3;i++)cin>>a[i]; //int a[3]={0,1,2} cout<<a[0]<<endl;//0 cout<<a[1]<<endl;//1 cout<<a[2]<<endl;//2 } ``` ---- ## 圖解 ```[]operator``` ![image](https://hackmd.io/_uploads/S1l0_yDeWl.png) ---- ## 小練習:找出該項對應的值 ``` int a[5]={0,3,5,6,-1}``` 1.``` a[1]``` 2. ```a[3]``` 3. ```a[5]``` ---- ## 解答 1.```a[1]``` =```3``` 2.```a[3]```=```6``` 3.```a[5]```=不存在 ---- ## C 風格陣列多維陣列 當我們的資料不只是一個維度的時候,我們就需要用到多維陣列 ```cpp= //假設我們需要九宮格,每一格都存取一個數字 #include<iostream> using namespace std; int main(){ int a[3][3]={ {1,2,3}, {4,5,6}, {7,8,9} } //使用巢狀結構輸出二微陣列 a for(int i=0;i<3;i++){ for(int j=0;j<3;j++){ cout<<a[i][j]<<' '; } } //1 2 3 4 5 6 7 8 9 } ``` --- ## C++ `std::vector` ---- ## 為甚麼要用 `std::vector` ? ```std::vector``` 是 C++ 標準函式庫 ```<vector>``` 中資料結構。與 C 風格陣列不一樣的地方是,他是一種動態陣列,可以自動調整大小,不需要另外去做動態分配的部分,十分的方便,一定要學起來。 ---- ## 使用 C 風格陣列 ```cpp= #include<iostream> using namespace std; int main(){ int a[3]; for(int i=0;i<3;i++)cin>>a[i]; cin>>a[3];//(X) } ``` 當我們需要的陣列長度大於一開始宣告的 C 風格陣列長度時,就沒辦法輸入了,如果真的硬要使用的話就會需要用到動態分配記憶體的概念 ---- ## 使用 `std::vector` ```cpp= #include<iostream> #include<vector> using namespace std; int main(){ vector<int>a(3); for(int i=0;i<3;i++)cin>>a[i]; a.resize(4); cin>>a[3]; } ``` 當我們想要增長 ```std::vector``` 時,只需要用簡單的修飾器(後面會教)就可以完成; ---- ## `std::vector` 的宣告與定義 ```cpp= std::vector<資料型別>陣列名稱(陣列長度) std::vector<資料型別>陣列名稱(陣列長度,值) std::vector<資料型別>陣列名稱({第 0 項,第 1 項,...,第 n-1 項}) ``` 長度:初始陣列長度 值:當寫入某一個值時,它會自動將 ```std::vector``` 的每一項都初始化成該值 ---- ## 範例 ```cpp= #include<iostream> #include<vector> using namespace std; int main(){ vector<int>a(3); vector<int>b(3,6);// 6 6 6 vector<int>c({1,2,3,4,5,6})//1 2 3 4 5 6 } ``` ---- ## `std::vector` 的引用 我們可以使用 ```[]operator``` 引用 ```std::vector``` 的資料 ```cpp= #include<iostream> #include<vector> using namespace std; int main(){ vector<int>a(3); //陣列的索引(項數)是從 0 開始的 for(int i=1;i<=3;i++)cin>>a[i]; //int a[3]={1,2,3} cout<<a[0]<<endl;//1 cout<<a[1]<<endl;//2 cout<<a[2]<<endl;//3 } ``` ---- ## 圖解 ```[]operator``` ![image](https://hackmd.io/_uploads/r1tOFJDxbg.png) ---- ## `std::vector` 的引用 除了 ```[]operator``` ,我們也可以使用 ```at()``` ```cpp= #include<iostream> #include<vector> using namespace std; int main(){ vector<int>a({1,2,3}); cout<<a.at(0)<<endl;//1 cout<<a.at(1)<<endl;//2 cout<<a.at(2)<<endl;//3 } ``` 與 ```[] operator``` 不一樣的地方在於, ```at()``` 在引用位置超出邊界時會報錯 ---- ## 圖解 ```at()``` ![image](https://hackmd.io/_uploads/B1A0vJweWe.png) --- ## C++ ```std::vector``` 的基礎操作 ---- ## 迭代器 iterator ```begin()``` 和 ```end()``` 我們可以使用 ```begin()``` 和 ```end()``` 來知道 ```std::vector``` 的起點位置與終點位置 ---- ## 圖解 ```begin()``` ![image](https://hackmd.io/_uploads/BJsGp68gZg.png) ---- ## 圖解 ```end()``` ![image](https://hackmd.io/_uploads/B1yfEkwgZl.png) ---- ## 新增元素 ```push_back()``` 我們可以使用 ``` push_back()```在陣列的最後新增元素 ```cpp= #include<iostream> #include<vector> using namespace std; int main(){ vector<int>a; for(int i=0;i<10;i++)a.push_back(i); //0 1 2 3 4 5 6 7 8 9 } ``` ---- ## 插入元素 ```insert()``` 我們可以使用 ```insert(iterator,value)``` 在指定位置插入元素 ```cpp= #include<iostream> #include<vector> using namespace std; int main(){ vector<int>a({0,1,2});//0 1 2 a.insert(a.begin(),3);//3 0 1 2 a.insert(a.begin()+2,4);//3 0 4 1 2 } ``` ---- ## 刪除元素 ```pop_back()``` 我們可以使用 ```pop_back()``` 刪除陣列最後方的元素 ```cpp= #include<iostream> #include<vector> using namespace std; int main(){ vector<int>a({0,1,2});//0 1 2 a.pop_back();//0 1 a.pop_back();//0 } ``` ---- ## 刪除元素 ```erase()``` 我們可以使用 ```erase(iterator)``` 刪除指定位置的元素,也可以使用 ```erase(iterator1,iterator2)``` 刪除某記憶體區間的元素 ```cpp= #include<iostream> #include<vector> using namespace std; int main(){ vector<int>a({0,1,2});//0 1 2 a.erase(a.begin());//1 2 a.erase(a.begin(),a.end());// } ``` ---- ## 刪除元素 ```clear()``` 我們可以使用 ```clear()``` 清空 ```std::vector``` 陣列 ```cpp= #include<iostream> #include<vector> using namespace std; int main(){ vector<int>a({0,1,2});//0 1 2 a.clear();// } ``` ---- ## 讀取陣列長度 ```size()``` 我們可以使用 ```size()``` 讀取陣列長度 ```cpp= #include<iostream> #include<vector> using namespace std; int main(){ vector<int>a({0,1,2}); cout<<a.size();//3 } ``` ---- ## 調整陣列長度 ```resize()``` 我們可以使用 ```resize()``` 調整陣列長度 ```cpp= #include<iostream> #include<vector> using namespace std; int main(){ vector<int>a({0,1,2}); cout<<a.size();//3 a.resize(5); cout<<a.size();//5 } ``` ---- ## 讀取陣列是否為空 ```empty()``` 我們可以使用 ```empty()``` 讀取陣列是否為空 ```cpp= #include<iostream> #include<vector> using namespace std; int main(){ vector<int>a({0,1,2}); cout<<a.empty();//0 a.clear(); cout<<a.empty();//1 } ``` ---- ## ```std::vector``` 多維陣列的宣告、定義以及引用 宣告及定義: ```cpp= std::vector<vector<...<vector<資料型別>>...>>陣列名稱(第 0 維長度,{第 1 維陣列長度,{...,{第 n-1 維陣列長度,初始值}}}); std::vector<vector<...<vector<資料型別>>...>>陣列名稱({{...{值,值,...,值},...,{值,值,...,值}}}); ``` 引用: ```cpp= 陣列名稱[第 0 維索引][第 1 維索引]...[ 第 n-1 維索引]; 陣列名稱.at(第 0 維索引).at(第 1 維索引).....at(第 n-1 維索引); 陣列名稱[第 0 維索引].at(第 1 維索引)...[第 n-2維索引].at(第 n-1 維索引) ``` ---- ## 範例 ```cpp= #include<iostream> #include<vector> using namespace std; int main(){ vector<vector<int>>a(3,{3,0}); /* 0 0 0 0 0 0 0 0 0 */ vector<vector<int>>b({ {1,2,3,4}, {5,6,7,8}, {9,10,11,12}, {13,14,15,16} }); cout<<b[0][0]<<endl;//1 cout<<b.at(1).at(1)<<endl;//6 cout<<b.at(2)[2]<<endl;//11 cout<<b[3].at(3)<<endl;//16 } ``` --- ## ```char``` 字元 ---- ## 字元是什麼 ```char``` 是 C++ 中最基本的字元型別,儲存單一字元 而這些字元的儲存會使用 ASCII 碼 ---- ## ASCII 碼 ASCII 碼是「美國資訊交換標準代碼」,是一種電腦編碼系統,用來將英文字母、數字和符號轉換成電腦能讀取的二進位代碼,以便進行資訊交換和傳輸。 ---- ## ASCII 碼對照表 ![image](https://hackmd.io/_uploads/Hy-oR53eWl.png) ---- ## 字元的運算 因為有了 ASCII 碼,我們可以對字元做簡單的運算 ```cpp= #include<iostream> using namespace std; int main(){ char a='a',b='b',c='1',d='d',e='e',f='f'; int C=c-'0'; cout<<a-b<<endl;//-1 cout<<C<<endl;//1 cout<<int(d)<<endl;//100 cout<<(e>f)<<endl;//0 } ``` ---- ## `cctype` 函式 在對字元進行操作時,有一些比較方便的函式在 `C++ <cctype>` 內: ```cpp= #include<iostream> #include<cctype> using namespace std; int main(){ char a='a'; cout<<isalpha(a)<<endl;//是否為字母 cout<<isupper(a)<<endl;//是否為大寫字母 cout<<islower(a)<<endl;//是否為小寫字母 cout<<isdigit(a)<<endl;//是否為數字 cout<<isalnum(a)<<endl;//是否為數字或字母 cout<<isspace(a)<<endl;//是否為空格 ' ' cout<<isblank(a)<<endl;//是否為空格 ' ' 或 '\t' cout<<toupper(a)<<endl;//將 a 從小寫轉換成大寫的 ASCII cout<<tolower(a)<<endl;//將 a 從大寫轉換成小寫的 ASCII } ``` --- ## C++ ```std::string``` ---- ## 為何要用 ```std::string``` ```std::string``` 是 C++ 標準函式庫 ```<string>``` 中資料結構。與 ```char []``` 不一樣的地方是,他可以自動調整大小,不需要另外去做動態分配的部分,十分的方便,一定要學起來。 ---- ## 使用 ```char []``` ```cpp= #include<iostream> using namespace std; int main(){ char a[10];//必須事先定義陣列長度 for(int i=0;i<10;i++)cin>>a[i]; cin>>a[10];//(X) } ``` 當我們需要的陣列長度大於一開始宣告的 ```char []``` 長度時,就沒辦法輸入了,如果真的硬要使用的話就會需要用到動態分配記憶體的概念 ---- ## 使用 `std::string` ```cpp= #include<iostream> #include<string> using namespace std; int main(){ string a; cin>>a; a.resize(a.size()+1); cin>>a[a.size()-1]; } ``` 當我們想要增長 ```std::string``` 時,只需要用簡單的修飾器(後面會教)就可以完成; ---- ## `std::string` 的宣告與定義 ```cpp= std::string 字串名稱 = "字串值"; std::string 字串名稱("字串值"); ``` 字串值:可以是任意數字、字母和符號 **注意** : 單一字元使用單引號 ```' '```,字串則使用 ```" "``` ---- ## 範例 ```cpp= #include<iostream> #include<string> using namespace std; int main(){ string a="Xiaochengyi"; string b="kaikai" } ``` ---- ## `std::string` 的引用 我們可以使用 ```[]operator``` 和 ```at()``` 引用 ```std::string``` 的資料,也可以直接寫字串名稱引用整個字串 ```cpp= #include<iostream> #include<string> using namespace std; int main(){ string a="Xiaochengyi"; //字串的索引(項數)是從 0 開始的 cout<<a[0]<<endl;//X cout<<a.at(1)<<endl;//i cout<<a<<endl;//Xiaochengyi } ``` --- ## C++ ```std::string``` 基礎操作 ---- ## 字串的相加 `+` 當我們想要將兩個字串串接在一起時,可以使用 `+` ```cpp= #include<iostream> #include<string> using namespace std; int main(){ string a="xiaoxiao",b="Xiaochengyi"; cout<<a+b<<endl;//xiaoxiaoXiaochengyi } ``` ---- ## 字串的相加 `append()` 除了使用 `+` 將兩個字串串接在一起,也可以使用 `append()` ```cpp= #include<iostream> #include<string> using namespace std; int main(){ string a="xiaoxiao",b="Xiaochengyi"; a.append(b); cout<<a<<endl;//xiaoxiaoXiaochengyi } ``` ---- ## 整行輸入 ```getline()``` 因為正常來說 ```std::string``` 的輸入在遇到空格後就會結束,所以我們可以使用 ```getline(輸入串流,字串名稱)``` 輸入整行的包含空格的字串 ```cpp= #include<iostream> #include<string> using namespace std; int main(){ string a; getline(cin,a);//輸入整行包含空格的字串 } ``` ---- ## 新增元素 ```push_back()``` 我們可以使用 ``` push_back()```在字串的最後新增元素 ```cpp= #include<iostream> #include<string> using namespace std; int main(){ string a; for(int i=0;i<10;i++)a.push_back(i+65); cout<<a<<endl;//ABCDEFGHIJ } ``` ---- ## 插入元素 ```insert()``` 我們可以使用 ```insert(iterator,value)``` 在指定位置插入元素 ```cpp= #include<iostream> #include<string> using namespace std; int main(){ string a="Xiaochengyi"; a.insert(4,"xiao");//Xiaocxiaohengyi } ``` ---- ## 刪除元素 ```pop_back()``` 我們可以使用 ```pop_back()``` 刪除字串最後方的元素 ```cpp= #include<iostream> #include<vector> using namespace std; int main(){ string a="Xiaochengyi";//Xiaochengyi a.pop_back();//Xiaochengy a.pop_back();//Xiaocheng } ``` ---- ## 尋找子字串 `find()` 當我們需要在字串中尋找對應的子字串,則可以使用 `find()` 尋找該子字串第一個被發現的位置 ```cpp= #include<iostream> using namespace std; int main(){ string a="Xiaochengyi"; cout<<a.find("Xiao")<<endl;// 0 cout<<a.find("xiao")<<endl;// 亂碼(找不到) } ``` ---- ## 擷取子字串 `substr()` 當我們需要把某個字串的其中一部份擷取下來時,就可以使用 `substr(位置,長度)` ```cpp= #include<iostream> #include<string> using namespace std; int main(){ string a="Xiaochengyi"; cout<<a.substr(4,7)<<endl;//chengyi } ``` ---- ## 刪除元素 ```clear()``` 我們可以使用 ```clear()``` 清空字串 ```cpp= #include<iostream> #include<string> using namespace std; int main(){ string a="Xiaochengyi";//0 1 2 a.clear();// } ``` ---- ## 讀取字串長度 ## ```size()``` 和 ```length()``` 我們可以使用 ```size()``` 和 ```length()``` 讀取字串長度 ```cpp= #include<iostream> #include<string> using namespace std; int main(){ string a="ABC"; cout<<a.size();//3 cout<<a.length();//3 } ``` ---- ## 調整字串長度 ```resize()``` 我們可以使用 ```resize()``` 調整字串長度 ```cpp= #include<iostream> #include<string> using namespace std; int main(){ string a="Xiaochengyi"; cout<<a.size();//11 a.resize(a.size()+1); cout<<a.size();//12 } ``` ---- ## 讀取字串是否為空 ```empty()``` 我們可以使用 ```empty()``` 讀取陣列是否為空 ```cpp= #include<iostream> #include<string> using namespace std; int main(){ string a="Xiaochengyi"; cout<<a.empty();//0 a.clear(); cout<<a.empty();//1 } ```