hoge.ccをコンパイルして実行するなら,
- g++ hoge.cc
- ./a.exe
実行ファイル名を変えたいなら,
- g++ hoge.cc -o fuga.exe
- ./fuga.exe
最適化オプションとかつけるなら
- g++ hoge.cc -O2
とか.
- g++ --help
でいろいろ見られる.
行コメントとブロックコメントがある.
- int a; //これはコメント
- int b;
- /*
- ここはコメント
- */
- int c;
的な.
- #include <iostream>
- #define rep(i, n) for(int i = 0; i < (n); ++i)
- using namespace std;
- typedef long long ll;
とか, その他もろもろ.
#includeはお馴染みの, 標準ライブラリをロードするやつ.
Cのstdio.hとかmath.hとかも#include <stdio.h>とかでinclude出来る.
#include <cstdio>とかcを先頭につけても良い.
includeして使わないというのは別に問題ないので, プロコンでは最初に30個くらいincludeしてる人とか多い.
日本語では名前空間とか言う.
これから出てくるcinとかcoutとか, その他様々なやつはstdというnamespaceに入っている.
本当はstd::cinとか, std::coutとかいちいち書かなければならないのを, using namespace std; することで省略できる.
Cと同じように, マクロが使える.
慣れるとおいしい.
最初はあんまり気にしなくていいけど, 他の人のソースを読むのに理解する必要がある.
型のエイリアス的な.
上の例では, long long 型を, llで使えるようにする.
C言語と同じように, いろいろな型がある.
C言語と同様, 型名 変数名 で変数宣言する.
C言語と違い, 割とどこでも変数宣言できる.
- int a = 0, b = 1;
- double p = 3.14;
- string s = "hoge";
- int arr[10] = {0, 1, 2, 3};
- arr[4] = 4;
- if(a == 0) b *= 2;
- int d = 0;
型& 名前 = 同じ型の別の変数; で宣言すると, エイリアスを作ることが出来る.
これのおかげで, あんまりポインタ使わなくてもよい感じになっている.(関数の項でもちょっと出てくる)
- int a = 0;
- int& b = a;
- b = 10; //aも10になる
- a = 2; //bも2になる
詳しくは, C++ 参照 でググるとよいです.
cinとcoutで大体なんとかなる.
多分console input/outputの略.
cstdioをincludeすればprintfとかscanfも使える.
- int a, b;
- string s;
- char c;
- cin >> a >> b >> s >> c;
- cout << a*b << ", " << b << endl << s << endl;
cin は >> という演算子を再定義していて, cin >> hoge とやると, hoge の型にあわせて読み込み, hogeに入れてくれる.
さらに, cinはcin自体を返すので, cin >> hoge >> fugaとやると, hoge のあとに fuga に入力する.
空白と改行区切りでパースされるので, 一行全体を取得したいとかいう場合は,
- string s;
- getline(cin, s);
とかで.
coutも, 変数の型によって適当に出力してくれる.
endlは改行. 多分 end line だと思う.
このへんは std 内なので, using namespace std をしていないなら, std::cout << a << std::endl とかする.
doubleとかを出力する時は精度がよろしくないので,
- cout.setf(ios::fixed);
- cout.precision(10);
とかする.
基本的にC言語と同じ.
比較は ==, !=, <=, >=, >, <.
and, orは &&, ||
- if(a != 0 && b != 0) cout << "a*b != 0" << endl;
- if(a == 0 || b == 0) cout << "a*b = 0" << endl;
int, longなどの整数型は, 0の場合は偽, それ以外は真とみなされる.
- if(a) cout << "a != 0" << endl;
- a = !(!a) // aは0ならそのまま, それ以外なら1になる.
一行の時は, ブレース(波ガッコ:{})は付けても付けなくてもよい.
- if(a == 0) cout << "a equals to zero" << endl;
- else if(a == 1) {
- cout << "a equals to one" << endl;
- } else
- cout << "a*a != a" << endl;
Cと同じ.
あんまり使わない.
breakを忘れずに.
charとか整数とかで使える.
- int a, b, res;
- char c;
- cin >> a >> c >> b;
- switch(c){
- case '+':
- res = a + b;
- break;
- case '-':
- res = a - b;
- break;
- case '*':
- res = a * b;
- break;
- case '/':
- res = a / b;
- break;
- default:
- res = 0;
- break;
- }
- cout << res << endl;
Cと同じ.
ただし, forの最初の処理のところで変数宣言とか出来る.
一行の時は, ブレース(波ガッコ:{})は付けても付けなくてもよい.
- for(int i = 0; i < 10; ++i){
- cout << i << endl;
- }
- for(int i = 0; i < 10; ++i){
- if(i) cout << ", ";
- cout << i;
- }
- cout << endl;
2つ目のはイディオムで, 間にスペースとかカンマとかを入れて出力したい時とかに使われる.
(iが0の時以外, cout << ", "; が実行される.)
Cと同じ.
- int n;
- cin >> n;
- while(n){
- cout << n << endl;
- --n;
- }
- do{
- cout << n << endl;
- --n;
- }while(n >= 0);
どちらもnから1を表示する.
do-while(後置while)は,
- int n;
- do{
- cin >> n;
- }while(n % 2 != 0);
のように, 最初の一回は必ず実行されて欲しい時に使う.
上の場合, 偶数が入力されるまで入力させ続ける.
大体はC言語と同じ.
- int gcd(int a, int b){
- if(b == 0) return a;
- return gcd(b, a%b);
- }
C言語で, gcdとlcmを一気に計算したいとか思ったら, ポインタを使って
- void gcdlcm(int a, int b, int* g, int* l){
- int ab = a * b;
- while(b != 0){
- a %= b;
- swap(a, b);
- }
- *g = a;
- *l = ab / *g;
- }
とかやるが, C++で参照を使うと, 次のように書ける.
- void gcdlcm(int a, int b, int& g, int& l){
- int ab = a * b;
- while(b != 0){
- a %= b;
- swap(a, b);
- }
- g = a;
- l = ab / g;
- }
英語ではオペレータのオーバーロードとか言う.
C++ 演算子 オーバーロード とかでググるとよい.
自分で作ったクラスで, a + b とかが出来るようになる.
更に, 入出力が cin >> a とかで出来るように作れる.
また, set や map のキーにする時は, 比較演算子を再定義する必要がある.
リンクのProgramming Placeとか見ると良い.
例えば, 絶対値を返す, my_absという関数を作りたいとする.
- int my_abs(int n){ return n > 0 ? n : -n; }
しかし, 数値の型はintだけじゃないわけで,
- double my_abs(double n){ return n > 0 ? n : -n; }
とかも要るだろうし, 他にもまだまだあるんじゃないかという感じである.
こういうのを解決したのがテンプレート.
上の例だと,
- template<class T> T my_abs(T n){ return n > 0 ? n : -n; }
で, my_abs(-1.5) とかやると, Tにdoubleが代入されたやつが実行される.
template<class T> でなく, template<typename T> でもよい.
- template<typename T, typename U> U add(T a, T b){
- U au = a, bu = b;
- return au + bu;
- }
みたいに, 複数の型を使ったりしてもよい.
明示的には, add<int, long>(1, 2) とかで呼び出す.
例えば二次元ベクトルを扱いたいけど, 要素が整数なのか実数なのかは後で決めたいみたいな.
- <class T>
- class Vec{
- T x, y;
- Vec(T xx, T yy){ x = xx; y = yy; }
- Vec add(Vec other){
- return Vec(x + other.x, y + other.y);
- }
- };
- int main(void){
- Vec<int> a(0, 1), b(1, 0);
- Vec<int> c = a.add(b);
- }
みたいな感じで使う.
注意すべきなのは,
- Vec<Vec<int>> matrix;
とかやると, Vec<Vec<int>> の >> を右シフトとして捉えてしまい, コンパイルエラーが起きる事.
- Vec<Vec<int> > matrix;
と, スペースを開けましょう.
ここ.
C++ hoge 的なググり方をするとよく引っかかるサイト.
ここ.
演算子の再定義ってどうやるんだっけとか, 何を再定義できるんだっけとか, ちょっとマニアックなのが載ってる.
ここ.
関数名が思い出せない時とか便利.
ここ.
詳しい. 便利.