## 第六堂社課
---
## 複習
----
## 字元
根據 ASCII 碼,我們可以對字元做簡單的運算
```cpp=
#include<iostream>
using namespace std;
int main(){
char a='a',b='b',c='1',d='d',e='e',f='f';
int C=c-'0';
cout<<a-b<<endl;//-1
cout<<C<<endl;//1
cout<<int(d)<<endl;//100
cout<<(e>f)<<endl;//0
}
```
----
## `cctype` 函式
`isalpha()` : 是否為字母
`isupper()` : 是否為大寫字母
`islower()` : 是否為小寫字母
`isdigit()` : 是否為數字
`isalnum()` : 是否為數字或字母
`isspace()` : 是否為空格 ' '
`isblank()` : 是否為空格 ' ' 或 '\t'
`toupper()` : 將字元從小寫轉換成大寫的 ASCII
`tolower()` : 將字元從大寫轉換成小寫的 ASCII
----
## C++ `std::string`
```cpp=
#include<iostream>
#include<string>
using namespace std;
int main(){
// std::string 的宣告與定義
string a="Xiaochengyi";
string b("Kaikai");
// std::string 的改變
b[3]='K';
a.at(0)='x';
// std::string 的引用
cout<<a[0];
cout<<b.at(1);
cout<<a;
}
```
----
## C++ ```std::string``` 的基礎操作
`push_back()` : 在字串的最後新增元素
`insert()` : 在指定位置插入元素
`pop_back()` : 刪除陣列最後方的元素
`erase()` : 刪除指定位置或指定記憶體區間的元素
`clear()` : 清空字串
`size()` : 讀取字串長度
`length()` : 讀取字串長度
`resize()` : 調整陣列長度
`empty()` : 讀取字串是否為空
----
## C++ ```std::string``` 的基礎操作
`append()` : 將兩字串相加
`getline()` : 讀取整行字串
`find()` : 尋找子字串
`substr()` : 擷取子字串
----
## 變數的域
變數的作用是有範圍的,主要是以大括號 `{}` 為分界
```cpp=
#include<iostream>
using namespace std;
int a=0;// 全域變數
int main(){
cout<<a;// 0
int a=1;// 區域變數
{
cout<<a;// 1
int a=2;// 區域變數
{
cout<<a;// 2
int a=3;// 區域變數
cout<<a;// 3
}
cout<<a;// 2
}
cout<<a;// 1
}
```
----
## 函式的宣告、定義、引用
## 以及函式參數的使用
```cpp=
#include<iostream>
using namespace std;
// 函式的宣告
int myPlus(int a,int b);// 函式的宣告先於函式的引用
int main(){
int x=1,y=2;
// 函式的引用: 因為函式是 int 型態的,所以我們把它當作一個 int 型態的變數使用,故可以輸出
cout<<myPlus(x,y)<<endl;
}
// 函式的定義
int myPlus(int a,int b){
return a+b;
}
```
----
## 遞迴
在函式中呼叫函式,直到達到某特定效果後回傳
```cpp=
#include<iostream>
using namespace std;
int Fib(int n){
if(n==0)return 0;
if(n==1)return 1;
return Fib(n-1)+Fib(n-2);
}
int main(){
int n;
cin>>n;
cout<<Fib(n)<<endl;
}
```
---
## 競賽程式編程技巧
----
## 萬用標頭檔 `bits/stdc++.h`
`bits/stdc++.h` 內有所有 `C++` 標準函式庫,但在某些編譯器中無法使用,所以還是要稍微記一下各種標頭檔的名稱
----
## 不使用萬用標頭檔
當你要寫一個很複雜的程式,你可能要打那麼多字
```cpp=
#include<iostream>
#include<algorithm>
#include<vector>
#include<cctype>
#include<string>
#include<deque>
#include<queue>
#include<map>
#include<set>
#include<cstdlib>
#include<stdio.h>
#include<limits.h>
#include<ctime>
#include<iomanip>
```
----
## 使用萬用標頭檔
只需要一行,而且不影響執行時間
```cpp=
#include<bits/stdc++.h>
```
----
## 節省輸入輸出時間
在程式競賽中,執行時間是一個很重要的事情。很多時候都會因為跑太久被 `TLE` 。除了考慮是個人語法不夠精確(暴力解)的問題以外,我們也可以針對幾個點去做優化
----
## 輸入輸出優化方法
我們可以使用 C 語言中的 `scanf()` 以及 `printf()` 讓輸入輸出的時間優化。但是這個方法因為過於麻煩,且使用到了指標的概念,這邊只簡單介紹帶過
----
## 輸入輸出優化方法
我們可以透過關閉 `C++` 與 `C` 語言輸入輸出流的同步以及解除 `cin` 與 `cout` 之間的綁定以加快輸入輸出的效率(這段文字不用理解,反正用就對了)
```cpp=
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
```
----
## 輸入輸出優化方法
我們在輸出時,可以儘量避免使用 `endl` 而改使用 `'\n'` 以增快輸出速度
```cpp
#include<bits/stdc++.h>
using namespace std;
int main(){
for(int i=0;i<10;i++)cout<<i<<'\n';
cout<<"apple\nbanana\ncandy";
}
```
----
## 文字替換 `#define`
當有時候覺得某些程式碼很長懶得打,可以使用 `#define` 簡化。如果你高興,也可以把一串程式碼弄到沒人看得懂在寫什麼
----
## 範例(天書)
```cpp=
#include<bits/stdc++.h>
#define Hello using
#define World namespace
#define XD std
#define QQ int
#define QQQ main
#define QQQQ cin
#define QQQQQ >>
#define QQQQQQ <<
#define QQQQQQQ cout
#define Xiaochengyi ;
#define kaikai signed
#define Darrenw1004 '\n'
Hello World XD Xiaochengyi
kaikai QQQ (){
QQ Q Xiaochengyi
QQQQ QQQQQ Q Xiaochengyi
QQQQQQQ QQQQQQ Q QQQQQQ Darrenw1004 Xiaochengyi
}
```
##### ~~如果哪天想要搞人,可以寫一個這樣的東西,疊一大堆不會用到的 #define ,然後中間弄一個錯去讓他 debug ,保證他會很高興~~~
----
## 範例(正常情況)
```cpp=
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define N 10
int main(){
ll a;
ll b[N];
cin>>a;
cout<<a+1<<'\n';
}
```
----
## 型別別名 `using`
除了 `define` ,我們也可以用 `using` 來給程式碼改名。
----
## 範例(正常情況)
```cpp=
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
int main(){
ll a;
cin>>a;
cout<<a+1<<'\n';
}
```
----
## `using` 與 `#define` 的差別
這兩者其實差別挺多的,而主流認為 `using` 比 `#define` 好用得多,主要原因在於`using` 可以只在固定域使用,而 `#define`則是全域的,可能會影響整個程式碼的運行。而在某些情況, `#define` 會造成指標變數定義上的 bug ,因此比較推薦使用 `using`
----
## 固定值的變數 `const`
當有一個變數可能是固定的,但是在做測試時可能會需要頻繁變更,就可以使用 `const` 來固定某值,使其無法被改變
----
## 範例
```cpp=
#include<bits/stdc++.h>
using namespace std;
const int N=10;
int main(){
int a[N];
for(int i=0;i<N;i++){
cin>>a[i];
if(a[i]>N)cout<<"true";
else cout<<"false";
cout<<'\n';
}
}
```
----
## 長整數 `long long`
在某些題目中,他給予的值範圍可能會很大,因此我們需要使用 `long long` 來做為儲存變數的容器
----
## 獲取 `ASCII` 碼
如果你在寫題目時,突然忘記 `'A'` 的 `ASCII` 碼是 `65`或類似的情況,你就可以用強制轉型的方法將其輸出出來
----
## 範例
```cpp=
#include<bits/stdc++.h>
using namespace std;
int main(){
cout<<int('A');
}
```
----
## 字元數字轉換為整數數字
有時候題目中的數字會連著字母或符號輸入而儲存成字元型態,那麼當我們需要讀取那個數字時,就需要把它轉換成數字。而最簡單的方法就是直接 `-'0'`
----
## 範例
```cpp=
#include<bits/stdc++.h>
using namespace std;
int main(){
string a="1B";
int x=a.at(0)-'0';
cout<<x+2<<endl;
}
```
----
## 大數輸入
有時候題目的輸入可能是一串沒有空格數字,而這些數字往往會需要以陣列的形式處理。但因為在各個輸入的數字之間沒有空格的情況下,輸入串流會判斷他是同一個數字而不是好幾個不同的數字,因此我們需要一些方法讓他變成一個陣列
----
## 大數直接轉陣列
先將那一串數字儲存為一個大數,再轉換成陣列
```cpp=
#include<bits/stdc++.h>
using namespace std;
using ll=long long;
int main(){
ll a;
vector<int>b;
cin>>a;
while(a!=0){
b.insert(b.begin(),a%10);
a/=10;
}
}
```
但這個寫法不適用 `0` 出現在零出現在前面的大數
----
## 字串轉陣列
我們可以先把大數輸入成字串,再轉換成陣列
```cpp=
#include<bits/stdc++.h>
using namespace std;
int main(){
string a;
vector<int>b;
cin>>a;
for(int i=0;i<a.length();i++)b.push_back(a.at(i)-'0');
}
```
這個寫法基本上適用任何情況
---
## 競賽程式解題技巧
----
## 題目敘述
在讀題時,可以忽略那些沒有意義的文字,就像是考段考一樣,可以忽略一些劇情的部分。但是競賽程式的題目都是素養導向,所以很多細節可能也會藏在故事情節裡面,所以沒有注意也容易會被晃一波。而這邊特別建議去看條列式和標粗的部分,因為會特別條列出來的都是重點或者是程式邏輯規則。
----
## 輸入格式與範例
輸入範例是競程裡面最需要細讀的部分,特別要注意它需要輸入什麼、輸入多少個數字以及輸入數字的大小。個人特別建議變數、函式名稱都按照題目給的取名,不然到後面 `debug` 的時候很容易全部亂掉。而如果還沒有解題思路,可以先試著把輸入的部分寫一寫
----
## 輸出格式與範例
輸出範例則主要要關注他的輸出格式。絕對不要覺得這些格式沒什麼,因為在某些考試中,多一個空格都可能算錯。所以輸出格式一定要仔細認真的去研究,以免最後 `debug` 了半天才發現是輸出錯誤導致的 `NA` 或 `WA`
----
## 評分說明
評分說明看似是整份題目最沒用的部分,但實則是最重要的部分。當你在對這整個大題還沒有思路時,可以先嘗試把各個子題目解出來,也會有一定的分數可以拿,而且可以增加你對題目的理解度,以尋找解出整個題目的思路
----
## 題目範例
https://apcs.csie.ntnu.edu.tw/wp-content/uploads/2025/08/01_APCS-%E7%A8%8B%E5%BC%8F%E5%AF%A6%E4%BD%9C%E5%88%9D%E7%B4%9A%E9%A1%8C%E6%9C%AC%E7%AF%84%E4%BE%8B.pdf
----
## 程式架構
程式架構以自己習慣的為主。平常可以先訓練把自己常用的寫法記憶起來,到考試現場把那套自己設計的模板先儲存成一個檔案,之後要用直接複製一個檔案來用就好了
----
## 範例
```cpp=
#include<bits/stdc++.h>
using namespace std;
using ll=long long;
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
//後面就可以打程式碼了
}
```
----
## 註釋
幾乎沒有人喜歡打註釋,但是也沒有人喜歡沒有註釋的程式。為了防止自己寫完的程式只剩下神才看得懂,你可以在寫完程式後加上註釋來解釋邏輯在哪裡,後面 `debug` 時會比較快。當然,如果你打字沒那麼快,還是別浪費時間在打註釋上了。
----
## 在變數中找出問題
APCS 提供的 IDE debug 功能很難用,沒辦法讓使用者從後台查看變數變化情況。所以如果我們想要知道程式碼可能是在哪裡出現問題的時候,可以透過直接輸出來查看變數變化,以找到問題點並加以改善。而在提交檔案的時候把那幾行註釋掉即可。
---
## 測驗時間(40 分鐘)
總共有五題共1000分,依照難度分配分數,達到250分及格,破台絕對是電神。可以先把所有題目都讀一遍,挑自己拿手的題目來寫。可以參考之前社課的講義,但請不要使用 AI ,後臺其實看得出來~
加油!!!
{"title":"第六堂社課","description":"根據 ASCII 碼,我們可以對字元做簡單的運算","contributors":"[{\"id\":\"79e95694-48b2-4fa4-828c-ba3fc7802f72\",\"add\":19774,\"del\":12560,\"latestUpdatedAt\":1767274191374}]"}