講師:建電學術長 鹽亞倫
C++ 介紹
Hello World!
變數 variables
運算子 operators
條件判斷 Conditions
迴圈 loops
陣列 Arrays
字串 Strings
函式 function
評測系統 Online Judges
And why is it important?
Bjarne Stroustrup
又難寫,也沒有貓圖形化介面
坦白講,C++ 一點都不適合初學者
那我們幹嘛要學他?
如果想要做APP 去學Java、Swift
C、C++是計算機科學的基礎!
如果想要架伺服器 去學PHP
如果想做網頁 去學HTML
如果你想做到任何事 去學python
編譯式語言
低階語言
速度極快
競賽程式必備!
(等等會提到)
IDE 整合開發環境
Text editors
文字編輯器
Visual
Studio
xcode
clion
Code::Blocks
Dev C++
VS code
Sublime
Vim
我們今天要用的---
一個線上的IDE
乾淨、好用、不用設定
進去以後先登入/註冊
然後按 create
進去之後長這樣
寫code的地方
output
執行鈕
先把裡面程式刪掉
學習程式語言的第一步
把以下內容打入程式區吧!
#include <iostream>
using namespace std;
int main() {
cout << "Hello World!" << endl;
return 0;
}
;
#include
#define
cin
cout
std::
(縮)(排)(空)(格)
endl '\n'
things compilers will do
編譯
預處理
連結
variables
怎麼宣告變數?
int a = 10;
int b; // 注意!此時b的值是亂的
char c = 'k'; // 字元用單引號
float pi = 3.14;
// 以下為錯誤示範
int max = 2147483647; // 不好 用到函式名稱
int while = 333; // 錯誤 用到保留字
用 = 給值
各種變數的型別
int | 整數 |
---|---|
long long | 長長的整數 |
char | 字元 |
string | 字串 |
bool | 布林(0 or 1) |
float | 小數(浮點數) |
double | 比float準兩倍的小數 |
那些年,我們一起被範圍搞
整數 | 範圍 |
---|---|
int long |
|
long long | |
short | |
unsigned int | |
unsigned long long | |
unsigned short |
\(-2147483648 \sim 2747483647\)
(\(-2^{31} \sim 2^{31}-1\))
\(-2^{63} \sim 2^{63}-1\)
\(-32768 \sim 32767\;\; (-2^{15}\sim 2^{16})\)
\(0 \sim 2^{32}-1\)
\(0 \sim 2^{64}-1\)
\(0 \sim 2^{16}-1\)
那些年,我們一起被精度搞
浮點數 | 大小 & 精度 |
---|---|
float | 4 bites (7位小數) |
double | 8 bites (16位小數) |
long double | 10 bites (19位小數) |
輸入兩個整數a, b,請你將他們互換
怎麼吃輸入? cin >> x;
#include <iostream>
using namespace std;
int main() {
int a, b;
cin >> a >> b;
}
#include <iostream>
using namespace std;
int main() {
int a, b;
cin >> a;
cin >> b;
}
不標準答案:
#include <iostream>
using namespace std;
int main() {
int a, b;
cin >> a >> b;
cout << b << " " << a << endl;
}
標準答案
#include <iostream>
using namespace std;
int main() {
int a, b, temp;
cin >> a >> b;
temp = a;
a = b;
b = temp;
cout << a << " " << b << endl;
}
那些年,我們一起分不清字元與字串
一個字母
怎麼存?
Ascii code!
那些年,我們一起分不清字元與字串
一個字母
怎麼存?
Ascii code!
重要性質:
char本身也是數字!
那些年,我們一起分不清字元與字串
一個字母
一個字元的陣列
等等會另外解釋
單引號''
雙引號""
注意不要用成“”‘’``之類的東西
栗子
給一個大寫字元,請用ascii轉成小寫
ANS:
#include <iostream>
using namespace std;
int main() {
char ch;
cin >> ch;
char n_ch = ch + 32;
cout << n_ch << endl;
// 或是
cout << (char)(ch + 32) << endl;
}
#include <iostream>
using namespace std;
int main() {
char ch;
cin >> ch;
cout << ch - 'A' + 'a' << endl;
}
栗子
將輸入的數字用字元存下,並且轉成實際的數字
大家自己想想嘍
operators
進行運算的東西
例如:+-*/=()[]
有一些不像符號的東西也算是運算子
(int)
new sizeof decltype
看看就好,不知道也不重要
剛剛應該講過
是把右邊的值給左邊
int a = 1;
char b = 'g';
char c;
c = b; // 注意這兩行的差異
c = 'b'; // 注意這兩行的差異
+ | - | * | / | % |
---|---|---|---|---|
加 | 減 | 乘 | 除 | 取餘數 |
重要:
/ 前後若為整數,為無條件捨去
若有小數,則是小數除法運算
% 用在負數或小數會出現各種詭異情況
請小心使用
+= | -= | *= | /= | %= | ++ | -- |
---|---|---|---|---|---|---|
加等於 | 減等於 | 乘等於 | 除等於 | 模等於 | 遞增 | 遞減 |
a += 5; a = a + 5;
c *= 5; c = c * 5;
i++; i += 1; i = i+1;
i = 10;
a = ++i;
// a = 11, i = 11
i = 10;
a = i++;
// a = 10, i = 11
各種題目的答案,有時候數字會太大,因此題目有時候會請你將答案 mod 一個很大的質數
ex. 1e9+7, 712271227
為什麼勒?敬請期待開學後數論小社課
等等再講
話說,大家有沒有覺得,我們一直提到的題目,到底是什麼題目?
在此為你隆重介紹---
以及
演算法程式競賽
Online Judges
最大目標:IOI資訊奧林匹亞
比賽方式:
題目會給你輸入,你要按照題目的要求給出正確的輸出
額外限制:你的程式必須要在指定時間與空間以內完成
-->考演算法
用OJ檢測你的code
校內能力競賽
北市賽
全國賽
選訓營 1!
海選 or APCS
初選
11人
12人
20人
10人
10人
4人
選訓營 2!
9月
11月
12月
1月
1,6,10月
3月
zerojudge: 台灣最大,題目有點參差不齊,個人不常用
TIOJ: 建中(資訊社or資讀)維護的,都是難題
codeforce: 世界最大oj,常常有比賽,但都在台灣時間半夜
Atcoder:第二大oj,在日本,比賽時間比較適合台灣人
cses
neoj
建北電資OJ
https://iscoj.fg.tp.edu.tw/
一一、一二學長去年把他復活的,題目還有點少,等待我們的努力QAQ
Conditions
布林判斷式 & 剛剛沒講完的運算子
回傳一個bool
1 == true == 真
0 == false == 假
常見運算子 | == | != | > | < |
---|---|---|---|---|
作用 | 等於 | 不等於 | 大於 | 小於 |
<= | >= | ! | && | || |
小於等於 | 大於等於 | 否 (1變0,0變1) |
且 | 或 |
飯粒
1 + 2 == 3 // true
1 + 2 == 4 // false
1 + 2 != 3 // false
1 + 2 != 4 // true
!(1 && 1) // false
(0 || 1) // true
注意事項:運算順序
() [] {} |
---|
! |
* / % |
+ - |
<< >> |
> >= <= < |
== != |
&& |
|| |
= += -= ?: |
先
後
if
if (條件式) {
cout << "條件式為true時會印出這一行" << endl;
}
else
if (條件式) {
cout << "條件式為true時會印出這一行" << endl;
} else {
cout << "條件式為false時會印出這一行" << endl;
}
else if
// A, B 皆為條件式
if (A) {
cout << "A 為 true" << endl;
} else if (B) {
cout << "A 為 false 但是 B 為 true" << endl;
} else {
cout << "A、B 都是 false" << endl;
}
經典範例
#include <iostream>
using namespace std;
int main() {
int score; cin >> score;
if (score >= 80) cout << "AaW不可能是電神一定是成績改錯了\n";
else if (score >= 60)
cout << "好扯竟然有及格\n"; // 注意:以上兩種寫法if只會包含一行
else if (score >= 40) {
cout << "快去準備補考\n";
}
else {
cout << "沒救了QAQ\n";
}
}
AaW的物理成績實在太爛了,面臨補考邊緣。已知建中學期總成績60分以上為及格,40~59分要參加補考,39分以下就被死當了QAQ。又這一次物理老師成績打法心狠手辣,如果有辦法拿到80分以上就算是大電神。
但是AaW小學數學沒有學好,請幫他判斷他的成績算是哪個範圍呢?
switch case
switch(變數/式子){
case 可能1: //符合可能1
做事;
break; // 沒有break會繼續執行!!!
case 可能2: //符合可能2
做事;
break;
default: //上面的可能都沒符合
做事;
break;
}
switch case
int a;
cin >> a;
switch(a){
case 100:
cout << "a==100" << endl;
break;
case 200:
cout << "a==200" << endl;
// 沒有break
case 300:
cout << "a==200 or a==300" << endl;
break;
default: //上面的可能都沒符合
cout << "a不是100, 200, 300" << endl;
break;
}
條件運算子
三元運算子
A? x: y
當A為true回傳x
否則回傳y
int a = 12;
int b = ((a==12)? 23: 24); // b == 23
int c = ((a==14)? 33: 66); // c == 66
有多筆測資部分之後會解釋要怎麼處理
loops
直接看例題:
No Judge:
給一個正整數\(\,n\)
輸出\(\,n\,\)個"*
"
#include<bits/stdc++.h>
using namespace std;
int main(){
int n;
cin>>n;
for(int i=0; i<n; i++) {
cout<<"*";
}
return 0;
}
迴圈
重複某件事情
直到...一個狀況才會停止重複
兩大迴圈
for (起始; 持續條件; 更新) {
// 注意是用分號隔開
// do something...
}
範例
輸出從0 ~ 9
#include <iostream>
using namespace std;
signed main(){
int n = 10;
for (int i = 0; i < n; ++i) {
cout << i << " ";
}
cout << endl;
return 0;
}
範例
輸出從1 ~ 10
0 1 2 3 4 5 6 7 8 9
#include <iostream>
using namespace std;
signed main(){
int n = 10;
for (int i = 1; i <= n; ++i) {
cout << i << " ";
}
cout << endl;
return 0;
}
1 2 3 4 5 6 7 8 9 10
#include <iostream>
using namespace std;
signed main(){
for (int i = 1; i <= 9; ++i) {
for (int j = 1; j <= 9; ++j) {
cout << i*j << " ";
}
cout << endl;
}
return 0;
}
1 2 3 4 5 6 7 8 9
2 4 6 8 10 12 14 16 18
3 6 9 12 15 18 21 24 27
4 8 12 16 20 24 28 32 36
5 10 15 20 25 30 35 40 45
6 12 18 24 30 36 42 48 54
7 14 21 28 35 42 49 56 63
8 16 24 32 40 48 56 64 72
9 18 27 36 45 54 63 72 81
while (A) { // A 為一個boolean expression
// A == true
// do something
}
// A == false
當表示式為真,不斷重複執行
和if的差別
while 內會一直重複,if 只會執行一次
#include <iostream>
using namespace std;
signed main(){
int a = 12;
while (a < 23) {
cout << a << " ";
a = a + 3;
}
cout << endl << "after while: a=" << a << endl;
return 0;
}
12 15 18 21
after while: a=24
please enter password:
wrong password
please enter password:
wrong password
please enter password:
password correct
管你三七二十一,先做再說
至少會被執行一次!
#include <iostream>
#include <string>
using namespace std;
int main() {
string password = "aawsoweak";
string userinput;
do {
cout << "please enter password: ";
cin >> userinput;
if (userinput != password) cout << "wrong password\n";
} while (userinput != password);
cout << "password correct\n";
}
please enter password:
password correct
brineorz
8wcp
aawsoweak
aawsoweak
這樣不就永遠卡住了嗎?怎麼辦?
while (true) {
// do sth
}
break
直接跳出去
while (條件) {
if (想要提早跳出) {
break;
}
// do sth
}
// break 完會跑到這邊
continue
跳到下一次迴圈
#include <iostream>
using namespace std;
int main() {
for (int i = 1; i <= 5; ++i) {
if (i == 3) {
cout << "continue executed!\n";
continue;
}
cout << "i = " << i << endl;
}
}
i = 1
i = 2
continue executed!
i = 4
i = 5
while (/*...*/) { // continue 會回到這裡
if (sth) continue;
if (sth) break;
// do sth
}
// break 會直接跳出到這裡
補坑
多筆測資讀到EOF?
例子:zj a004
int n;
while (cin >> n) {
// do sth
}
手動輸入測試時,可以用ctrl + D 代替EOF
補坑
多筆測資讀到n==0?
int n;
cin >> n;
while (n != 0) {
// do sth
cin >> n;
}
int n;
while (cin>>n && n) {
//do sth
}
array
給你\(\,n\,\)以及\(\,n\,\)個整數\(k\)
\(0\le k \le 100\)
請印出所有數字出現的數量
先來看看錯誤噁心示範
#include <iostream>
using namespace std;
int main() {
int a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29, a30, a31, a32, a33, a34, a35, a36, a37, a38, a39, a40, a41, a42, a43, a44, a45, a46, a47, a48, a49, a50, a51, a52, a53, a54, a55, a56, a57, a58, a59, a60, a61, a62, a63, a64, a65, a66, a67, a68, a69, a70, a71, a72, a73, a74, a75, a76, a77, a78, a79, a80, a81, a82, a83, a84, a85, a86, a87, a88, a89, a90, a91, a92, a93, a94, a95, a96, a97, a98, a99, a100;
a0 = a1 = a2 = a3 = a4 = a5 = a6 = a7 = a8 = a9 = a10 = a11 = a12 = a13 = a14 = a15 = a16 = a17 = a18 = a19 = a20 = a21 = a22 = a23 = a24 = a25 = a26 = a27 = a28 = a29 = a30 = a31 = a32 = a33 = a34 = a35 = a36 = a37 = a38 = a39 = a40 = a41 = a42 = a43 = a44 = a45 = a46 = a47 = a48 = a49 = a50 = a51 = a52 = a53 = a54 = a55 = a56 = a57 = a58 = a59 = a60 = a61 = a62 = a63 = a64 = a65 = a66 = a67 = a68 = a69 = a70 = a71 = a72 = a73 = a74 = a75 = a76 = a77 = a78 = a79 = a80 = a81 = a82 = a83 = a84 = a85 = a86 = a87 = a88 = a89 = a90 = a91 = a92 = a93 = a94 = a95 = a96 = a97 = a98 = a99 = a100 = 0;
int n;
cin >> n;
for (int i = 0; i < n; ++i) {
int temp;
cin >> temp;
switch (temp) {
case 0:
a0++;
break;
case 1:
a1++;
break;
case 2:
a2++;
break;
case 3:
a3++;
break;
case 4:
a4++;
break;
case 5:
a5++;
break;
case 6:
a6++;
break;
case 7:
a7++;
break;
case 8:
a8++;
break;
case 9:
a9++;
break;
case 10:
a10++;
break;
case 11:
a11++;
break;
case 12:
a12++;
break;
case 13:
a13++;
break;
case 14:
a14++;
break;
case 15:
a15++;
break;
case 16:
a16++;
break;
case 17:
a17++;
break;
case 18:
a18++;
break;
case 19:
a19++;
break;
case 20:
a20++;
break;
case 21:
a21++;
break;
case 22:
a22++;
break;
case 23:
a23++;
break;
case 24:
a24++;
break;
case 25:
a25++;
break;
case 26:
a26++;
break;
case 27:
a27++;
break;
case 28:
a28++;
break;
case 29:
a29++;
break;
case 30:
a30++;
break;
case 31:
a31++;
break;
case 32:
a32++;
break;
case 33:
a33++;
break;
case 34:
a34++;
break;
case 35:
a35++;
break;
case 36:
a36++;
break;
case 37:
a37++;
break;
case 38:
a38++;
break;
case 39:
a39++;
break;
case 40:
a40++;
break;
case 41:
a41++;
break;
case 42:
a42++;
break;
case 43:
a43++;
break;
case 44:
a44++;
break;
case 45:
a45++;
break;
case 46:
a46++;
break;
case 47:
a47++;
break;
case 48:
a48++;
break;
case 49:
a49++;
break;
case 50:
a50++;
break;
case 51:
a51++;
break;
case 52:
a52++;
break;
case 53:
a53++;
break;
case 54:
a54++;
break;
case 55:
a55++;
break;
case 56:
a56++;
break;
case 57:
a57++;
break;
case 58:
a58++;
break;
case 59:
a59++;
break;
case 60:
a60++;
break;
case 61:
a61++;
break;
case 62:
a62++;
break;
case 63:
a63++;
break;
case 64:
a64++;
break;
case 65:
a65++;
break;
case 66:
a66++;
break;
case 67:
a67++;
break;
case 68:
a68++;
break;
case 69:
a69++;
break;
case 70:
a70++;
break;
case 71:
a71++;
break;
case 72:
a72++;
break;
case 73:
a73++;
break;
case 74:
a74++;
break;
case 75:
a75++;
break;
case 76:
a76++;
break;
case 77:
a77++;
break;
case 78:
a78++;
break;
case 79:
a79++;
break;
case 80:
a80++;
break;
case 81:
a81++;
break;
case 82:
a82++;
break;
case 83:
a83++;
break;
case 84:
a84++;
break;
case 85:
a85++;
break;
case 86:
a86++;
break;
case 87:
a87++;
break;
case 88:
a88++;
break;
case 89:
a89++;
break;
case 90:
a90++;
break;
case 91:
a91++;
break;
case 92:
a92++;
break;
case 93:
a93++;
break;
case 94:
a94++;
break;
case 95:
a95++;
break;
case 96:
a96++;
break;
case 97:
a97++;
break;
case 98:
a98++;
break;
case 99:
a99++;
break;
case 100:
a100++;
break;
}
// .........
}
}
顯然,這樣做很沒效率
陣列A
[0]
[1]
[2]
[3]
[4]
[5]
索引值
陣列頭
陣列尾
一個長度為6的陣列
[6]
#include <iostream>
using namespace std;
typedef long long ll
// 全域宣告
int handinit[5] = {0, 1, 2, 3, 4};
int autoinit[3] = {0}; // [0, 0, 0]
int partinit[4] = {1, 2}; // [1, 2, 0, 0]
int nosize[] = {1, 3 ,5}; // [1, 3, 5]
int notsafe[3]; // [0, 0, 0] 因為是全域,所以會補0
int err[]; // 不合法!沒有大小也沒有初始值
int main() {
// 區域宣告
int arr[10] = {0};
char arr2[5] = {'a','b','c','d','e'};
ll bad[10]; // 危險,此時值不定!
}
T name[size_t] = {init, array}
注意初始化!
注意陣列長度無法調整!
#include <iostream>
using namespace std;
typedef long long ll
// 全域宣告
int arr[5] = {0, 10, 20, 30, 40};
int main() {
cout << "arr第三項 = " << arr[3] << endl; // arr第三項 = 30
arr[3] += 5;
cout << "arr第三項 = " << arr[3] << endl; // arr第三項 = 35
}
name[index]
也就是說,我們可以建立一個陣列\(C\)
\(C[i]\) 代表 \(i\) 出現了幾次
來寫寫看吧!
答案點我
#include <iostream>
using namespace std;
int main(){
int n;
cin >> n;
int C[101] = {0};
for (int i = 0; i < n; ++i) {
int t;
cin >> t;
C[t]++;
}
for (int i = 0; i <= 100; ++i) {
if (C[i] > 0) {
cout << i << " " << C[i] << endl;
}
}
return 0;
}
要是先弄好大小,好浪費
聽說... C++ 裡面有個神奇的資料庫STL
裡面有...
std::vector !!!!!
重作簡報好累,我懶
偷學長得更開心
string
這是字串
這也是字串
this is a 字串, too.
講完了,下課
char chs[20] = "this is a str"
字串A
'h' | 'u' | 'h' | 'a' | '\0' | '\0' |
---|
[0]
[1]
[2]
[3]
[4]
[5]
索引值
字串頭
陣列尾
一個長度為6字串
char A[6] = "huha";
[6]
字串尾
(NULL字元)
std::string !!!
#include <iostream>
#include <string>
using namespace std;
int main() {
string s = "please enter your name.\n";
string name, s2, s3;
cout << s;
cin >> name; // 可以直接這樣輸入AaW
s2 = "hello, ";
ret = ret + name;
cout << ret << endl; // hello, AaW
}
string s = "abcdefghijk";
for (int i = 0; i < s.size(); ++i) {
// do sth with s[i]
}
for (char& ch : s) {
// do sth with ch AKA s[i]
}
string s = "password";
string s2 = "wordpass";
if (s == s2) {
cout << "they r same\n";
}
else {
cout << "they r not same\n";
}
// they r not same
==
< or >
string s = "apple";
string s2 = "elephant";
if (s < s2) {
cout << "s shorter than s2\n";
}
// s shorter than s2
function
怎麼辦?
包裝成函式
函數\(f\)
input
output
\(x\)
\(f(x)\)
#include <iostream>
using namespace std;
void printnum(int x) {
cout << "x = " << x << endl;
return;
}
int main() {
int a = 10101;
printnum(a);
}
void printnum(int x) {
// 做事的地方
cout << "x = " << x << endl;
return;
}
回傳值型態
參數列
int abs_minus(int a, int b) {
// 回傳 |a-b|
int k = a - b;
if (k < 0) k = -k;
return k;
}
#include <iostream>
using namespace std;
int n = 0;
void func(int a) {
a = 15;
}
void func2() {
n = 15;
}
int main() {
// n = 0
func(n);
// n = 0,因為 n 被複製給區域變數a,a的值更動之後n不會變
func2();
// n = 15
}
以後再說
去年資讀簡報,有興趣自己研究
no judge:
寫出一個函數,給你字元\(\,c\,\)和字串\(\,s\,\)
請回傳\(\,c\,\)在\(\,s\,\)中出現幾次
提示點我
for (char i : s)
int countChar(char c, string s) {
int ans = 0;
for (char i : s) {
if (i == c) {
ans++;
}
}
return ans;
}
information
stackoverflow 問問題的地方
shengyu's talk 中文優質部落格
google、youtube 這...不用多說吧
板中資訊社 超詳盡
建中校培講義 主要是演算法,很電的資源