基礎整理:

基本架構要背

1
2
3
4
5
6
7
8
9
#include<bits/stdc++.h>   //萬用標頭
using namespace std;
int main(){
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); //IO優化

//主程式丟中間

return 0;
}

變數

1
2
3
4
5
int x;
int x,y; //若多個輸入用 , 隔開
long long x;

比賽用long long存正數 double存浮點數(有小數點) char字元 string字串 bool布林值

輸入

1
2
3
4
cin>>x;
cin>>x>>y; //多個輸入
getline(cin,x);
//存字串用getline()

補充 https://www.runoob.com/note/50168


FOR

1
2
3
4
5
6
7
8
9
10
for迴圈結構
for(設值;目標;每執行一次程式所要做的改變){
執行內容;
}


//實作
for(int i=0;i<100;i++){
cout<<i<<" \n";
}

註解: \n意思=endl;


if

直接帶題目: 奇偶數的判別

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
int n;
cin >> n;
if (n % 2 != 0){
cout << "odd!\n";
}
else{
cout << "even!\n";
}



//也可以簡寫成這樣
if (n % 2 != 0) cout << "odd!\n";
else cout << "even!\n";


//或更精簡 像這樣
(n%2!=0)?cout << "odd!\n":cout << "even!\n";

使用方式:
(判別式) ? (如果成立就執行這個) : (否則執行這邊) ;

if / else / else if 用法要熟記

1
2
3
4
5
6
7
8
9
10
11
12
if (num < 10){
ans = 1;
}
else if (num < 100){
ans = 2;
}
else if (num < 1000){
ans = 3;
}
else if (num < 10000){
ans = 4;
}

陣列

解題時建議一律將陣列宣告在 main 函式之上,
example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <bits/stdc++.h>
using namespace std;

int price[1024]; // 宣告在 main() 之上 意思就是丟成全域變數

int main(){

int n, i;
cin >> n;
for (i=0; i<n; i++){
cin >> price[i];
}
for (i=0; i<n; i++){
cout << "price[" << i << "] = " << price[i] << ";\n";
}
return 0;
}

更正確的說是,不要宣告在任何函數內,包括但不限於 main()。 關於函數以及全域、區域變數的差異,在後續章節會再提及。

結論而言,在 main() 裡面宣告太大的陣列(粗估 10000 以上),
可能會在某些環境下導致程式當掉。

到時候會教一個好用的東西叫vector

陣列的大小恆久不變

陣列一旦宣告完後,大小從此固定,無法改變。

如此一來,在宣告時由於仍無法得知所需個數,
必須考慮最差情形所需要的數量,再預留至少 5~10 作為緩衝。

例如題目最多給 1000 個整數,則宣告時至少需要 1005 的大小。
沒用上的部份就空著沒有關係,用來交換風險的降低非常划算。

若題目未講明最大數值範圍,保險起見可以多宣告一些。(多開不用錢)

陣列的初始化

陣列可以在宣告時給予初始值,例如:

1
2
3
4
5
6
7
int dx[4] = {0, 1, 0, -1};
{} 僅限用於初始化,不能用於對已宣告好的陣列


以下是錯誤的:
int dx[4];
dx = {0, 1, 0, -1}; // compile error!!

初始化時「未指定」(長度不足)的部份,會自動填入 0,例如以下:

1
2
3
4
5
int dx[4] = {0};
for (int i=0; i<4; i++)
{
cout << dx[i] << '\n';
}

以下 code 並不能把陣列每一格初始化成 -1。

1
2
3
4
5
int dx[4] = {-1};
for (int i=0; i<4; i++)
{
cout << dx[i] << '\n';
}

陣列建表 - 將不規則資料整理成可用迴圈跑過

陣列的初始化,可用來將必要資料,建成一張表來使用,
藉此簡化程式碼、增加可讀性。

同時,能讓不規則資料在陣列索引上產生規則,方便用迴圈跑過。

例如,輸入一個座標,輸出其上、下、左、右相鄰的四個座標。
原本四個方向的位移量沒有什麼規則性,難以用迴圈窮舉,不過放進陣列後就能窮舉陣列的索引值,再從陣列取出資料,例如以下例子。

1
2
3
4
5
6
7
8
int x, y, i;
int dx[] = {0, 1, 0, -1};
int dy[] = {1, 0, -1, 0};
cin >> x >> y;
for (i=0; i<4; i++)
{
cout << "(" << x+dx[i] << ", " << y+dy[i] << ")\n";
}

透過預先將 x, y 的變化量建成一張表,就能整合成一個迴圈,而不必個別處理。


字串

