C++
工具介紹
C++ 基本格式
#include <iostream>
using namespace std;
int main(){
cout << "Hello Jinkela!\n";
return 0;
}
函數庫
#include <iostream>
using namespace std;
int main(){
cout << "Hello Jinkela!\n";
return 0;
}
命名空間
#include <iostream>
using namespace std;
int main(){
cout << "Hello Jinkela!\n";
return 0;
}
cout
- C++ 常用輸出工具
- 把資訊印到螢幕上
- #include <iostream>
程式碼
螢幕
a = 7122
b = 7122712271227122
c = Jinkela
d = 0.7122
7122Jinkela7122
#include <iostream>
using namespace std;
int main(){
int a = 7122;
long long b = 7122712271227122;
char c[100] = "Jinkela";
double d = 0.7122;
cout << "a = " << a << '\n';
cout << "b = " << b << endl;
cout << "c = " << c << '\n';
cout << "d = " << d << '\n';
cout << a << c << 7122 << '\n';
return 0;
}
endl
- cout 專用的換行
- 比賽來說建議用 '\n' 取代
cin
- C++ 最常使用的輸入工具
- 把你用鍵盤打的東西存到變數中
- 以空白,換行當作分割
- #include <iostream>
做個小實驗
#include <iostream>
using namespace std;
int main(){
int a;
long long b;
char c[100];
double d;
cin >> a >> b >> c >> d;
cout << "a = " << a << '\n';
cout << "b = " << b << endl;
cout << "c = " << c << '\n';
cout << "d = " << d << '\n';
cout << a << c << 7122 << '\n';
return 0;
}
常見錯誤
#include <iostream>
using namespace std;
int main(){
int a, b;
cin << a, b; // 這樣編譯會過!!
cout << a << ' ' << b << '\n';
return 0;
}
輸入輸出加速
- C++ 輸入輸出比C還要慢
- 有一些手段可以加速
- 但有一些限制
#include <iostream>
using namespace std;
int main(){
// 在main開頭加上這兩行,debug時建議拿掉
ios_base::sync_with_stdio(false); // 加了這行scanf/printf會壞掉
cin.tie(0); // 加了這行就不要用 endl
return 0;
}
C++ 字串
string
string
- C++ 專用字串
- 比C的char陣列好用
- #include <string>
string 基本操作
#include <iostream>
#include <string>
using namespace std;
int main(){
string a = "abc7122";
cout << a.size() << ' ' << a << '\n';
for(size_t i = 0; i < a.size(); ++i){
a[i] = 'j';
}
cout << a << '\n';
char c[100] = "Jinkela";
a = c;
cout << a << '\n';
return 0;
}
string 加法
#include <iostream>
#include <string>
using namespace std;
int main(){
string a = "aa";
string b = "bb";
a += b;
cout << a << '\n';
a += a + b;
cout << a << '\n';
a.pop_back();
cout << a << '\n';
return 0;
}
string 輸入
#include <iostream>
#include <string>
using namespace std;
int main(){
string a, b;
cin >> a >> b;
cout << a + b << '\n';
return 0;
}
string 比較: 字典序
#include <iostream>
#include <string>
using namespace std;
int cmp(string a, string b){
size_t len = a.size() < b.size() ? a.size() : b.size();
for (size_t i = 0; i < len; ++i){
if(a[i] == b[i]) continue;
return a[i] < b[i] ? -1 : 1;
}
if (a.size() == b.size()) return 0;
return a.size() < b.size() ? -1 : 1;
}
int main(){
string a, b;
while(cin >> a >> b){
cout << cmp(a, b);
if (a < b) cout << " <\n"; // -1
if (a == b) cout << " ==\n"; // 0
if (a > b) cout << " >\n"; // 1
}
return 0;
}
string 轉成 c字元陣列
#include <cstdio>
// stdio.h
#include <string>
using namespace std;
int main(){
string s = "aaa7122";
printf("%s\n", s.c_str());
return 0;
}
整行輸入
getling
getline
- #include <iostream>
- getline(cin, 變數(必須是string))
#include <iostream>
#include <string>
using namespace std;
int main(){
string s;
getline(cin, s);
cout << s << '\n';
return 0;
}
輸出輸入重導向
a.out的code
螢幕
小實驗
#include <iostream>
#include <string>
using namespace std;
int main(){
cout << "Please input: ";
string s;
getline(cin, s);
cout << "Your input: ";
cout << s << '\n';
return 0;
}
Please input: aaa ssss
Your input: aaa ssss
input.txt
螢幕
檔案輸入
Please input:
Your input: aaa ssss
aaa ssss
- ./a.out < input.txt
螢幕
output.txt
檔案輸出
Please input:
Your input: GGGGGGG GGG
GGGGGGG GGG
- ./a.out > output.txt
input.txt
output.txt
檔案輸入輸出
Please input:
Your input: aaa ssss
aaa ssss
- ./a.out < input.txt > output.txt
連續輸入
通常題目會這樣的描述
- 輸入有多筆測資
- 請輸入到EOF為止
- (中英都要能看懂)
EOF (end of file)
- 讀到檔案結束時會觸發EOF事件
- cin , getline在遇到EOF時會回傳false
- 用鍵盤輸入製造EOF
- windows: Ctrl + Z
- Linux: Ctrl + D
輸入範例
輸入有多筆。
每比第一行有一個數字\(n\),接下來有\(n\)行,每行有兩個浮點數x, y
適合的code
#include <iostream>
using namespace std;
int main(){
int n;
while(cin >> n){
for(int i = 0; i < n; ++i){
double x, y;
cin >> x >> y;
}
}
return 0;
}
從字串輸入
sscanf
stringstream
sscanf
- #include <cstdio>
- sscanf(字元陣列, 後面和 scanf 一樣)
- 格式化輸入
#include <iostream>
#include <cstdio>
#include <string>
using namespace std;
int main(){
string s;
getline(cin, s); // input: (123,456)
int x, y;
sscanf(s.c_str(), "(%d,%d)", &x, &y);
cout << x << ' ' << y << '\n'; // output: 123 456
return 0;
}
stringstream
- #include <sstream>
- 把字串作為輸入
#include <iostream>
#include <sstream>
#include <string>
using namespace std;
int main(){
string str;
getline(cin, str);
stringstream ss(str);
int a;
while(ss >> a){
cout << a << '\n';
}
return 0;
}
getchar()
scanf("%c")
初學者不建議使用(參閱例題)
double or float?
比賽時千萬不要用float
小實驗
#include <iostream>
using namespace std;
template<typename T>
void test(){
T a = 1.0 / 81;
T b = 0;
for(int i = 0; i < 729; ++ i)
b += a;
cout << b << '\n'; // (729/81) = 9
}
int main(){
test<float>(); // prints 9.00002
test<double>(); // prints 9
return 0;
}
double小數點輸出
- 輸出到小數點後第k位(四捨五入)
- #include <iomanip>
#include <iostream>
#include <iomanip>
using namespace std;
int main(){
int k = 3; // 輸出到小數點後第3位
cout << fixed << setprecision(k);
cout << 0.7122 << '\n';
double pi = 3.14159265358979;
cout << pi << ' ' << pi*pi << '\n';
return 0;
}
C++ 特殊技巧
auto
- auto變數定義時會自動判斷自己的型別
#include <iostream>
using namespace std;
string f(){
return "Jinkela";
}
int main(){
auto a = 7122; // int
auto b = 2147483647122;// long long
auto c = "7122"; // const char*
auto d = f(); // string
cout << a << ' ' << b << ' ' << c << '\n';
cout << d << '\n';
return 0;
}
錯誤用法
- auto不是這樣用的
#include <iostream>
using namespace std;
int main(){
auto a = 7122; // int
a = 7123;
a -= 1;
a = "aaaaaa"; // error
return 0;
}
Range-based for
- for(型態 變數 : 範圍)
#include <iostream>
using namespace std;
int main(){
for(int n : {1,2,3,4,5}){
cout << n << ' ';
}
cout << '\n';
int a[10] = {1,2,3,4,5};
for(int n : a){
cout << n << ' ';
}
cout << '\n';
return 0;
}
reference(c++ 98)
- C要做到同樣功能的話需要指標
#include <iostream>
using namespace std;
int main(){
int a = 5;
int &b = a;
b += 1;
cout << a << '\n';
int c[10] = {1,2,3};
for(auto &i : c){
i += 7122;
}
for(auto i : c){
cout << i << ' ';
}
cout << '\n';
return 0;
}
常見錯誤
行尾空白
直接輸出在螢幕上看不出來
#include <iostream>
using namespace std;
int main(){
int a[] = {1,2,3,4,5};
for(int x : a){
cout << x << ' ';
}
cout << '\n';
return 0;
}
建議處理方式
#include <iostream>
using namespace std;
int main(){
int a[] = {1,2,3,4,5};
bool use = false;
for(int x : a){
if(use) cout << ' ';
use = true;
cout << x;
}
cout << '\n';
return 0;
}
建議處理方式2
#include <iostream>
using namespace std;
int main(){
int a[] = {1,2,3,4,5};
for(int x : a){
static bool use = false;
if(use) cout << ' ';
use = true;
cout << x;
}
cout << '\n';
return 0;
}
炫技處理方式
#include <iostream>
using namespace std;
int main(){
int a[] = {1,2,3,4,5};
for(int i = 0; i < 5; ++i){
cout << a[i] << " \n"[i==4];
}
return 0;
}
萬能標頭黨
<bits/stdc++.h>
萬能標頭黨
- 一口氣把所有常用的功能include
- 解題時很好用(背起來),但開發大型專案時不要用
#include<bits/stdc++.h>
using namespace std;
int main(){
int a;
cin >> a;
cout << a * a << '\n';
scanf("%d", &a);
printf("%d\n", max(a, 1));
return 0;
}
例題
地圖翻轉問題
- 給你一張由字元組成的地圖,請你將他翻轉
- 輸入第一行有兩個數字\(n, m, (n,m\le 10^3)\)
接下來有\(n\)行,每行有\(m\)個以空白隔開的字元,表示地圖 - 請你將地圖翻轉後輸出
範例輸入
範例輸出
4 5
% A B C D
H K J L L
* 5 6 * 7
l s d / ?
% H * l
A K 5 s
B J 6 d
C L * /
D L 7 ?
answer (C)
#include <stdio.h>
char s[1005][1005];
int main(){
int n,m;
scanf("%d%d", &n, &m);
for(int i = 0; i < n; ++i){
for(int j = 0; j < m; ++j){
char buff[2];
scanf("%s", buff); //這裡用getchar或 %c 都容易壞掉
s[i][j] = buff[0];
}
}
for(int j = 0; j < m; ++j){
for(int i = 0; i < n; ++i){
if(i != 0) putchar(' ');
printf("%c",s[i][j]);
}
puts("");
}
return 0;
}
answer (C++)
#include <bits/stdc++.h>
using namespace std;
char s[1005][1005];
int main(){
int n,m;
cin >> n >> m;
for(int i = 0; i < n; ++i){
for(int j = 0; j < m; ++j){
cin >> s[i][j];
}
}
for(int j = 0; j < m; ++j){
for(int i = 0; i < n; ++i){
cout << s[i][j] << " \n"[i==n-1];
}
}
return 0;
}
地圖翻轉問題2
- 給你一張由字元組成的地圖,請你將他翻轉
- 輸入第一行有兩個數字\(n, m, (n,m\le 10^3)\)
接下來有\(n\)行,每行有\(m\)個字元,表示地圖 - 請你將地圖翻轉後輸出
範例輸入
範例輸出
4 5
%ABCD
HKJLL
*56*7
lsd/?
%H*l
AK5s
BJ6d
CL*/
DL7?
answer (C)
#include <stdio.h>
char s[1005][1005];
int main(){
int n,m;
scanf("%d%d", &n, &m);
for(int i = 0; i < n; ++i){
scanf("%s", s[i]);
}
for(int j = 0; j < m; ++j){
for(int i = 0; i < n; ++i){
printf("%c",s[i][j]);
}
puts("");
}
return 0;
}
answer (C++)
#include <bits/stdc++.h>
using namespace std;
char s[1005][1005];
int main(){
int n,m;
cin >> n >> m;
for(int i = 0; i < n; ++i){
cin >> s[i];
}
for(int j = 0; j < m; ++j){
for(int i = 0; i < n; ++i){
cout << s[i][j];
}
cout << '\n';
}
return 0;
}
進階字串反轉
- 第一行有一個數字\(n, n\le 10^5\)
- 接下來有\(n\)行,每行有一些以空白分隔的字串
- 一行最多有\(10^5\)個字元
- 對於每一行
請你將這些字串反轉後去掉空白然後輸出
範例輸入
範例輸出
4
asdf dfgh adfgdfa fhgdf sfs dfsd
a_a b_b_ ccdd
abcd 1234 a1b2c3d4
jinkela Jinkela
fdsahgfdafdgfdafdghfsfsdsfd
abcda_a_b_bddcc
dcba43214d3c2b1a
aleknijalekniJ
answer(C++)
#include <bits/stdc++.h>
using namespace std;
int main(){
string buff;
getline(cin, buff);
stringstream ss(buff);
int n;
ss >> n; // 直接用cin 會出問題
while(n--){
getline(cin, buff);
stringstream ss(buff);
string tmp;
while(ss >> tmp){
for(int i=tmp.size()-1; i>=0; --i)
cout << tmp[i];
}
cout << '\n';
}
return 0;
}
C++競賽技巧
By jacky860226
C++競賽技巧
- 592