C/C++ 基礎程式設計 C++: 物件的使用 參考 重載函式 成就別人認為不可能的事 Do what nobody else considered possible. -Steve Jobs 講師 : 張傑帆 CSIE NTU
C++ 相較於 C 的特色 向下相容 在 C 語言中, 我們學了許多程式語法, 所有學過的東西, 在 C++ 中都可以使用 高階的程式描述方式 更利於用來開發大型專案, 讓程式設計師在分工時更能快速的開發程式, 並減少錯誤的產生 物件導向程式設計 讓開發程式者簡單的使用物件所提供的功能, 來達到所需要的效果
課程大綱 C++ 基礎語法 第一個 C++ 程式 : Hello World! 輸入輸出 動態記憶體配置 字串 參考 (Reference) 重載函式 (Over Loading)
C++ 的程式架構 C++ 是由 C 延伸出來的, 因此 C++ 當然包含 C 語言的所有功能, 另外提供完整物件導向程式設計 (Object-Oriented Programming:OOP) 功能 C++ 可說是 C 語言的加強版 C++ 的程式架構和 C 語言很類似, 而且程式的進入點都是由 main() 函式開始
新式標頭 C 程式中若有使用到 printf() 和 scanf() 輸出入函式時, 由於這些函式的宣告都在 stdio.h 標頭檔內, 因此必須先將此標頭檔含入到程式的最前面, 寫法如下 : #include<stdio.h>
新式標頭 C++ 逐漸取代傳統的 C 語言, 為了能向下與 C 語言相容, 標準的 ANSI/ISO C++( 簡稱標準 C++) 仍支援傳統 C 語言的標頭檔 只不過在 C++ 程式中, 若有使用到這些 C 語言所提供的標頭檔時, 我們建議使用新式標頭寫法 其做法就是在標頭檔名稱最前面加上小寫的 c 和省略副檔名 *.h 即可 例如 : #include<cstdio>
標準 C++ 為了提升功能, 引進新的 C++ 標準程式庫函式, 當然也使用新式標頭檔寫法, 以和 ANSI C 有所區別 由於新式標頭不是檔名而是一個標頭名稱, 是由識別字組成, 因此在含入新式標頭名稱時不要加上.h 副檔名 下列即是標準 C++ 所提供一些新式標頭名稱寫法 : #include<iostream> #include<string> #include<fstream> #include<list> #include<vector> #include<map>
輸入 / 出資料 標準的 C++ 程式, 則是使用 cout 和 cin 物件來輸出入資料 由於這兩個物件的宣告都定義在 C++ 標準程式庫中的 iostream 在 C++ 的程式中, 若有使用到 cin 或 cout 物件, 都必須在程式最前面先將 iostream 含入進來 寫法如下 : #include<iostream>
C++ 寫一個簡單 cout 程式, 將 Hello, 和 這是第一個 C++ 程式 兩個字串分別用 cout 逐行輸出 : Hello, 這是第一個 C++ 程式
C++ 寫一個簡單 cout 程式, 將 Hello, 和 這是第一個 C++ 程式 兩個字串分別用 cout 逐行輸出 : Hello, 這是第一個 C++ 程式
命名空間 已標準化後的 C++, 標頭檔的所有內容放在 std 命名空間中, 因此程式中使用到 cout 或 cin 時, 就必須如上面敘述在前面加上 std::, 此種寫法造成撰寫上的不方便 為解決此問題 C++ 提供 using directive 方式, 即在程式之前加上 using namespace std; 敘述把 std 完全打開, 讓 std 命名空間變得可見, 如此上面範例在程式中便可將 std:: 拿掉
C++: Helloworld 第一個 C++ 程式 :Helloworld #include <iostream> using namespace std; int main() cout << "Hello World!" << endl; return 0;
C++ 輸入輸出 cout 物件 : 輸出 << : 將一個指定的內容傳給 cout 輸出 cin 物件 : 輸入 >> : 將 cin 輸入值傳給某個儲存單位 ( 有幾個內容就用幾個 << 或 >>) #include <iostream> using namespace std; int main() int num; cin >> num; cout << num << endl; return 0;
C++ 輸入輸出 試著輸入輸出不同型態的資料 請觀察跟 printf 函式使用上的差異 #include <iostream> using namespace std; int main() int a; double b; char c; char d[80]; cout << " 請分別輸入整數, 小數, 字元, 字串 " << endl; cin >> a; cin >> b; cin >> c; cin >> d; cout << " 輸入的內容為 : " << endl; cout << a << endl; cout << b << endl; cout << c << endl; cout << d << endl; return 0;
C++ 輸入輸出 思考 : 為什麼 cin/cout 物件都不用跟告訴它我要印到螢幕的資料型態,scanf/printf 函式就要? 因為 C++ 的 cin/cout 物件比較聰明, 所以比較容易使用 在聰明的背後 ( 使用物件很容易, 自己設計物件比較困難!)
輸入含有空白字元的字串 使用 cin 物件提供的 getline 函式 ( 類似 gets 函式 ) 語法 : cin.getline( 字元陣列名稱, 最大長度 ); 輸入字串放到指定字元陣列中 若輸入字串長度超過最大長度 -1 則自動捨去 #include <iostream> using namespace std; int main() char a[80]; cin.getline(a, 80); cout << a << endl; return 0;
輸入含有空白字元的字串 使用 cin 的 >> 與 getline 會產生像在 C 語言中使用 scanf 與 gets 的問題 使用 cin 物件提供的 cin.ignore() 解決 #include <iostream> using namespace std; int main() char a[80]; char b[80]; cin >> a; cin.ignore(); cin.getline(b, 80); cout << a << endl << b << endl; return 0;
C++ 動態記憶體配置 動態記憶體配置 : new 配置一個資料空間, 並傳回該空間的位址, 語法 : 指標 = new 資料型態 ; 配置一個給定初始值的空間, 並傳回該空間的位址, 語法 : 指標 = new 資料型態 ( 初始值 ); 釋放記憶體 : delete 配置一個空間的釋放 delete 指標 ; #include <iostream> using namespace std; int main() int *ptr = new int(100); cout << " 空間位置 :" << ptr << endl; cout << " 空間儲存值 :" << *ptr << endl; *ptr = 200; cout << " 空間位置 :" << ptr << endl; cout << " 空間儲存值 :" << *ptr << endl; delete ptr; return 0;
C++ 動態記憶體配置 動態記憶體配置 : new 配置多個資料空間, 並傳回該空間的位址, 語法 : 指標 = new 資料型態 [ 個數 ]; 釋放記憶體 : delete 配置多個空間的釋放 delete [] 指標 ; #include <iostream> using namespace std; int main() int *ptr; int size, i; cout << " 請輸入個數 :"; cin >> size; ptr = new int[size]; cout << " 請輸入內容 :" << endl; for(i = 0; i < size; i++) cout << "ptr[" << i << "] = "; cin >> ptr[i]; for(i = 0; i < size; i++) cout << "ptr[" << i << "] = " << ptr[i] << endl; delete [] ptr; return 0;
進階練習 請撰寫一程式令 使用 C++ 動態記憶體配置 令使用者輸入陣列大小 ex:5 然後令使用者輸入 n 個整數後使用泡沫排序法排序 最後將結果列出 若排序已完成則須提早跳出迴圈, 以增進效能 Hint: 若排序的過程中已不會交換, 則代表排序完成
C++ 字串 : string 使用 C++ 提供的特殊字串型態 string 可以用來宣告字串物件, 方便我們做字串處理 ( 參考資料 ) 宣告語法 : string 字串物件名稱 ; 產生的字串物件提供下面語法可以使用 : [ 索引 ]: 取得索引值代表的字元 =: 字串複製 == : 字串比對 += : 字串連結 string.length(): 計算字串長度 getline(cin, str, '\n'); 可輸入含 空白 的字串 string.c_str(): 回傳字串位置 ( 常用在字串函式 )
C++ 字串 : string 範例 : 輸入字串後印出長度與所有字元 #include <iostream> #include <string> using namespace std; int main() string str; int n, i; cout << " 請輸入字串 : "; cin >> str; n = str.length(); cout << " 輸入的長度為 : " << n << endl; cout << " 輸入的字元為 : " << endl; for(i=0; i<n; i++) cout << "[" << i << "]:" << str[i] << endl; return 0;
C++ 字串 : string 範例 :string 常用之運算 字串比對 : a==b // 比對 a 與 b 是否相等 字串複製 : a = b // 將 b 複製到 a 字串連結 : a+=b // 將 b 連結到 a 後面 #include <iostream> #include <string> using namespace std; int main() string a, b; a = "Hello"; cout << " 請輸入 b 字串 : "; cin >> b; if(a==b) cout << "b 字串 a 字串相同 " << endl; else cout << "b 字串 a 字串不同 " << endl; a+=b; cout << "a,b 字串連結結果 : " << a << endl; return 0;
C++ 字串 : string 範例 : 輸入 b 字串內容後儲存 a string 字元陣列 #include <iostream> #include <string> #include <string.h> using namespace std; int main() char a[80]; string b; cout << " 輸入 string 字串 b: "; cin >> b; strcpy(a, b.c_str()); #include <iostream> #include <string> #include <string.h> using namespace std; int main() char a[80]; string b; cout << " 輸入字元陣列 a: "; cin >> a; b = a; 字元陣列 string cout << " 輸出字元陣列 a: " << a << endl; return 0; cout << " 輸出 string 字串 b: " << b << endl; return 0;
進階練習 請撰寫一程式 使用 C++ 動態記憶體配置 令使用者輸入陣列大小 ex:5 然後令使用者輸入 n 個字串後使用泡沫排序法排序 最後將結果列出 若排序已完成則須提早跳出迴圈, 以增進效能 Hint: 若排序的過程中已不會交換, 則代表排序完成
課程大綱 C++ 基礎語法 第一個 C++ 程式 : Hello World! 輸入輸出 動態記憶體配置 字串 參考 (Reference) 重載函式 (Over Loading)
C++ 參考 (Reference) 參考 (Reference) 型態代表了變數或物件的一個別名 (Alias) 參考型態可以直接取得變數或物件的位址, 並間接透過參考型態別名來操作物件 作用類似於指標, 但卻不必使用指標語法, 也就是不必使用 * 運算子來提取值 要定義參考型態, 在定義型態時於型態關鍵字後加上 & 運算子, 例如 : int var = 10; // 定義變數 int *ptr = &var; // 定義指標, 指向 var 的位址 int &ref = var; // 定義參考, 代表 var 變數
C++ 參考 (Reference) 為何參考型態一定要初始化? 因為參考初始化後就不能改變它所代表的物件, 任何指定給參考的值, 就相當於指定給原來的物件 #include <iostream> using namespace std; int main() int var = 10; int *ptr = &var; int &ref = var; cout << "var: " << var << endl; cout << "*ptr: " << *ptr << endl; cout << "ref: " << ref << endl; ref = 20; cout << "var: " << var << endl; cout << "*ptr: " << *ptr << endl; cout << "ref: " << ref << endl; return 0;
C++ 參考 (Reference) 參考型態最常使用於函式的參數列上 #include <iostream> using namespace std; void increment(int &n) n = n + 1; int main() int x = 10; increment(x); cout << x << "\n"; return 0;
練習 使用參考寫一個 MySwap 函式, 將兩個變數內容交換 ex: int a=10, b=5; MySwap(a,b); // a=5, b=10
C++ 重載函式 理解多載 (overload) 的原理 定義多個名稱相同, 但引數的型態和數量不同之函數, 就叫作函數的多載 ( 多重定義 : function overloading) 當函數進行多載時, 可以依照呼叫時所傳遞的引數, 來呼叫出適當的函數 要進行多載的函數, 其引數的型態或個數都必須不同, 否則將無法判斷要呼叫的函數, 因此也必須避免使用預設引數
C++ 重載函式 C++ 支援函式 重載 (Overload), 根據回傳值的不同或參數列個數或型態的不同, 而自動呼叫對應的函式 #include <iostream> using namespace std; void show(int x) cout << " 我有一個整數 int:" << x << endl; void show(int x, int y) cout << " 我有兩個整數 int:" << x << ", " << y << endl; int main() show(10); show(20, 30); return 0;
C++ 重載函式 根據參數的型態來決定要呼叫的函式 #include <iostream> using namespace std; void show(int x) cout << " 我是整數 int:" << x << endl; void show(double x) cout << " 我是小數 double:" << x << endl; int main() show(12); show(12.5); return 0;
練習 延續上頁範例, 新增一個函式 show 將上一章的 struct Person 型態中的姓名, 身高, 體重輸出 void show(struct Person x);
C++ 重載函式 思考 : 為什麼要使用重載函式? 宣告成不同函式名稱不好嗎? 從使用函式角度 功能一樣但參數不同的函式不用取多個名字比較好記! 物件化後的方法, 雖可用選的, 但減少選項可節省時間 可以搭配運算子重載使用 要記得所有可以傳 struct Person 結構的函式很不方便, 有沒有辦法把 struct Person 可用的函式記住呢?
延申閱讀 名稱空間 (namespace) 樣版函式 (template) 字串切割 用 strtok 函數進行字串分割 ( 字元陣列 ) find () 方法 substr() 方法 boost 庫的正規表示式實現字串分割