文字的處理鮮少只處理單一個文字,
因此需要能夠將多個文字視為一個單位的字串。

字串 string

字串為零或多個字元,按特定順序排列而成。

最初的 cout << "hello world!\n""hello world!\n" 就是一個字串。
概念上和字元陣列有共通之處,但又不太相同。

字串型別與宣告

字串的型別為 string。

例如以下程式碼示範如何宣告一個名為 str 的字串變數:

1
2
3
4
string str;

//和基本型別不同,字串是有包裝過的型別,犧牲一些效能換取便利性。
也因此,剛宣告的字串變數不同於其他型別,會被初始化為空字串。

字串的常數

字串常數以雙引號 " 作為起始與結束。
例如 "Hello World!\n" 就是一個字串常數。

補充:用 "" 可以代表空字串。

字串的賦值

字串可以直接被賦值,但賦值的對象必須同樣是個字串。
例如以下程式碼:

1
2
3
string str, ntr;
str = "Fxck";
ntr = str;

也可以在宣告時初始化,例如:

1
string str = "shxt";

字串的輸入

字串型別同樣可直接透過 cin 輸入:

1
2
3
string str;
cin >> str;
cout << "Received string: " << str << '\n';

一個慣用技巧是:在字串的前後輸出中括號之類容易分辨的文字夾起來,
就能夠確認字串頭尾難以目視的空白、tab 或換行等空白字元。

1
2
3
4
5
string s;
while (cin >> s)
{
cout << "[" << s << "] received.\n";
}

試著輸入一些文字,夾雜各種符號或空白、換行等,觀察看看:

  • 哪裡到哪裡,會被認成一個字串?
  • 遇到哪些字元會被斷開?
  • 能斷開的那些字元,會不會被收錄到輸入的字串中?

以行為單位的輸入 getline

內建的另一種字串輸入方式 getline() 則提供了以「行」為單位的輸入方式。

getline() 需要提供輸入的來源、以及存放字串的容器,
呼叫後便會輸入完整的一行,不會被空白字元截斷。

1
2
3
string s;
getline(cin, s); // 輸入來自 cin,讀到的字串存放至 s
cout << s << '\n';

即使有連續的換行字元出現,也會視為是「空白行」而不會一口氣跳過。
為了方便測試,同樣可以使用多重輸入,並在前後加中括號以便辨識:

1
2
3
4
5
6
7
8
string s;
while (getline(cin, s))
{
cout << "[" << s << "] received.\n";
}

直接用 cin 時會跳過的空白字元,被收入至輸入的字串中了。
另外,儘管下一個換行字元會被 getline() 吃掉,但不會被記錄至輸入的字串中。

getline 與行尾

考慮輸入是先有一個整數,接下來有一行文字時,
例如以下:

1
2
7
Alice Margatroid

很直覺地,會這樣輸入:

1
2
cin >> n;
getline(cin, s);

實際測試輸出 s 的內容看看,會發現 s 是個空字串,並未正確讀到第二行。
這是怎麼回事呢?

字串的長度

字串長度可在字串變數之後加上 .size() 取得。

1
2
3
4
string s, t;
cin >> s >> t;
cout << "s has length: " << s.size();
cout << ", t has length: " << t.size() << '\n';

常見符號必懂 不懂要懂!

1
2
+  -  *  /  %         &&   ||    !        > < >= = == <=
加 減 乘 除 取餘數 and or 不等於 (後面的應該沒問題)

常見函數

1
2
3
4
5
6
7
8
9
10
11
12
13
14
stoi(); 或 atoi(); //string轉int
sort(); //排序陣列中的值 (小到大)
變數.size(); //求字串變數大小
max(a,b); //求a和b其中的最大值
min(a,b); //求a和b其中的最小值
swap(a,b); //交換a和b的值
pow(a,b); //求指數 a為底 b為指
sqrt(a); //回傳a的開平方
islower(a); //字元a是否為小寫 是的話回傳1 反之回傳0
__gcd(a,b); //回傳a和b的最大公因數
abs(a) //a的絕對值
reverse(a,b); //反轉
lower_bound(a,b,c); //a到b中第一個 大於等於 c的元素的位置
upper_bound(a,b,c); //a到b中第一個 大於   c的元素的位置

無營利 僅供分享 若有侵權 煩請告知
以上內容部分參考emanlaicepsa

觀念題題庫

https://apcs.csie.ntnu.edu.tw/wp-content/uploads/2022/10/%E8%A7%80%E5%BF%B5%E9%A1%8C_%E9%A1%8C%E5%9E%8B%E7%AF%84%E4%BE%8B.pdf

如果有不會的 午休時間我在資訊教室!