Download & Install
-
在開始使用C++之前須先建立工作環境,網路上有許多的編譯器與IDE介紹,在這裡使用Cold::Blocks(也可以使用Dev-C++,使用Dev-C++可同時安裝IDE與compiler,一次到位。)。
- 首先下載code::blocks
- 在安裝過程會出現選擇compiler,因為沒有compiler,所以選擇沒有,然後接下來再安裝compiler(應該可以先安裝後面介紹的compiler然後再安裝Code::Blocks,如此在安裝過程就可以直接選擇要使用的compiler。沒這樣做過,下次可以試試)。
- 此處選擇MinGW這個compiler,可以網路上查詢其他選擇。到官網下載MinGW - Minimalist GNU for Windows
- 下載完成後,點擊安裝(如下圖),因為要使用C++,所以至少要選擇如下,若需要其他程式語言可點選其他。
-
接下來在左上角點選Installation > Apply Changes,然後在跳出來的視窗內點選Apply。
-
經過一段時間的安裝後,終於完成,然後在環境變數中加上路徑(e.g. C:\MinGW\bin)。
-
完成後打開DOS視窗(使用cmd指令),在其中輸入gcc -v觀察版本,若出現版本資訊,表示安裝完成。
-
接下來在code::blocks編輯器內,打開settings>compiler
-
在Selected compiler內選取GNU GCC Compiler,若是要將此編譯器當為預設編譯器,可以點選下方的Set as default。
-
接下來選擇Toolchain executables檢查看安裝MinGW的路徑是否正確? 可使用Auto-detect來偵測或是使用旁邊的...自己來手動修正路徑。
Hello.cpp
#include <iostream> using namespace std; int main(){ cout << "Hello World" << endl; return 0; }
- 使用以下方式編譯並執行:
- 點選Build > Build,完成後選Build > Run(或是快捷列的綠色三角形)。
- 直接點選Build > Run,因為沒有Build所以會提示是否先Build,選擇是。
- 直接選Build and Run(可直接按F9)。
Basic
- 首先建立一個專案(Project),步驟如下:
- 打開code blocks,選擇開啟新project >> console application >> C++ 出現以下視窗:
- 按Next,出現一下視窗:
- 按Finish完成,選擇main.cpp,出現程式碼輸入畫面,此時可開始設計程式。
Comments
- 註解的寫法有兩種,單行註解為//,區塊註解為/**/,註解內的文字不會被編譯執行。
#include <iostream> using namespace std; int main() { /* * Here is the comments * Date: 2018/09/04 */ cout << "Hello World!" << endl; //use cout to output to screen return 0; }
Escape sequence
- 在輸出文字時,有些字元無法直接輸出,例如",因為會與字串的表示符號相混淆,因此需要使用escape sequence。
- \': '。
- \": "。
- \?: ?。
- \\: \。
- \t: Horizontal tab。
- \v: Vertical tab。
- \n: Newline。
- \a: Alert or bell。
- \b: Backspace。
- \f: Form feed。
- \r: Carriage return。
- \ooo: Octal number of one to three digits。
- \xhh...: Hexadecimal number of one or more digits。
#include <iostream> using namespace std; int main() { cout << "You are \t\"so\"\t thin.\nSo is she."; return 0; }
Variables
- 首先了解變數型態,C++包含以下基本變數: int(包含short int, long int), float, double(包含 long double), bool, void, wchar_t等。
- char: 包含char, char16_t, char32_t, wchar_t。
- int: 包含int, short int, long int, long long int。
- real number: 包含float, double, long double。
- bool: 僅有兩個值true of false。
- void。
- auto: 表示該變數的形態由所給予的值來決定。
- 其中char與int(包含short int, long int可以使用unsigned與signed關鍵字修飾。
- 每個變數佔的記憶體容量不同,可以使用sizeof()函數來顯示。
CppApp1 >> main.cpp
#include <iostream> using namespace std; int main() { cout << "char 的大小: " << sizeof(char) << endl; cout << "unsigned char 的大小: " << sizeof(unsigned char) << endl; cout << "signed char 的大小: " << sizeof(signed char) << endl; cout << "char16_t 的大小: " << sizeof(char16_t) << endl; cout << "char32_t 的大小: " << sizeof(char32_t) << endl; cout << "wchar_t 的大小: " << sizeof(wchar_t) << endl; cout << "int 的大小: " << sizeof(int) << endl; cout << "signed int 的大小: " << sizeof(signed int) << endl; cout << "unsigned int 的大小: " << sizeof(unsigned int) << endl; cout << "short int 的大小: " << sizeof(short int) << endl; cout << "signed short int 的大小: " << sizeof(signed short int) << endl; cout << "unsigned short int 的大小: " << sizeof(unsigned short int) << endl; cout << "long int 的大小: " << sizeof(long int) << endl; cout << "signed long int 的大小: " << sizeof(signed long int) << endl; cout << "unsigned long int 的大小: " << sizeof(unsigned long int) << endl; cout << "long long int 的大小: " << sizeof(long long int) << endl; cout << "signed long long int 的大小: " << sizeof(signed long long int) << endl; cout << "unsigned long long int 的大小: " << sizeof(unsigned long long int) << endl; cout << "float 的大小: " << sizeof(float) << endl; cout << "double 的大小: " << sizeof(double) << endl; cout << "long double 的大小: " << sizeof(long double) << endl; cout << "bool 的大小: " << sizeof(bool) << endl; cout << "void 的大小: " << sizeof(void) << endl; return 0; }
- 單位為byte。
- 字串(string)不屬於primitive variable,是多個char的組合。
#include <iostream> using namespace std; int main() { int age = 18; // declare a int variable named age cout << "I am " << age << " years old." << endl; return 0; }
- 建立變數需先宣告變數型態(int),空一格給變數名,用等號(也可以使用小括號int age(18);或大括號:int age{18};)將右方的值指派給該變數並儲存在記憶體內。可以不給初值,此時變數值未決定。
- 變數與字串需分開顯示。
- 幫變數取名時的規則與慣例:
- 使用英文字母(大小寫有分別)、數字與底線(_),數字不可在前,中間不包含空白(space or tab)
- 使用有意義的字或組合字(e.g. myHeight)。
- 不可使用關鍵字,關鍵字可參考此網頁。
- 若要宣告常數(通常命名為全大寫),可使用關鍵字const或使用#define。
#include <iostream> using namespace std; //#define PI 3.14159 int main() { const double PI = 3.14159; double radius = 10; cout << "Circle Area = " << PI*radius*radius << endl; return 0; }
- 請注意若使用#define PI 3.14159,其後沒有分號。
Operators
- 運算子用來連結運算元並運算。
- Assignment operator (=): 等號的意思是指派,也就是說將右方的值指派給左方的變數,例如x=1;。
- Arithmetic operators ( +, -, *, /, % ): 分別為加減乘除與計算餘數。
#include <iostream> using namespace std; int main() { int x = 1; x = x + 2; cout << "x = " << x << endl; return 0; }
- x = x + 1;的意思是先計算等號右方的x+2(3),然後再將值指派給左方的變數x。
#include <iostream> using namespace std; int main() { int x = 1; x += 2; cout << "x = " << x << endl; return 0; }
- x += 2;原則上就是x = x + 2;。其餘依此類推。
- >>=, <<=: 使用2進位,左移或右移幾位。e.g. x <<= 2;表示x值用2進位表示然後左移2位,也就是x的值乘以4。
- &=, ^=, |=: 邏輯判斷,後面介紹。
#include <iostream> using namespace std; int main() { int x = 1; int y = x++; int z = ++x; cout<<y<<"\t"<<z<<endl; }
- x++或++x原則上都等於x = x + 1 (或x+=1)。
- 上例中輸出結果y=1, z=3,原因是x++是先將x的值指派給y,然後再++,而++x則是先++,然後再指派給z。
- 請注意==用來判斷兩數是否相等,與=(指派)意義完全不同。
#include <iostream> using namespace std; int main() { int x = 1; int y = x++; int z = ++x; bool b1 = (y>x) && (z<x); // 0 bool b2 = (y>x) || (!(z<x)); // 1 cout<<b1<<"\t"<<b2<<endl; }
- 傳回0表示false,傳回1表示true。
- &:且。若2進位法表示中,同位置兩者皆為1(true),則傳回true,否則傳回false(0)。e.g. 010(2)&011(3) >> 010(2)。
- |:或。若2進位法表示中,同位置兩者任一為1(true),則傳回true,否則傳回false(0)。e.g. 010(2)&011(3) >> 011(3)。
- ^:XOR。若2進位法表示中,同位置兩者有一為1(true),另一為0,則傳回true,否則傳回false(0)。e.g. 010(2)&011(3) >> 001(1)。
- ~:否。若2進位法表示中,將某數的0變為1,1變為0。e.g. ~011(3) >> 100(-4)。
- <<,>>: 2進位法表示中左右移動,如前所述。
#include <iostream> using namespace std; int main() { int x = 2; int y = 3; cout<<(float)y/x << endl; }
- 先將int y cast成為float再除以x,結果為1.5,若沒有先cast,傳回整數,結果為1。
1 | Scope | :: |
2 | Postfix | |
++ -- | ||
() | [] | |
. -> | ||
3 | Prefix | |
++ -- | ||
~ ! | ||
+ - | ||
& * | ||
new delete | ||
sizeof | ||
(type) | ||
4 | Pointer-to-member | .* ->* |
5 | Arithmetic: scaling | * / % |
6 | Arithmetic: addition | + - |
7 | Bitwise shift | << >> |
8 | Relational | < > <= >= |
9 | Equality | == != |
10 | And | & |
11 | Exclusive or | ^ |
12 | Inclusive or | | |
13 | Conjunction | && |
14 | Disjunction | || |
15 | Assignment-level expressions | |
= *= /= %= += -= >>= <<= &= ^= |= | ||
?: | ||
16 | Sequencing | , |
Basic Input & Output
- 此處介紹簡單的輸出入(在console輸出入)。
- 已經知道輸出為cout,而輸入則使用cin。
#include <iostream> using namespace std; int main() { int age; string name; cout << "How old are you?" << endl; cin >> age; cout << "You are " << age << " years old." << endl; cout << "What is your name?" << endl; cin >> name; cout << "Hi, there, " << name << endl; }
- 使用cin來取得數值並儲存於變數age中,以供後續使用。
- 使用cin一樣可以取得字串,但是若輸入的字串中有空白(e.g. Tom Smith),只會取得第一個字,所以若欲取得整個句子(至輸入Enter止),可納入字串資料庫(#include
),然後使用getline()方法。
#include <iostream> #include <string> using namespace std; int main() { string age; string name; cout << "How old are you?" << endl; getline(cin, age); cout << "You are " << age << " years old." << endl; cout << "What is your name?" << endl; getline(cin, name); cout << "Hi, there, " << name << endl; }
#include <iostream> #include <string> #include <sstream> using namespace std; int main() { string str; int age; string name; cout << "How old are you?" << endl; getline(cin, str); stringstream(str) >> age; cout << "You are " << age << " years old." << endl; cout << "What is your name?" << endl; getline(cin, name); cout << "Hi, there, " << name << endl; }
Flow Control
- Flow Control是用來控制程式執行的順序。原則上可分為if...else, switch, loop(while & for)等等,以下會逐一介紹。
if...else
- if...else用來判斷部分程式碼是否要執行,輸入參數為bool。
#include <iostream> using namespace std; int main() { int x = 10; if(x > 1){ cout << "x > 1" <<endl; } return 0; }
#include <iostream> using namespace std; int main() { int x = 0; if(x > 1){ cout << "x > 1" << endl; }else{ cout << "x <= 1" << endl; } return 0; }
#include <iostream> using namespace std; int main() { double weight; double height; cout << "Please input your weight(kg)" << endl; cin >> weight; cout << "Please input your height(m)" << endl; cin >> height; double bmi = weight/height/height; if(bmi < 18.5){ cout << "Your bmi = " << bmi << "\nYou are too thin." << endl; }else if(bmi >= 18.5 && bmi <23.9){ cout << "Your bmi = " << bmi << "\nYou are in good shape." << endl; }else if(bmi >= 23.9 && bmi <27.9){ cout << "Your bmi = " << bmi << "\nYou are over-weighted." << endl; }else{ cout << "Your bmi = " << bmi << "\nYou are obese." << endl; } return 0; }
- 若是程式碼很短的判斷,可以使用?符號,e.g.
#include <iostream> using namespace std; int main() { int number; string s; cout << "Please input a number:" << endl; cin >> number; s = (number > 10)? ">10":"<10"; cout << s << endl; }
switch
- switch類似if...else,也是用來判斷部分程式碼是否要執行。
#include <iostream> using namespace std; int main() { int choice; cout << "Please input your choice(1-3)" << endl; cin >> choice; switch(choice){ case 1: cout << "You chose 1" << endl; break; case 2: cout << "You chose 2" << endl; break; case 3: cout << "You chose 3" << endl; break; default: cout << "You chose other numbers(" << choice << ")" << endl; } // switch return 0; }
while loop
- while loop使用關鍵字while,其意義就是讓部分程式碼在輸入參數為true的情況下重複執行。
#include <iostream> using namespace std; int main() { int number; cout << "Please input a positive integer..." << endl; cin >> number; int sum = 0; int index = 1; while(index <= number){ sum = sum + index; index++; } cout << "The sum of 1+2+...+" << number << " = " << sum << endl; return 0; }
#include <iostream> using namespace std; int main() { int snumber; int bnumber; cout << "Please input a smaller positive integer..." << endl; cin >> snumber; cout << "Please input a bigger positive integer..." << endl; cin >> bnumber; int sum = 0; int index = snumber; do{ if(snumber < 0 || bnumber < 0 || snumber > bnumber){ cout << "The numbers you inputed are invalid, please try again." << endl; break; } sum = sum + index; index++; }while(index <= bnumber); // 此處須有分號 cout << "The sum of " << snumber << " + ... + " << bnumber << " = " << sum << endl; return 0; }
- 需注意在do-while之後必須加上分號。
for loop
- for loop的作用與while loop相同,只是for loop將上述的三要件直接定義在輸入引數內。
#include <iostream> using namespace std; int main() { int snumber; int bnumber; cout << "Please input a smaller positive integer..." << endl; cin >> snumber; cout << "Please input a bigger positive integer..." << endl; cin >> bnumber; int sum = 0; for(int i = snumber; i <= bnumber; i++){ sum = sum + i; } cout << "The sum of " << snumber << " + ... + " << bnumber << " = " << sum << endl; return 0; }
#include <iostream> using namespace std; int main() { int snumber; int bnumber; cout << "Please input a smaller positive integer..." << endl; cin >> snumber; cout << "Please input a bigger positive integer..." << endl; cin >> bnumber; for(int i = snumber, j = bnumber; i < j; i++, j--){ cout << i << "\t" << j << "\t" << i+j << endl; } return 0; }
- 粗略的說,for loop用在執行次數已知的情況,而while loop可用在執行次數未知的情況。。
break, continue, goto
- break, continue, goto這三個關鍵字可以控制程式的執行流程,break在之前提過,若在loop內,則是終止loop,而continue則是跳回loop開始處,goto則是跳到程式的某一位置。
#include <iostream> using namespace std; int main() { int number; cout << "Please input a positive integer: " << endl; cin >> number; int sum = 0; for(int i = 0; i < number; i++) { if(i == 100) break; else if(i%2 == 0) continue; else sum = sum + i; } cout << "sum = " << sum << endl; return 0; }
#include <iostream> using namespace std; int main() { int number; label_a: cout << "Please input a positive integer: " << endl; cin >> number; if(number > 100){ cout << "Number has to be less than 100, please try again." << endl; goto label_a; }//if int sum = 0; for(int i = 0; i < number; i++) { if(i == 100) break; else if(i%2 == 0) continue; else sum = sum + i; }//for cout << "sum = " << sum << endl; return 0; }
- goto label會跳回到label處繼續執行。。
function
- function是一段獨立的程式碼,當被呼叫(call)時執行,其好處是可將程式碼分為小片段,易於偵錯,且可重複使用。
- 以下為一個最簡單的函數,void表示沒有傳回值。在另一個函數(main)中呼叫f1(),便會執行f1()的程式內容。請注意main必須傳回int,不能使用void。
#include <iostream> using namespace std; void f1(){ cout << "Execute Function 1" << endl; } int main() { f1(); return 0; }
- 函數必須置於main()之前。。
#include <iostream> using namespace std; void f1(){ cout << "Execute Function 1" << endl; } double square(double x){ return x*x; } int main() { f1(); double d; cout << "Please input a number:" << endl; cin >> d; cout << "The square of " << d << " is " << square(d) << endl; return 0; }
- 命名函數時也要遵循之前的命名規則,最好是有意義的字。。
#include <iostream> using namespace std; int addition(int a, int b = 2){ return a+b; } int main() { int a, b; cout << "Please input a number:" << endl; cin >> a; cout << "Please input another number:" << endl; cin >> b; cout << "The addition of " << a << " and " << b << " are " << addition(a,b) << endl; return 0; }
- 在函數addition的argument內,b=2的意思是b的初始值為2,也就是說可以這個形式呼叫函數addition(a),此時b=2。
- 須注意有初始值的變數需置於沒有初始值的變數之後,也就是說(int a = 2, int b)是不行的,原因是因為若是我們呼叫addition(10),程式無法判斷10是要指派給a還是b。
#include <iostream> using namespace std; int addition(int& a, int& b){ a = a*a; b = b*b; return a+b; } int main() { int a, b; cout << "Please input a number:" << endl; cin >> a; cout << "Please input another number:" << endl; cin >> b; cout << "a = " << a << "\tb = " << b << endl; cout << "The addition of " << a << " and " << b << " are " << addition(a,b) << endl; cout << "NOW a = " << a << "\tb = " << b << endl; return 0; }
- 此例中兩個函數間的a,b指的是同樣的變數,之前的例子中兩個函數間的a,b為不同變數,只是值相同。。
#include <iostream> using namespace std; string fullName(const string& a, const string& b){ return a+" "+b; } int main() { string firstname, surname; cout << "Please input your first name:" << endl; cin >> firstname; cout << "Please input your surname:" << endl; cin >> surname; cout << "Hi, " << fullName(firstname,surname) << endl; cout << "NOW firstname = " << firstname << "\tsurname = " << surname << endl; return 0; }
- 此例中在函數fullNmae內,不可修改a,b的值。。
#include <iostream> using namespace std; int addition(int a, int b); int main() { int a, b; cout << "Please input a number:" << endl; cin >> a; cout << "Please input another number:" << endl; cin >> b; cout << "The addition of " << a << " and " << b << " are " << addition(a, b) << endl; return 0; } int addition(int a, int b){ return a+b; }
#include <iostream> using namespace std; /* * Fibonacci sequence: 0, 1, 1, 2, 3, 5, 8, ... * The index of first number(0) is 0, second number is 1...... */ int fibonacci(int n){ if(n==0) return 0; else if(n==1) return 1; else return fibonacci(n-1)+fibonacci(n-2); } int main() { int a; cout << "Please input a number:" << endl; cin >> a; cout << "The " << a << "-th number of Fibonacci sequence is " << fibonacci(a) << endl; for(int i = 0; i <= a; i++){ cout << fibonacci(i) << endl; } return 0; }
#include <iostream> using namespace std; int minimum(int& a, int& b){ if (a <= b) return a; else return b; } int minimum(int& a, int& b, int& c){ if(c < minimum(a,b)) return c; else return minimum(a,b); } int main() { int a, b, c; cout << "Please input a number:" << endl; cin >> a; cout << "Please input another number:" << endl; cin >> b; cout << "Please input another number:" << endl; cin >> c; cout << "The minimum of a,b is " << minimum(a,b) << endl; cout << "The minimum of a,b,c is " << minimum(a,b,c) << endl; return 0; }
#include <iostream> using namespace std; template <class T> T sum (T a, T b){ T result = a+b; return result; } int main() { cout << sum<int>(5,6) << "\t" << sum<double>(5.5, 6.6) << endl; return 0; }
- 這樣設計時,無論要輸出int或double皆可,不需要設計兩個函數。。
- 使用時用sum
(5,6),其實這個情況 。可以省略。不過若是沒寫型態,使用sum(5,6.1)便會出現錯誤,此時需用sum (5,6.1)
#include <iostream> using namespace std; int m = 10; // global variable namespace ns1{ int m = 20; // variable in ns1 } namespace ns2{ double k = 10.555; // variable in ns2 } template <class T> T multi_1(T m){ T result = m*ns1::m; return result; } template <class T> T multi_2(T a){ T result = a*m; return result; } int main() { int m = 5; // local variable cout << multi_1(m) << "\t" << multi_2(m) << "\t" << multi_2(ns1::m) << endl; using namespace ns2;//using ns2::k; cout << multi_1(k) << "\t" << multi_2(k) << endl; return 0; }
- 上例中,最上方的m是golbal variable,整個程式內皆可使用。main()內定義的m為local variable,僅在main()內使用,但在main()內使用的m指的是local variable。
- namespace是一個命名空間,欲使用需用using namespace ns2或專指其中單一變數,e.g. ns2::k。
Array & Class
- Array是用來儲存一組相同型態的資料,Class用來描述物件,包含相關的資料(可以不同型態)與相關方法。
Array
- 宣告Array時須先指名儲存資料的型態,可以給初值。
#include <iostream> using namespace std; int main() { int arr1[5]; int arr2[] = {1,2,3,4,5}; // int arr2[]{1,2,3,4,5} cout << "arr1[0] = " << arr1[0] << endl; arr1[0] = 10; cout << "arr1[0] = " << arr1[0] << endl; cout << "arr2[0] = " << arr2[0] << endl; arr2[0] = 100; cout << "arr2[0] = " << arr2[0] << endl; return 0; }
#include <iostream> #include <time.h> using namespace std; void printArray(int a[], int len){ for(int i = 0; i < len; i++) { cout << a[i] << endl; }//for } int main() { int arr1[5]; int arr2[]{1,2,3,4,5}; srand(time(NULL)); for (int i = 0; i < sizeof(arr1)/sizeof(arr1[0]); i++) { arr1[i] = rand()%101; } printArray(arr1, 5); cout << "RAND_MAX = " << RAND_MAX << endl; printArray(arr2, 5); return 0; }
- sizeof(arr1)/sizeof(arr1[0]) or sizeof(arr1)/sizeof(int)可以計算array長度。
- arr1內的值為亂數,產生隨機數的方式是rand(),會產生0到RAND_MAX之間的整數。
- 亂數需要給seed才會有不同亂數序列,所以使用srand(seed)函數。
- 為了讓每次產生都不同,seed使用時間(time(NULL)),因此要加入時間的標頭檔#include
,若是要固定產生的亂數序列,只需將seed設為定數即可,e.g. srand(1) 。
#include <iostream> #include <time.h> using namespace std; int main() { int arr[5]; srand(time(NULL)); for(int i = 0; i < 5; i++){ arr[i] = rand()%100; }//for for(int elem:arr) cout << elem << endl; return 0; }
#include <iostream> #include <time.h> using namespace std; void print2DArray(int a[3][5], int rows, int cols){ for(int i = 0; i < rows; i++) { for(int j = 0; j < cols; j++){ cout << "[" << i << "][" << j << "] = " << a[i][j] << endl; }//for cout << "\n"; }//for } int main() { int marr[3][5]; srand(time(NULL)); for(int i = 0; i < 3; i++){ for(int j = 0; j < 5; j++){ marr[i][j] = rand()%100; }//for }//for print2DArray(marr, 3, 5); return 0; }
- 在將多維陣列當作參數傳送時,需要給各維度的長度,所以給a[3][5],第一個可以空白,也就是說a[][5]也可以。
- 若是三維陣列的參數,須至少給後面兩個維度長度,e.g. a[][3][5]。
#include <iostream> using namespace std; int main() { string s = "Hello";// string s = {"Hello"};string s {"Hello"}; for (char elem : s) cout << elem << '\n'; cout << endl; for(int i = 0; i < 5; i++) cout << s[i] << endl; return 0; }
- string s = "Hello"; string s = {"Hello"};string s {"Hello"};三種宣告方式都可以。
Class
- Class是物件的類別,類別內包含相關參數,建構子與對應方法。
- C++的class設計有幾個地方可以有變化,以下為一個圓的class。
#include <iostream> #include <cmath> using namespace std; class Circle{ double radius; // variable public: Circle(double r){radius = r;}; // constructor double area(){ // method return radius*radius*M_PI; }; }; int main() { Circle c1 = 10; // instance Circle c2 = 100; cout << c1.area() << "\t" << c2.area() << endl; return 0; }
- 通常命名class,第一個字母大寫。
- 設計圓的參數,主要為半徑。
- public下的第一個函數為建構子(constructor),是用來建構物件使用(在此須與class同名),可在此初始化參數,之後的area為圓的方法,用來求圓面積。
- 在主程式中利用建構子建構圓的物件,可建立任意數量的物件,此時可以使用圓的方法來求得面積,因為計算圓面積需要使用PI,所以include資料庫cmath(#include
),然後直接使用M_PI即可 。
#include <iostream> #include <cmath> using namespace std; class Circle{ double radius; // variable public: Circle(double); // Only need to specify the data type double area(){ // method return radius*radius*M_PI; }; }; Circle :: Circle(double r){radius = r;} // Complete the constructor here int main() { Circle c1 = 10; // instance Circle c2 = 100; cout << c1.area() << "\t" << c2.area() << endl; return 0; }
- 此處的建構子僅設計欲傳入之型態,參數的初始在之後完成。
#include <iostream> #include <cmath> using namespace std; class Circle{ double radius; // variable public: Circle(); // first constructor Circle(double); // second constructor double area(){ // method return radius*radius*M_PI; }; }; Circle :: Circle(){radius = 10;} // Complete the first constructor Circle :: Circle(double r){radius = r;} // Complete the second constructor int main() { Circle c1; // instance using the first constructor Circle c2 = 100; // instance using the second constructor cout << c1.area() << "\t" << c2.area() << endl; return 0; }
- 此處設計兩個建構子,分別包含0跟1個參數。
#include <iostream> #include <cmath> using namespace std; class Circle{ double radius; // variable public: void set_radius(double); double area(){ // method return radius*radius*M_PI; }; }; void Circle::set_radius(double r){ radius = r; } int main() { Circle c1; // instance using the first constructor Circle c2; // instance using the second constructor c1.set_radius(10); c2.set_radius(100); cout << c1.area() << "\t" << c2.area() << endl; return 0; }
- 原則上set_radius()函數可以直接在class內完成 >> void set_radius(double r){radius = r;};。
- 在main()之內宣告物件,然後使用set_radius()方法來完成初始。
- 請注意class中的參數預設為private,所以無法從class外直接取得其值。
#include <iostream> #include <cmath> using namespace std; class Circle{ double radius; // variable public: Circle(double); // constructor double area(){ // method return radius*radius*M_PI; }; }; Circle::Circle(double r){ radius = r; } int main() { Circle c1 = 10; // Circle c2(100); // Circle c3 = {1000}; // Circle c4{10000}; // cout << c1.area() << "\t" << c2.area() << "\t" << c3.area() << "\t" << c4.area() << endl; return 0; }
#include <iostream> using namespace std; class Vec{ int x,y; public: Vec(){}; // constructor Vec(int a, int b){ // constructor x=a;y=b; } Vec operator+ (Vec &anotherVec){ // function that returns a Vec Vec temp; temp.setX(x + anotherVec.getX()); temp.setY(y + anotherVec.getY()); return temp; } bool operator == (Vec &anotherVec); int getX(){ return x; } void setX(int xx){ x = xx; } int getY(){ return y; } void setY(int yy){ y = yy; } }; bool Vec::operator== (Vec &anotherVec){ if(x == anotherVec.getX() && y == anotherVec.getY()){ return true; }else return false; } int main(){ Vec v1 {1,2}; Vec v2 (3,4); Vec v3; Vec v4; v3 = v1 + v2; v4 = v1.operator+ (v2); cout << v3.getX() << ", " << v3.getY() << endl; cout << v1.operator+ (v2).getX() << ", " << v4.getY() << endl; cout << (v3==v4) << endl; return 0; }
- class Vec有兩個變數x,y。若想要從外部使用VecObj.x與VecObj.y取得x,y,可將x,y置於public:後面一行。。
- 通常為了安全性,x,y還是使用private修飾較好,取得與改變x,y的值使用getters與setters方法。
- Vec operator+ (Vec &anotherVec)是一個函數,重載+號的定義,當使用+號連結兩個Vec物件時的計算方式(x1+x2, y1+y2),此函數傳入另一個Vec(&anotherVec),傳回一個Vec(temp)。
- v1 + v2;與v1.operator+ (v2);兩者都可使用,效果相同。
- bool operator == (Vec &anotherVec);定義當使用==符號時的計算方式,在此只要兩個物件的x與y對應相等即視為相等,傳回true(or 1)。
- 可以被重載的符號包括:+ - * / = < > += -= *= /= << >> <<= >>= == != <= >= ++ -- % & ^ ! | ~ &= ^= |= && || %= [] () , ->* -> new delete new[] delete[]。
#include <iostream> using namespace std; class Vec{ int x,y; public: Vec(){}; // constructor Vec(int x, int y){ // constructor this->x=x;this->y=y; } Vec operator+ (Vec &anotherVec){ // function that returns a Vec this->setX(x + anotherVec.getX()); this->setY(y + anotherVec.getY()); return *this; } int getX(){ return x; } void setX(int xx){ x = xx; } int getY(){ return y; } void setY(int yy){ y = yy; } }; int main(){ Vec v1 {1,2}; Vec v2 (3,4); v1 + v2; cout << v1.getX() << ", " << v1.getY() << endl; cout << v2.getX() << ", " << v2.getY() << endl; return 0; }
- 此例稍微修改之前的例子。this->x=x;等號右邊的x為constructor內的local variable,而this->x則表示此物件Vec內的參數,因為this就是該物件。
- 在設計+號的方法內,傳回*this,因為this是該物件的pointer,所以*this為此物件的值。。
- 在使用的時候,v1+v2操作後因為傳回*this,所以改變的是v1的值。與之前例子不同,之前的例子是傳回另一個物件。
#include <iostream> using namespace std; class Aclass{ public: static int total; int w = 5; Aclass(){ total++; }; // constructor static int add(int x, int y){ return x+y; // return x+y+w; is forbidden. } }; int Aclass::total=0; int main(){ Aclass a1; cout << a1.total << endl; Aclass *a2 = new Aclass[5]; delete a2; cout << Aclass::total << endl; cout << Aclass::add(3,6) << endl; return 0; }
- 被static修飾的變數,不能在class內初始化,必須在class外初始。
- 因為是公用的變數,所以可以直接用class name來取得它,所以可使用Aclass::total;(相當於a1.total)。
- add()函數因為被static修飾,所以可以直接用Aclass::add(3,6)來取得。但是因為該函數為static,所以無法使用其他非static變數或函數(例如使用w,但是若是x+y+total則可以)。此外,也不能使用this指標。
#include <iostream> using namespace std; class Aclass{ public: int w; int v; Aclass(int w, int v){ this->w = w; this->v = v; }; // constructor int add(int x, int y){ return x+y; } int getw() const {return w;} const int getv() {return v;} const int get() const { return w+v; } }; int main(){ const Aclass a1(5,10); cout << a1.getw() << "\t" << a1.w << "\t" << a1.v << endl; // cout << a1.add(2,3) << endl; => is illegal... // cout << a1.getv() << endl; => is illegal... // a1.w = 50; => is illegal... const int k = a1.get(); cout << k << endl; Aclass a2(20,30); a2.w = 50; cout << a2.getw() << "\t" << a2.w << "\t" << a2.getv() << "\t" << a2.v << endl; cout << a2.add(2,3) << endl; const int kk = a2.get(); cout << kk << endl; return 0; }
- 當宣告物件為const時,該物件只能使用class內的const函數,若不是const物件,則都可以使用。
- int getw() const表示是const函數。
- const int getv()表示傳回值是const。
- const int get() const表示是const函數且傳回值是const。
#include <iostream> using namespace std; template <class T> class Aclass{ T values [2]; public: Aclass(T one, T two){ values[0] = one; values[1] = two; } T add(){ return values[0]+values[1]; } T bigger(); }; template <class T> T Aclass<T>::bigger(){ T big = values[0] > values[1]? values[0]: values[1]; return big; } template <> class Aclass<string> { string values [2]; public: Aclass(string one, string two){ values[0] = one; values[1] = two; } string concatenate(){ string s = values[0]+values[1]; return s; } }; int main(){ Aclass<int> a(1,2); cout << a.add() << endl; cout << a.bigger() << endl; Aclass<double> b(2.5,2.6); cout << b.add() << endl; cout << b.bigger() << endl; Aclass<string> c("abc","xyz"); //cout << c.bigger() << endl; => no such a function defined. cout << c.concatenate() << endl; return 0; }
- 當要在class之外完成函數bigger()時,在之前必須再次寫template
。 - template <> class Aclass
與之前不同之處是根據原來的版針對某一類型物件設計class,相關函數需重新設計 。
#include <iostream> #include <cmath> using namespace std; class Circle{ double radius; public: Circle(){} Circle(double r){radius = r;} double area(){return M_PI*radius*radius;} friend Circle circlefriend(const Circle&); }; Circle circlefriend(const Circle& cir){ Circle c; c.radius = cir.radius; return c; } int main(){ Circle c1; Circle c2(20); c1 = circlefriend(c2); cout << c1.area() << endl; return 0; }
- friend Circle circlefriend(const Circle&);此指令使函數circlefriend成為class Circle的friend,所以可在其內取得Circle物件的private variable。
#include <iostream> #include <cmath> using namespace std; class Circle; class Ellipse{ double a, b; public: Ellipse(){} Ellipse(double a, double b){ this->a=a;this->b=b; } double area(){ return M_PI*a*b; } void convert (Circle c); }; class Circle{ friend class Ellipse; double radius; public: Circle(double r){radius = r;} }; void Ellipse::convert(Circle c){ a = c.radius; b = c.radius; } int main(){ Ellipse e; Circle c(10); e.convert(c); cout << e.area() << endl; return 0; }
- 因為Ellipse內的convert()需要傳入Circle,所以在Ellipse之前宣告class Circle;。
- 在Ellipse內的convert()參數為Circle,但因為Circle尚未定義完成,所以此函數在Circle之後再完成。
- 在Circle內聲明其為friend of Ellipse,所以在convert()函數內,可以取得Circle內的參數radius。
#include <iostream> using namespace std; class Animal{ public: string name; Animal(){name="no name";} Animal (string name){ this->name=name; } }; class Dog: public Animal{ public: Dog(string name){} string sound(){ return name + ": woof woof"; } }; class Cat: public Animal{ public: Cat(string name):Animal (name){ cout << "Cats inherited animal..." << endl; } string sound(){ return name + ": meow meow"; } }; int main(){ Dog d ("Lucky"); Cat c ("Kitten"); cout << d.sound() << endl << c.sound() << endl; return 0; }
- 欲繼承class Animal,須在classname之後加上: public Animal,除了constructors, destructor, assignment operator memebers(operator=), friends, private members,其餘在class內的成員都會被繼承。
- 欲繼承Animal的constructor,需在constructor之後加上Animal(name){},如果沒有加上Animal(name){}來繼承constructor,則會使用default constructor。
#include <iostream> #include <cmath> using namespace std; class Circle{ public: double radius; Circle(){} Circle (double r){ this->radius=r; } double area(){ return M_PI*radius*radius; } }; class Color{ public: string color; Color(){} Color(string c){ this->color=c; } }; class ColoredCircle: public Circle, public Color{ public: ColoredCircle(double r, string c):Circle (r), Color(c){ } string toString(){ double d = area(); string area = to_string(d); string s = color + " Circle with area = " + area; return s; } }; int main(){ ColoredCircle cc(10.0, "blue"); cout << cc.toString() << endl; return 0; }
- 將要繼承的class用逗號分開即可多重繼承,在constructor處亦然。
- to_string(d)用來將數字轉換為字串,方便之後字串相加。
Pointers
- 在C++中,電腦的記憶體就像一個個的區塊(byte),每個區塊有固定的位址(address),程式可以直接操控一塊記憶體( memory cells with consecutive addresses >> 可以超過1 byte)。
Address-of operator (&)
- 每個變數接儲存在電腦的某一塊記憶體內,該記憶體有特定位址。
- 將&加在某變數名稱,變成表示該變數的位址,否則只表示該變數的值。e.g.
#include <iostream> using namespace std; int main() { int a = 10; int &add_a = a; int val = a; cout << "a = " << a << "\tval = " << val << endl; cout << "Address of a = " << &add_a << "\tValue contained in &add_a = " << add_a << endl; add_a = 20; val = 100; cout << "a = " << a << "\tval = " << val << endl; cout << "Address of a = " << &add_a << "\tValue contained in &add_a = " << add_a << endl; return 0; }
- 此例中&add_a表示變數a在記憶體的位址,而add_a則表示該位址所儲存的值(也就是a),當add_a被改變時,a也隨之改變(反之亦然),因為是指的同一塊記憶體。
- 而val=a;則表示val得到a的值的copy,但是val與a分別儲存在兩塊不同的記憶體。
- 在取得某變數的reference時,兩者必須有相同的type(e.g. 皆為int),若有const修飾,則兩者皆須有const修飾(e.g. const int a = 10; const int &add_a = a;)。
- 可以refer to常數,但是必須使用const修飾,e.g. const int &add_a1 = 50;。
Dereference operator (*)
- 儲存某一變數(或物件)的位址的變數稱為pointer。
- 將*加在某變數之前,表示該變數為pointer,指向被指派的變數。e.g.
#include <iostream> using namespace std; int main() { int x = 10; int *y = &x; cout << "x = " << x << "\ty = " << y << "\t*y = " << *y <<endl; return 0; }
- 變數y儲存變數x的位址,在宣告pointer時,還是使用要指向的資料的資料型態(除非是void)。
- *y則表示該位址的值,因為去除了指位來取得值,因此稱為dereference,所以*&x指的便是x。
#include <iostream> using namespace std; int main() { int x[5] = {1,2,3,4,5}; int *y; y = x; // *y = x[0] *y = 10; y = &x[1]; // *y = x[1] *y = 20; y = x + 2; // *y = x[2] *y = 30; y = &x[0]; // equivalent to y = x *(y+3) = 40; // *(y+3) = x[3] *(x+4) = 50; for(int i = 0; i < 5; i++) cout << x[i] << " "; return 0; }
- int *y宣告y是pointer變數,而y=x則為y=&x[0]的簡寫。
- pointer y可以指向其他位址,例如y = &x[1];此時y指向&x[1]。
- y = x + 2;表示自x[0]平移兩位,所以是指向x[2]。
- *(y+3)表示自原指位位址平移三位。
- 由上可知pointer可使用+號來表示往後移動多少塊記憶體(以快為單位,實際長度是資料型態而定)。所以可以如下印出array內容(若使用*y++表示指標往後指一位)。
#include <iostream> using namespace std; int main() { int x[5] = {1,2,3,4,5}; int *y; y = x; for(int i = 0; i < 5; i++) cout << *y+i << " "; // cout << *y++ << " "; return 0; }
#include <iostream> using namespace std; int main() { char s[]="Hello!"; char *y = s; for(int i = 0; i < 6; i++){ cout << *y++ << endl; } return 0; }
#include <iostream> using namespace std; int main() { int x = 10; int *y = &x; int **z = &y; cout << x << "\t" << y << "\t" << z << endl; cout << *y << "\t" << *z << "\t" << **z << endl; return 0; }
- z所儲存的是y的記憶體位址,而y所儲存的是x的記憶體位址。
- *z為y所表示的位址(也就是&x),**z則再dereference一次,變成y所指向位址的值(*y),也就是x。
#include <iostream> using namespace std; int main() { int x = 10; void *v = &x; cout << v << endl;// CANNOT print *v int *p = (int*)v; ++*p; cout << *p << endl; return 0; }
- v是void pointer,當int x的位址指派給*v後,可以取得v的位址,但是*v無法取得。
- 使用int *p = (int*)v;將v cast成為int,指派給*p,此時可以印出*p。
#include <iostream> #include <cmath> using namespace std; double CircleArea(double r){ return M_PI*r*r; } double CirlcleCircumference(double r){ return 2*M_PI*r; } double Circle(double r, double (*call)(double)){ double result = (*call)(r); return result; } int main() { int r = 10; double (*perimeter)(double) = CirlcleCircumference; cout << Circle(r, CircleArea) << endl; cout << Circle(r, perimeter) << endl; return 0; }
- double (*call)(double)同為CircleArea()與CirlcleCircumference()的型態,所以只要傳入call的名稱與其中之一相同,表示將使用該函數。
- double (*perimeter)(double) = CirlcleCircumference;表示將原來CirlcleCircumference名稱改為使用perimeter代替。
#include <iostream> #include <cmath> using namespace std; class Circle{ double radius; // variable public: Circle(double r){radius = r;}; // constructor double area(){ // method return radius*radius*M_PI; }; }; int main() { Circle c1 = 10; // instance Circle c2 = 100; Circle c3 = 1000; Circle circles[] = {c2, c3}; Circle *p = &c1; cout << (*p).area() << "\n" << c1.area() << endl; Circle *ps = circles; cout << ps[0].area() << endl; cout << ps[1].area() << endl; return 0; }
- p->area()等同於(*p).area() or c1.area()。
- 若是物件所組成的array,則用法與之前提到的array相同,使用Circle *ps = circles;將整個array指派給ps,然後使用ps[index]來取得在index位置的物件。原則上就等於circles[index]。
Dynamic memory
- 在某些情況下,程式所需要的記憶體大小無法確認,此時可以配置動態記憶體。
- 使用關鍵字new將記憶體配置給pointer變數,在使用完之後,需要將記憶體釋放,歸還給系統,此時需使用delete關鍵字。
#include <iostream> #include <cmath> using namespace std; int main() { int *p = new int(100); cout << p << "\t" << *p << endl; p++; cout << p << "\t" << *p << endl; delete p; return 0; }
- 系統配置一塊int大小的記憶體給p,並給初值100。這樣就不用先宣告一個int,在取得位址(&),然後指派給p。
- new會配置記憶體,所以要指派給pointer變數。
#include <iostream> #include <cmath> using namespace std; int main() { int arraysize; cout << "Please input the size of array: " << endl; cin >> arraysize; int *a = new int[arraysize]; for(int i = 0; i < arraysize; i++){ cout << "a[" << i << "] = "; cin >> *(a+i); } for(int i = 0; i < arraysize; i++){ cout << "a[" << i << "] = " << a[i] << endl; } delete []a; return 0; }
- arraysize也可以配置成pointer,e.g. int *arraysize=new int(0);。
#include <cmath> using namespace std; int main() { int arraysize; cout << "Please input the size of array: " << endl; cin >> arraysize; int *a = new (nothrow) int[arraysize]; if(a == nullptr) cout << "Memory allocation error." << endl; else{ for(int i = 0; i < arraysize; i++){ cout << "a[" << i << "] = "; cin >> *(a+i); } cout << "-------------------" << endl; for(int i = 0; i < arraysize; i++){ cout << "a[" << i << "] = " << a[i] << endl; } delete []a; } return 0; }
- 將(nothrow)關鍵字加在宣告pointer的new後方,之後判斷是否pointer等於nullptr,若是則表示配置失敗。
#include <iostream> #include <cmath> using namespace std; int main() { int row, col; cout << "Please input the dimension of a 2D array" << endl; cin >> row >> col; int *arrPointer = new (nothrow) int[row*col]; if(arrPointer==nullptr){ cout << "Memory allocation error." << endl; }else{ for(int i = 0; i < row; i++){ for(int j = 0; j < col; j++){ cout << "[" << i << "][" << j << "] = "; cin >> *(arrPointer + col*i + j); } } cout << "--------------------" << endl; for(int i = 0; i < row; i++){ for(int j = 0; j < col; j++){ cout << "[" << i << "][" << j << "] = " << *(arrPointer + col*i + j) << endl; } } delete[] arrPointer; }//else return 0; }
- 其實就是變成1D的記憶體長度,算出每塊記憶體在2D array的位置即可。
Class
- 在設計class時使用pointer。
- destructor: 當設計class時配置了記憶體,可設計destructor,在程式結束後負責釋放記憶體。
#include <iostream> using namespace std; class Aclass{ int *x; public: Aclass(): x(new int){} // constructor, same to Aclass(){x = new int();} Aclass(const int& i){ // constructor x = new int(i); } ~Aclass(){delete x;} // destructor const int& value() const{return *x;} }; int main(){ Aclass a(100); cout << a.value() << endl; return 0; }
- destructor ~Aclass(){delete x;}用來在程式結束後刪除配置之記憶體。
- Aclass(): x(new int){}等同於Aclass(){x = new int();}。
#include <iostream> #include <cmath> using namespace std; class Animal{ public: string name; void setName (string name){ this->name=name; } }; class Dog: public Animal{ public: string call(){ return name + ": woof woof"; } }; class Cat: public Animal{ public: string call(){ return name + ": meow meow"; } }; int main(){ Dog lucky; Cat kitten; Animal *dog = &lucky; Animal *cat = &kitten; dog->setName("Lucky"); // lucky.setName("Lucky"); cat->setName("Kitten"); // kitten.setName("Kitten"); cout << lucky.call() << endl << kitten.call() << endl; return 0; }
- 此例主要要說明的是繼承而來的class與被繼承的class兩者的pointer型態是相容的(e.g. Animal *dog = &lucky;)。
- 使用dog->setName("Lucky");等同於lucky.setName("Lucky");。
#include <iostream> #include <cmath> using namespace std; class Animal{ public: string name; void setName (string name){ this->name=name; } virtual string call(){return "unknown animal sound";} void getName(){ cout << this->name << endl; } }; class Dog: public Animal{ public: string call(){ return name + ": woof woof"; } }; class Cat: public Animal{ public: string call(){ return name + ": meow meow"; } }; int main(){ Dog lucky; Cat kitten; Animal unknown; Animal *dog = &lucky; Animal *cat = &kitten; Animal *ani = &unknown; dog->setName("Lucky"); cat->setName("Kitten"); ani->setName("Unknown"); cout << lucky.call() << endl << kitten.call() << endl << unknown.call() << endl; dog->getName(); cat->getName(); return 0; }
- 因為動物都會鳴叫,所以設計virtual函數call(),在繼承的class處可以覆寫此方法。
- 因為unknown animal的call()函數其實沒有使用的必要,所以可以將其設為abstract,將virtual函數修改為virtual string call()=0;即可。
- 請注意有abstract方法後,class Animal無法被宣告、使用其中的函數。但其pointer還是可以使用非virtual函數(e.g. dog->getName();)。
#include <iostream> #include <cmath> using namespace std; class Animal{ public: string name; Animal (string name){ this->name=name; } virtual string call()=0; void getName(){ cout << this->name << endl; } }; class Dog: public Animal{ public: Dog(string name):Animal(name){} string call(){ return name + ": woof woof"; } }; class Cat: public Animal{ public: Cat(string name):Animal(name){} string call(){ return name + ": meow meow"; } }; int main(){ Animal *lucky = new Dog("Lucky"); Animal *kitten = new Cat("kitten"); cout << lucky->call() << endl << kitten->call() << endl; lucky->getName(); kitten->getName(); delete lucky; delete kitten; return 0; }
- 使用Animal *lucky = new Dog("Lucky");語法來配置記憶體,在使用後記得使用delete釋放出記憶體。
Exceptions & IO
- 例外是指預期中可能發生錯誤的情況。同時介紹如何使用C++進行Input&Output。
Exceptions
- 預期可能產生例外時,預先作的處置,稱為例外處理(Exceptions handling)。
- 使用try...catch...語法。
#include <iostream> using namespace std; int main(){ try{ int a[] = {1,2,3,4,5}; int index; cout << "Please input index : " << endl; cin >> index; if(index >= 5){ throw 20; }else{ cout << "a[" << index << "] = " << a[index] << endl; } }catch(int e){ cout << "Array index out of bound exception." << endl; }catch(...){ cout << "Unexpected error." << endl; } return 0; }
- 在try{}內寫程式內容,當可能錯誤(index >= 5)發生時,使用throw丟出例外,再由catch()承接。
- 丟出的例外形態(20),需與catch()所定義相符(int e)。
- Exception可能超過一個,使用catch(...)來承接所有其他未能被預期處理的例外。
exception | description |
bad_alloc | 當使用new失敗時 |
bad_cast | 當使用dynamic_cast失敗時 |
bad_exception | 當特定dynamic exception被拋出時 |
bad_typeid | 當使用type_id被拋出時 |
bad_function_call | 當拋出空的函數物件時 |
bad_weak_ptr | 當通過bad weak_ptr然後拋出shared_ptr時 |
logic_error | 當程式內部邏輯錯誤時 |
runtime_error | 執行程式偵測到錯誤時 |
#include <iostream> #include <exception> using namespace std; class exceptionone: public exception{ virtual const char* what() const throw(){ return "Something wrong."; } }exone; // exone為exceptionone的物件 int main(){ try{ throw exone; }catch(exception& e){ cout << e.what() << endl; } return 0; }
- 繼承exception然後重載what()函數。
Input & Output
- 輸出與輸入是資料的流動,之前常用的cout是將資訊輸出到螢幕上,cin是收集使用者輸入的資料,這兩個指令都是定義在
,所以每次都要將其include。而若要將資料寫入檔案或自檔案讀出,則可納入fstream來寫入與讀取檔案(或是使用ofstream來寫入檔案,ifstream來讀取檔案)。
#include <iostream> #include <fstream> using namespace std; int main(){ ofstream file; file.open("abc.txt"); file << "Write something.\n"; file.close(); return 0; }
- 使用ofstream來開啟檔案資料流,使用open()函數開啟連結檔案,使用後須使用close()函數關閉資料流。
- 到專案資料夾可以找到檔案(abc.txt)。
- 可以使用file.is_open()來判斷檔案資料流是否已開啟。
#include <iostream> #include <fstream> #include <string> using namespace std; int main(){ string line; // for one line of data ifstream file ("abc.txt"); while(getline(file, line)){ cout << line << endl; } file.close(); return 0; }
- 使用getline()每一次會讀出一行,所以使用while loop,一直讀到檔案的最後一行,因為讀取的資料是字串,所以需include
資料庫 。 - 可以使用is_open()方法先判斷是否已正常開啟再行讀取。
#include <iostream> #include <fstream> #include <string> using namespace std; int main(){ string line; // for one line of data ifstream file ("abc.txt"); if(file.is_open()){ while(getline(file, line)){ cout << line << endl; } file.close(); }else{ cout << "File stream is not open." << endl; } return 0; }