作者:李佳樺
日期:2021/04/16
基礎架構
// 使用名稱為iostream的標頭檔,用於資料輸入輸出 (應該吧?
#include <iostream>
using namespace std; // 定義名稱為 std 的命名空間
int main(){ // 主程式,程式由此開始執行
cout << "Hello World!" << endl; // 輸出指令
return 0; // 程式結束,可省略
}
標頭檔 Header files
標頭檔能夠引入函式庫中,如 camth, cctype …
C++ 使用了 #include 這個指令來載入標頭檔
//萬用標頭檔
#include <bits/stdc++.h>
註解 comment
在程式碼中做適當的註解能使其更容易閱讀
// 這是單行註解
/*
這是多行註解
可以換行
*/
縮排 Indent
我們可以用 TAB 鍵來進行縮排
增加程式碼的可讀性
如果只有單行敘述句則可以省略大括號
// 未縮排
while(1){cout << 12 << endl;}
// 縮排後
while(1){
cout << 12 << endl;
}
// 省略
while(1)
cout << 12 << endl;
敘述句
敘述句以分號 ; 隔開
int a;
a=5;
cout << a << endl;
區塊 Block
C++用大括號 { } 來表示一個區塊
通常加在函式、條件句後
// while
while(1){
cout << "Hello";
}
// if
if(a>0){
cout << "Hey";
}
// 建立函式
int func(int a, int b){
return a+b;
}
輸入輸出 input & output
在C++中,我們使用 cin 和 cout 以在終端機獲取和輸出資料
<< 和 >> 代表資料流方向
int a; // 宣告變數 a
cin >> a; //輸入 a
cout << a+1; //輸出a+1
// input: 5
// output: 6
我們還能使用多個 << 或 >> 來輸入輸出多個資料
int a, b; // 宣告變數 a b
cin >> a >> b;
cout << "總合為: " << a+b << endl; // 輸出 a+b
// input: 2 3
// output: 總合為: 5
習題
命名規則
C++的變數名稱遵守著一定的規則
當名稱和關鍵字(keyword)重複或不合法時,會造成無法編譯的錯誤
- 變數名稱的第一個字不可為數字( 0~9 )或符號( @ , & , # … )但可為底線( _ )
- 變數名稱不可使用中文
- 英文字母的大小寫不同,代表的東西也不同,因此我們可以利用此特性來避開關鍵字的使用
常數 CONSTANT
常數在程式中為固定不變的數,無法更改其初始值
我們可以使用 #define 和 const 來定義或宣告一個常數
#define Pi 3.14159
// #define 可以用來定義一個字詞,當那個詞被編譯時,會被轉換成所定義的程式碼
// Pi 常數名稱
// 3.14159 常數初始值
const double Pi 3.14159
// const 宣告這個數為常數
// double 常數型態,不可省略
資料型態 DATA TYPE
資料型態 | 中文意義 | 位元組(byte) | 範圍 |
---|---|---|---|
short | 短整數 | 2 | -32768 ~ 32767 |
int | 整數 | 4 | -2,147,483,648 ~ 2,147,483,647 |
long long int | 長整數 | 8 | ‘’ |
char | 字元 | 4 | 0 ~ 255 |
bool | 布林值 | 1 | false 或 true (0 或 1) |
float | 浮點數 | 4 | ‘’ |
double | 倍浮點數 | 8 | ‘’ |
浮點數的有效位數至小數點後第7位,而倍浮點數的有效位數至小數點後第15位
有號無號 SIGNED & UNSIGNED
型態可以分成 有號 ( signed ) 和 無號 ( unsigned ) 兩種
預設值為有號
short a; // 有號整數 -32768 ~ 32767
unsigned short b //無號整數 0 ~ 65535
溢位 OVERFLOW
如果指定給變數的值超過變數型態的範圍,將會發生溢位的錯誤
編譯器不會對可能會溢位的程式碼發出警告
short a = 32768; // 範圍: -32768 ~ 32767
cout << a << endl; // output: -32768
跳脫字元 ESCAPE CHARACTER
在反斜線 \ 後加上字元
用於對電腦的命令或表示不可列印的字元
跳脫字元 | 結果 |
---|---|
\a | 讓蜂鳴器發出嗶聲 ( alarm ) |
\b | 退後一格 ( backspace ) |
\f | 換頁 ( form feed ) |
\n | 換行 ( line feed ) |
\r | 歸位 ( carriage return ) |
\t | 水平制表 ( horizontal tab ) |
\v | 垂直製表 ( vertical tab ) |
\‘ | 顯示單引號 ’ |
\“ | 顯示雙引號 “ |
\ \ | 顯示反斜線 \ |
資料型態轉換
double a = 1.23;
int b = a; // 1.23 --> 1 (無條件捨去)
cout << (int)a; //強制轉換型態 浮點數 --> 整數
int p = 2;
double q = 1.2;
cout << p+q; // 3.2
// 先把 p 轉換成 double,再與 q 相加
大型態轉換至小型態時將會失去原本的精度
編譯器進行不同型態的運算時會先把精度小的數字轉換成精度大的
習題
運算子
在程式中,我們能使用運算元和運算子來進行算數運算、邏輯判斷…等
其中運算元可以是常數、變數、數字或是有回傳值的函式
我們將運算元和運算子的組合稱為運算式
算數運算子
運算子 | 功能 | 用法 |
---|---|---|
+ | 加 | a + b |
- | 減 | a - b |
* | 乘 | a * b |
/ | 除 | a / b |
% | 取餘數 | a % b |
++ | 遞增 | a++ |
– | 遞減 | b– |
int a=13;
int b=5;
cout << a + b; // 18
cout << a - b; // 8
cout << a * b; // 65
cout << a / b; // 2
cout << a % b; // 3
遞增和遞減根據位置的不同而有不同的結果
int a=2;
cout << a++; // 2
cout << a; // 3
int b=2;
cout << ++b; //3
cout << b; //3
當 ++ 或 – 在前面時,本身會先加 1 後再進行運算
而當 ++ 或 – 在後面時,進行運算後本身才加上 1
複合指定運算子
我們用等號 (指定運算子) = 來指定變數的值
而 指定運算子 搭配 算術運算子 後形成 複合指定運算子
運算子 | 用法 |
---|---|
+= | a+=b |
-= | a-=b |
*= | a*=b |
/= | a/=b |
%= | a%=b |
int a=5;
a+=3; // a=a+3 將 a 的值加上 3 之後再指定給 a ∴ a = 5 + 3 = 8
a-=2; // a=a-2 同理,將 a 的值減去 2 之後再指定給 a ∴ a = 8 - 2 = 6
a*=4; // a=a*4 ∴ a = 6 * 4 =24
a/=3; // a=a/3 ∴ a = 24 / 3 = 8
a%=7; // a=a%7 ∴ a = 8 % 7 = 1
關係運算子
我們能用下列運算子來進行條件的判斷:
運算子 | 功能 | 用法 |
---|---|---|
> | 大於 | a>b |
< | 小於 | a<b |
== | 等於 | a==b |
>= | 大於等於 | a>=b |
<= | 小於等於 | a<=b |
!= | 不等於 | a!=b |
int a=3, b=5, c=7;
cout << (a>b); // false
cout << (b==5); // true
cout << (c>=7); // true
cout << (a!=2); // true
邏輯運算子
我們能使用邏輯運算子能進行邏輯的判斷
運算子 | 功能 | 用法 |
---|---|---|
&& | 且 (交集) | A && B |
|| | 或 (聯集) | A || B |
! | 不等於 | !A |
int a=3, b=5, c=7;
cout << (a>2 && c<6); // false
cout << (b==5 || a>4) // true
cout << !(a>=3 && c<=8) // false
A && B ,當A和B皆為 True 時,結果為 True,其餘皆為 False
A || B ,當A和B皆為 False 時,結果為 False,其餘皆為 True
條件運算子
條件運算子 又稱為 三元運算子,其傳回值依條件式的結果而定
如果條件式的結果為 True,則回傳冒號前的值,若結果為 False,則回傳冒號 : 後的值
int a=5, b=9;
cout << (a>b ? "yes" : "no"); // no
條件判斷與迴圈
條件判斷
IF
當 if 的判斷條件為 True 時,將會執行 if 區塊內的敘述
若結果為 False ,則跳過此區塊
int a=7, b=9;
if(a>b){ // False
cout << "Hello" << endl; // 跳過 if 區塊內的敘述
}
if(b>5){ // True
a+=b; // a=a+b ∴a=16
}
IF … ELSE
當 if 的判斷條件為 True 時,將會執行 if 區塊內的敘述
若結果為 False ,則執行 else 區塊內的敘述
int a=5, b=7;
if(a>b){ // False
cout << "OK" << endl;
// 跳過 if 區塊內的敘述
}
else{ // 當 if 條件結果為 False
cout << "NO" << endl; // NO
// 執行 else 區塊內的敘述
}
ELSE IF
else if 可以放在 if 和 else 中間,用以判斷其他條件
int a=5, b=7;
if(a>b){ // False
cout << "Perfect" << endl;
// 跳過此區塊內的敘述,進入 else if 的區塊
}
else if(a<4){ // False
cout << "fabulous" << endl;
// 跳過此區塊內的敘述
}
else if(b>5){ // True
cout << "Nice" << endl; // Nice
// 當上面區塊的條件結果為 False 且自己的條件結果為 True
// 跳出流程判斷
}
else{
cout << "Good" << endl;
// 不會執行到此區塊
}
else if 的數量可以根據自己所需增加數量
SWITCH
switch 可以用來判斷單一條件
在條件式數量多的情況下,能使程式碼變得相對簡潔
int a=10;
switch(a/3){ // a/3 是switch的條件句
// 如果 a/3 和 case 後的數字或字元相等,則執行此case區塊的敘述
case 2: // a/3 != 2 False
cout << "Red" << endl;
break;
case 3: // a/3 == 3 結果為 True ,進入敘述
cout << "Green" << endl; // Green
break; // 跳出 switch 的判斷流程
case 4: // 此 case 區塊不會被執行
cout << "Blue" << endl;
break;
default: // 若上面所有 case 皆不符合,則執行 default 區塊的敘述
cout << "Color" << endl;
break;
}
case 後面必須加上冒號,而不是大括號
case 的敘述結束後,需要加上 break ,跳出 switch,否則會繼續向下執行另一個 case
迴圈
FOR
for 迴圈必須事先指定變數的初始值、結束條件及每執行一次變數的增減值
for(int i=0;i<10;i++){
// Code
}
int i=0 :
指定變數初始值i<10 :
結束條件,當 i 等於 10 時,跳出迴圈i++ :
控制變數增減,每跑一次迴圈就執行一次
for(int i=0;i<5;i++){
cout << "i=" << i << endl;
}
/*
當 i=0 ,判斷 i<5 為 True ,輸出 i=0 , i 加 1
當 i=1 ,判斷 i<5 為 True ,輸出 i=1 , i 加 1
當 i=2 ,判斷 i<5 為 True ,輸出 i=2 , i 加 1
當 i=3 ,判斷 i<5 為 True ,輸出 i=3 , i 加 1
當 i=4 ,判斷 i<5 為 True ,輸出 i=4 , i 加 1
當 i=5 ,判斷 i<5 為 False ,跳出迴圈
*/
WHILE
當 while 迴圈的條件句為 True 時,便會重複執行下去
我們可以在 while 迴圈中加入變數,進行迴圈次數的控制
int a=5;
while(a>0){ // while 的條件句, 當結果為 False, 跳出迴圈
cout << "a=" << a << endl;
a--;
}
/*
當 a=5 ,判斷 a>0 為 True,輸出 a=5 ,a減1
當 a=4 ,判斷 a>0 為 True,輸出 a=4 ,a減1
當 a=3 ,判斷 a>0 為 True,輸出 a=3 ,a減1
當 a=2 ,判斷 a>0 為 True,輸出 a=2 ,a減1
當 a=1 ,判斷 a>0 為 True,輸出 a=1 ,a減1
當 a=0 ,判斷 a>0 為 False,跳出迴圈
*/
DO … WHILE
我們可以使用 do … while 來使我們的程式碼至少被執行一次
int i=1
do{
// 進來迴圈時,先不進行條件判斷
cout << "Only one" << endl;
i--;
}while(i>0); // 如果條件句為 True ,再次進入迴圈,否則跳出迴圈
迴圈控制指令
我們可以藉由迴圈控制指令,使的迴圈直接進入下一次的迴圈或結束
常見的指令有 break 、 continue
CONTINUE
for(int i=1;i<11;i++){ // 從 i=1 執行到 i=10
if(i%2==0) //如果i整除2
continue; // 進入下一次迴圈
// 只有當 i 不被 2 整除才會被輸出
cout << i << " "; // 1 3 5 7 9
}
BREAK
for(int i=1;i<11;i++){ // 從 i=1 執行到 i=10
if(i%2==0) //如果i整除2
continue; // 進入下一次迴圈
// 只有當 i 不被 2 整除才會被輸出
cout << i << " "; // 1 3 5 7 9
}
習題
CJOJ 1001
CJOJ 1004
CJOJ 1005
CJOJ 1007
CJOJ 1008
CJOJ 1021
陣列
一維陣列
陣列是由許多相同型態的變數所串連而成的
我們可以將陣列想成各自有不同編號的收納盒
第一格的編號為 0 ,第二格的編號為 1 … 以此類推
// 宣告陣列
int arr[3]={4,5,6}
// 資料型態 陣列名稱[陣列大小]={初始值0,初始值1,...}
// 取得存在陣列中的值
arr[1] // 5
// 陣列名稱[索引值]
- 陣列的大小是固定不變的
- 如果陣列的大小超過記憶體的大小,將會發生錯誤
這時可以試著在 main 的區塊外宣告陣列- 宣告陣列時不一定要給予初始值
不過我們可以將陣列中所有值初始化為 0int array[10] = { 0 }
二維陣列
我們可以把二維陣列想像成一個平面的收納盒
int array2D[3][3] = { {1,2,3},{4,5,6},{7,8,9} };
cout << array2D[1][0] + array2D[2][2] + array2D[0][2] << endl; // 16
/*
1 2 3
4 5 6
7 8 9
array2D[1][0] → 第 2 列 第 1 行 → 4
array2D[2][2] → 第 3 列 第 3 行 → 9
array2D[0][2] → 第 1 列 第 3 行 → 3
*/
訪問陣列
我們能利用迴圈來訪問陣列
int array[3] = {1, 2, 3}; // 宣告陣列
for(int i=0;i<3;i++){ // 從 i=0 到 i=2
cout << array[i] << endl; //輸出索引值為 i 的值
}
int inputArray[5]; // 宣告一個空陣列
for(int i=0;i<5;i++){ // 從 i=0 到 i=5
cin >> inputArray[i]; // 讓使用者輸入陣列的值
}
int array2d[3][3] = { {1,2,3},{4,5,6},{7,8,9} };
for(int i=0;i<3;i++){ // 從 i=0 到 i=2
// 記得相同區塊內不能有名稱相同的變數
for(int j=0;j<3;j++){ // 從 j=0 到 j=2
array2d[i][j]+=2; // 全部加2
// { {3,4,5},{6,7,8},{9,10,11} }
}
}
/*
訪問順序:
array2d[0][0] => array2d[0][1] => array2d[0][2] =>
array2d[1][0] => array2d[1][1] => array2d[1][2] =>
array2d[2][0] => array2d[2][1] => array2d[2][2]
*/
氣泡排序法 - 概念
從陣列的開頭不斷的比較兩個數字
如果前面的數字比較大,則兩者交換,反之則不交換
第一次要檢查陣列長度-1
次,隨後每次檢查的次數會減1,直到完成排序
C++的函式庫中有內建排序函數 sort():
int arr[3] = {2,3,1} sort(arr, arr+3); // {1,2,3}