# C++ 的基本知識
# 必須注意的事
英文或阿拉伯數字需使用半形的字,不要使用全形。
英文字有大小寫的差別,輸入時務必小心。
例如: main 被打成 Main 或 MAIN 編譯時都會發生錯誤。程式中有空白的地方,需用鍵盤上的空白鍵隔開。
在一行或一組程式的結束後面切記加上 「;」,代表該行程式執行結束。
{ } 、[ ] 、 ( ) 和 " "、' ' 的使用時機互不相同。
善用 / /、/* */ 註解功能幫助自己查核時,減少大量時間和心力的消耗。
需善用 Tab 鍵 縮排 Enter 鍵 換行,可使程式更簡單、易讀,這是撰寫程式需養成的習慣。
如果括號內的程式只有一行,則括號可以省略。
若寫得程式很長可 分段做 debug 動作,一步一步做出修正,避免最後整個錯亂掉。
# 程式碼的內容
#include <iostream> // 為了要使用 cout 而引入的標頭檔 | |
using namespace std; // 為了更方便使用 cout 的註明 | |
int main() //main () 函數的開始 | |
{ | |
cout << "初次嘗試C++\n"; // 真正的程式從這樣一行開始 | |
cout << "要好好加油喔!\n"; // 接下來執行到這一行 | |
return 0; //main () 函數的結束 | |
} |
# 常出現的編譯問題 (CE)
expected ‘ ; ’ before ‘ ... ’ token
解決方案:在錯誤出現處的行末尾加上 ;expected ‘ } ’ before ‘ ... ’ token
解決方案:檢查自己縮排的狀況,並找出遺漏的 } 並補上“變數 / 常量 / 函式” was not declared in this scope
解決方案:
1. 檢查變數是否在使用前被宣告,若無則就宣告它 。
2. 確認使用的預設函式其標頭檔是否已被宣告,若無則宣告它。
# 常數、變數與資料
# 資料型態 (data type)
常用型態 | 意義 | 資料範圍 |
---|---|---|
int | 整數 | -2147483648~2147483647 |
long long int | 長整數 | -263~263-1 |
float | 單經度浮點數 | ±3.4x 10-38 ~ ±3.4x1038 |
double | 雙經度浮點數 | ±1.7×10-308~ ±1.7×10308 |
string | 字串 | "World" |
char | 字元 | 'A' |
bool | 布林 | true (1) 或 false (0) |
# 變數名稱 (variable)
- 用來做為變數的名稱,需注意的事,如下:
- 使用英文字母、阿拉伯數字、底線連接(_)等,不能使用特殊的符號,例如: sum-1
- 已保留的關鍵字(keyword) 不可為變數名稱。例如: return、break...
- 不能用阿拉伯數字作為開頭。例如: 12a、555...
- 英文字母的大小寫有區別。
# 變數宣告 (declaration)
int num; // 資料型態 變數名稱;
char a = 'A'; // 資料型態 變數名稱 = 初值;
int sum, ave, rank, ...; // 資料型態 變數名稱1, 變數名稱2, 變數名稱3,...;
# 宣告常數 (const)
利用常數給予一個定值可使數值被固定,如果後來再改變它,將發生錯誤
const double pi = 3.141592; //const 資料型態 變數名稱 = 特定資料 ;
//此後,pi值不會再被改變
# 運算子與基本結構
# 算術運算子
符號 | 功能 | 範例 | 說明 |
---|---|---|---|
+ | 加號 | a = x + y | |
- | 減號 | a = x - y | |
* | 乘號 | a = x * y | |
/ | 除號 | a = x / y | |
% | 取餘數 | a = x % y | |
++x | 運算前增量 | a = ++x + y | x=x+1, a=x+y |
x++ | 運算後增量 | a = x++ + y | a=x+y, x=x+1 |
--x | 運算前減量 | a = --x + y | x=x-1, a=x+y |
x-- | 運算後減量 | a = x-- + y | a=x+y, x=x-1 |
-x | 負號 | a = -x | |
+x | 正號 | a = +x |
:::note info
整數除整數,結果為整數。 浮點數除浮點數,結果為浮點數
例: 8 / 5 = 1 || 8.0 / 5.0 = 1.6
:::
# 關係與邏輯運算子
符號 | 功能 | 範例 | 說明 |
---|---|---|---|
> | 大於 | a>b | 若 a>b 則結果為真 |
>= | 大於等於 | a>=b | 若 a≧b 則結果為真 |
< | 小於 | a<b | 若 a<b 則結果為真 |
<= | 小於等於 | a<=b | 若 a≦b 則結果為真 |
== | 等於 | a==b | 若 a=b 則結果為真 |
!= | 不等於 | a!=b | 若 a≠b 則結果為真 |
! | 邏輯 NOT | !(a==1) | 若 a≠1 則結果為真 |
&& | 邏輯 AND | a>2&&a<9 | 若 2<a<9 則結果為真 |
|| | 邏輯 OR | a<2 || a>9 | 若 a<2 或 a>9 則為真 |
# 複合指定運算子
符號 | 功能 | 範例 | 說明 |
---|---|---|---|
= | 簡單指定 | x = y | 令 x = y |
+= | 加法指定 | x += y | 令 x = x + y |
-= | 減法指定 | x -= y | 令 x = x - y |
*= | 乘法指定 | x *= y | 令 x = x * y |
/= | 除法指定 | x /= y | 令 x = x /y |
%= | 餘數指定 | x %= y | 令 x = x % y |
:::note warning
指定值 x=y 之後,變數 x 原來的值被覆蓋,而 y 值不變
善用可以使程式碼變得更精簡,不善使用則... 會很困擾
:::
# 運算符號的優先順序
運算符號 | 優先順序 |
---|---|
( ) | 1 |
* , / , % | 2 |
+ , - | 3 |
==, <, >, <=, >=, != | 4 |
:::note warning
若優先順序並列,則程式會由左至右依序執行
記得先加減後乘除的觀念,善用括號
記得乘號在語言的世界裡,不能省略
:::
:::note primary
# Ex.01 面積 01:
利用海龍公式計算三角形面積 (不討論是否能夠成三角形)
,
:::
:::note primary
# Ex.02 距離:
輸入四個浮點數 ,計算坐標系上 到 的距離
距離公式:
:::
# 循序式結構 (sequence structure)
程式依序從第一個敘述執行至最後一個敘述
// 循序式結構 | |
#include <iostream> | |
using namespace std; | |
int main(){ | |
string name; // 第 1 步 | |
cin>>name; // 第 2 步 | |
cout<<"Hello, "<<name<<endl; // 第 3 步 | |
return 0; // 第 4 步 | |
} |
# 選擇式結構 (selection structure)
程式運行到條件敘述,當條件成立 (運算式值為 1) 時,重複執行重複區的敘述。
反之,當條件不成立時 (運算式值為 0),則結束重複結構。
// 選擇式結構 | |
#include <iostream> | |
using namespace std; | |
int main(){ | |
int num; // 第 1 步 | |
cout<<"請輸入一個數字"; // 第 2 步 | |
cin>>num; // 第 3 步 | |
if(num%2==0){ // 第 4 步 | |
cout<<"你輸入的是偶數"; //if 運算值為 1 時的第 5 步 | |
} //if 運算值為 0 省略第 5 步 | |
return 0; // 第 6 步 | |
} |
# 重複式結構 (repetition structure)
程式運行到重複敘述,當條件成立 (運算式值為 1) 時,重複執行重複區敘述。
反之,當條件不成立時 (運算式值為 0),則結束重複結構。
#include <iostream> | |
using namespace std; | |
int main(){ | |
int num,sum=0; // 第 1 步 | |
cin>>num; // 第 2 步 | |
for(int i=1;i<=num;i++) // 第 3 步判斷 | |
sum+=i; // 第 4 步,若執行完 i++ 後,仍小於 num 不斷重複 | |
cout<<"從1加到num的總和為:"<<sum; // 第 5 步 | |
return 0; // 第 6 步 | |
} |
# 條件選擇
# 邏輯運算
# 邏輯運算子
符號 | 功能 | 範例 | 說明 |
---|---|---|---|
! | 邏輯 NOT | !(a==1) | 若 a≠1 則結果為真 |
&& | 邏輯 AND | a>2&&a<9 | 若 2<a<9 則結果為真 |
|| | 邏輯 OR | a<2 || a>9 | 若 a<2 或 a>9 則為真 |
# 邏輯 AND 與 OR 運算真值表
運算式 A | 運算式 B | A && B | A || B |
---|---|---|---|
false | false | false | false |
false | true | false | true |
true | false | false | true |
true | true | true | true |
# 邏輯 NOT 運算真值表
A | !A |
---|---|
true | false |
false | true |
# 邏輯運算式值
邏輯運算式 | 邏輯運算值 |
---|---|
(4.3>3.7) && (7==4+3) | true(1) |
(9/2==4.5) || (5>3.2) | true(1) |
!(1.5 * 5 >= 2) | false(0) |
:::note primary
# Bouns 02 推算下列混合運算式的值 (true || false)
1. !(4.3 > 3.7) && (7 == 5 + 2) || (15 / 3 < 5) | |
2. (8.2 < 7.3 * 2) || !(1 + 3 * 2 < 5) | |
3. (96 / 4 + 2 > 20) && !(6 - 2 * 9 > 72 / 9) |
:::
# 條件選擇
# if 敘述
if(條件式) | |
{ | |
條件「成立」時的敘述; | |
} |
:::note warning
if (條件式) 後面沒有;
:::
# 例 1: 判斷正數
#include <iostream> | |
using namespace std; | |
int main(){ | |
int n; | |
cout<<"請輸入一個整數:"; | |
cin>>n; | |
if(n>0){ | |
cout<<n<<"是正數"; | |
} | |
return 0; | |
} |
# if-else 敘述
if(條件式) | |
{ | |
條件「成立」時,敘述1; | |
} | |
else | |
{ | |
條件「不成立」時,敘述2; | |
} |
:::note primary
# Ex.03 : 面積 02
繼 Ex.01 加上 if 先判斷是否能構成三角形
:::
# if-else if 敘述
if(條件1) | |
{ | |
條件1「成立」時程式碼區塊; | |
} | |
else if(條件2) | |
{ | |
條件1「不成立」,且條件2「成立」時的程式碼; | |
} | |
else if(條件3) | |
{ | |
條件1、2「不成立」,且條件3「成立」時的程式碼; | |
} | |
.... | |
else | |
{ | |
上述條件都「不成立」時的程式碼; | |
} |
# 例 2: 區分分數等級
#include <iostream> | |
using namespace std; | |
int main(){ | |
int number; | |
cout << "請輸入成績 (0 - 100):"; | |
cin >> number; // 輸入數值並存入 number | |
if (number >= 90) // 若 90<=number,則 | |
cout << "成績甲等\n"; // 輸出甲等並結束 if | |
else if (number >= 80) // 其餘若 80<=number,則 | |
cout << "成績乙等\n"; // 輸出乙等並結束 if | |
else if (number >= 70 ) // 其餘若 70<=number,則 | |
cout << "成績丙等\n"; // 輸出丙等並結束 if | |
else if (number >= 60 ) // 若 60<=number,則 | |
cout << "成績丁等\n"; // 輸出丁等並結束 if | |
else // 全部皆不成立,則 | |
cout << "成績戊等\n" // 輸出戊等並結束 if | |
return 0; | |
} |
:::note primary
# Ex.04 判斷一元二次方程式的根
由鍵盤輸入方程式 ax2+bx+c=0 的 a,b,c,判斷方程式根的狀態
- 若 b2-4ac>0,則表示方程式具有二個實根
- 若 b2-4ac=0,則表示方程式具有一個實根
- 若 b2-4ac<0,則表示方程式具有二個虛根
:::
:::note primary
# Ex.05 計算折扣價
假設一台電腦單價為 $39,999 元,由鍵盤輸入購買數量,計算並顯示總價
其採購量與折扣對應表如下:
| 數量 | 10~19 | 20~49 | 50~99 | 100 以上 |
|:----😐:-----😐:-----😐:-----😐:-------😐
| 折扣 | 10% | 20% | 30% | 40% |
:::
# 巢狀 if 敘述
if(條件1) | |
{ | |
if(條件2) | |
{ | |
條件1「成立」,且條件2「成立」時的程式碼A | |
} | |
else | |
{ | |
條件1「成立」,且條件2「不成立」時的程式碼B | |
} | |
} | |
else | |
{ | |
條件1「不成立」時程式碼C | |
} |
# 例 3: 用巢狀 if 判斷閏年年分
#include <iostream> | |
using namespace std; | |
int main(){ | |
int year; | |
cin >> year; | |
if(year % 4 !=0 ) // 如果不是 4 的倍數 | |
cout << year <<"不是閏年"; // 則輸出不是閏年 | |
else if(year % 100 ==0){ // 其中如果是 100 的倍數 | |
if(year % 400 ==0) // 如果又是 400 的倍數 | |
cout << year <<"是閏年"; // 則輸出是閏年 | |
else // 只是 100 的倍數 | |
cout << year << "不是閏年"; // 則輸出不是閏年 | |
} | |
else // 只能被 4 整除 | |
cout << year << "是閏年"; // 則輸出是閏年 | |
return 0; | |
} |
# switch 敘述
switch (條件運算式) | |
{ | |
case 數值1: | |
數值1「成立」的敘述區1; | |
break; // 中斷 switch | |
case 數值2: | |
數值2「成立」的敘述區2; | |
break; // 中斷 switch | |
default: | |
以上條件皆「不成立」敘述區n; | |
} |
# 例 4: 按 + - * / 鍵,執行 + - * / 運算
#include <iostream> | |
using namespace std; | |
int main() | |
{ | |
char letter; | |
int num1 = 90, num2 = 15; | |
cout<<"num1 = 90,num2 = 15\n"; | |
cout<<"從鍵盤上輸入+, -, *, / :"; | |
cin>>letter; | |
switch (letter){ | |
case '+': | |
cout<<"num1 + num2 ="<< num1 + num2 <<endl; | |
break; | |
case '-': | |
cout<<"num1 - num2 ="<< num1 - num2 <<endl; | |
break; | |
case '*': | |
cout<<"num1 * num2 ="<< num1 * num2 <<endl; | |
break; | |
case '/': | |
cout<<"num1 / num2 ="<< num1 / num2 <<endl; | |
break; | |
} | |
return 0; | |
} |
# 迴圈
# for 迴圈
for(變數初值;條件判斷;改變量) | |
{ | |
程式碼 | |
} |
:::note info
for ( ) 後面也沒有 ;
for 語句的三個部分都是可以省略的
:::
# 例 5: 計算 n! 的值
#include <iostream> | |
using namespace std; | |
int main() | |
{ | |
int n,sum=1; | |
cout << "請輸入n:"; | |
cin >> n; | |
for (int i=1;i<=n;i++) // 讓 i 從 1~n | |
sum*=i; // 每次迴圈 sum=sum*i | |
cout << sum; | |
return 0; | |
} |
# 巢狀迴圈
for(變數1初值;條件1判斷;改變量) | |
{ | |
for(變數2初值;條件2判斷;改變量) | |
{ | |
程式碼 | |
} | |
} |
# 例 6: 印出 n 層金字塔
#include <iostream> | |
using namespace std; | |
int main() { | |
int n; | |
cin>>n; | |
for(int i=1;i<=n;i++){ | |
for(int j=1;j<=n-i;j++) | |
cout<<" "; | |
for(int j=1;j<=2*i-1;j++) | |
cout<<"*"; | |
for(int j=1;j<=n-i;j++) | |
cout<<" "; | |
cout<<endl; | |
} | |
return 0; | |
} |
:::note primary
# Ex.06: 倒三角形
印出一個高為 10 的顛倒金字塔
:::
# while 迴圈
while(條件判斷) // 條件為「真」的時候繼續執行 | |
{ | |
程式碼 | |
} |
# 例 7: 把數字反轉
(若數字為 100,顛倒後的數表示為 1,不是 001)
#include <iostream> | |
using namespace std; | |
int main() | |
{ | |
int n; | |
cin>>n; | |
if(n==0) | |
cout<<0; | |
while(n%10==0 && n>0) | |
n/=10; | |
while(n%10!=0||n>=10) | |
{ | |
cout<<n%10; | |
n/=10; | |
} | |
return 0; | |
} |
# do...while 迴圈
do | |
{ | |
程式碼 | |
}while(條件判斷); // 條件為「真」的時候繼續執行 |
:::note warning
do...while 與 while 的差別在於 do...while 至少會做一次
do...while 後面要加分號,表示結束
:::
# 例 8: 小算盤開根號 (以牛頓法實作)
#include <iostream> | |
using namespace std; | |
int main() | |
{ | |
double a, n; | |
cin >> n; | |
a = n; | |
do | |
{ | |
a = (a*a+n)/(2*a); // 挑出的第 1 個近似值 a 之後,作一切線,切線和 x 軸的交點 | |
} while ( a*a-n>1e-13 ); // 當 a*a 和 n 的誤差 > 1e-13 時,繼續逼進 | |
cout << a; | |
return 0; | |
} |
# 陣列、字串
# 陣列
陣列(Array),是由相同類型的元素的集合所組成的資料結構,分配一塊連續的記憶體來儲存。利用元素的索引 (index) 可以計算出該元素對應的儲存位址。
int arr[5]; // 宣告一個大小為 5 的 int 陣列 | |
arr[0]=80; // 陣列的索引值由 0 開始 | |
arr[5]=90; // 索引值 0~4 | |
int arr[5] = { 1, 3, 5, 7, 9 }; // 宣告陣列時設定初值 | |
int arr[5] = { 1 }; //arr [0] 初值 1,其餘預設為 0 | |
int arr[] = { 1, 3, 5, 7, 9 }; // 陣列大小依初值自動計算 | |
int arr2D[4][2]; // 宣告二維陣列 (多維陣列) | |
int arr2D[4][2] = { { 1, 2 }, { 3, 4 }, { 5, 6 }, { 7, 8 } }; |
:::note info
如果陣列要用的比較大一些,它就要在全域宣告喔
:::
# 例 9: 利用泡沫排序法 (bubble sort)
將 {3,2,4,8,9,1,7} 由小至大排列,並依序輸出
#include <iostream> | |
using namespace std; | |
int main() | |
{ | |
int a[7]={3,2,4,8,9,1,7},t; | |
for(int i=0;i<7;i++){ | |
for(int j=0;j<7-i-1;j++){ | |
if(a[j]>a[j+1]){ | |
t=a[j]; | |
a[j]=a[j+1]; | |
a[j+1]=t; | |
} | |
} | |
} | |
for(int i=0;i<7;i++) | |
cout<<a[i]<<" "; | |
return 0; | |
} |
:::note primary
# Ex.07 成績單:
3 年 21 班前五號的學測成績如下:
座號 | 國文 | 數學 | 英文 | 自然 | 社會 | 總分 | 平均 |
---|---|---|---|---|---|---|---|
1 | 10 | 12 | 9 | 11 | 7 | ||
2 | 9 | 10 | 8 | 9 | 11 | ||
3 | 13 | 8 | 11 | 7 | 14 | ||
4 | 8 | 14 | 13 | 14 | 9 | ||
5 | 12 | 10 | 9 | 10 | 9 |
請利用多維陣列完成表格並完整的印出表格
:::
# 字串
字串實例可以使用 [] 指定索引來存取相對應位置的字元,就有如字元陣列的操作一般
string str1; // 內容為空字串
string str2 = "sololearn"; // 內容為指定的字串常量
可使用 str.length() 或 str.size() 得知字串大小
#include <iostream> | |
using namespace std; | |
int main() | |
{ | |
string s="Hello World"; | |
cout<<s長度為<<s.size()<<endl; | |
for(int i=0;i<s.size();i++) | |
cout<<s[i]; | |
return 0; | |
} | |
輸出-->s長度為11 | |
-->Hello World |
:::note warning
從字串上的數字,僅是字元。若直接進行運算,計算的依據將為 ASCII 碼,結果會錯誤
若需要進行運算,則必須先減去 '0' 才行
:::
# 例 10: 判別一個數字 N 是否為 3 的倍數 (N>1020)
#include <iostream> | |
using namespace std; | |
int main() | |
{ | |
string s; | |
cin>>s; | |
int sum=0; | |
for(int i=0;i<s.size();i++) | |
sum+=s[i]-'0'; | |
if(sum%3==0) | |
cout<<s<<"是3的倍數"; | |
else | |
cout<<s<<"不是3的倍數"; | |
return 0; | |
} |
:::note primary
# Ex.08 字串應用:
判別一個數字 N 是否為 11 的倍數 (N>1020)
:::
# 函式
# 自訂函式
有某些程式碼會經常使用,對於程式中出現兩次以上被重覆使用的程式片段,可以將之定義為函式以便重覆呼叫。
回傳值的型態 函式名稱(變數型態 參數1,變數型態 參數2,...) | |
{ | |
程式碼 | |
return 回傳值或運算式; | |
} |
# 例 11: 寫一函式可以計算 n!,並以之求 C(n,k)=\frac{n!}
#include<iostream> | |
using namespace std; | |
int f(int n) | |
{ | |
sum=1; | |
for(int i=1;i<=n;i++) | |
sum*=i; | |
return sum; | |
} | |
int main() | |
{ | |
int n,k; | |
cin >> n >> k; | |
cout << f(n)/((f(n-k)*f(k))<<endl; | |
return 0; | |
} |
:::note primary
# Ex.09 gcd 01:
寫一個函式計算兩數的最大公因數
:::
# void
如果呼叫函式不傳回任何值,則宣告為 void。
void 函式名稱(變數型態 參數1,變數型態 參數2,...) | |
{ | |
程式碼 | |
} |
# 遞迴
遞迴(Recursion),是指在函式中使用函式自身的方法。
:::note warning
遞迴函式必須有終止條件,才能被計算。
:::
# 例 12: 利用遞迴函式費氏數列的第 n 項
#include <iostream> | |
using namespace std; | |
int fib(int n) | |
{ | |
if (n == 0) //n==0 時終止,回傳 0。if 後只有一行,可省略 {} | |
return 0; | |
else if (n == 1) //n==1 時終止,回傳 1 | |
return 1; | |
else | |
return f(n-1)+f(n-2) // 遞迴呼叫 | |
} | |
int main() | |
{ | |
int n; | |
cin >> n; | |
cout << fib(n); | |
return 0; | |
} |
# 例 13: 利用遞迴函式求 ab的值
#include <iostream> | |
using namespace std; | |
int f(int a, int b) | |
{ | |
if( b == 0 ) | |
return 1; | |
if( b >= 1 ) | |
return a * f(a,b-1); | |
} | |
int main() | |
{ | |
int a, b; | |
while( cin >> a >> b ) | |
cout << f(a,b) << endl; | |
return 0; | |
} |
:::note primary
# Ex.10 gcd 02
繼 Ex.09 運用遞迴函式求兩數的最大公因數
:::