競技プログラミング? > C++


別ページにあるもの


このページにあるもの


コンパイルとか

hoge.ccをコンパイルして実行するなら,

  1. g++ hoge.cc
  2. ./a.exe

実行ファイル名を変えたいなら,

  1. g++ hoge.cc -o fuga.exe
  2. ./fuga.exe

最適化オプションとかつけるなら

  1. g++ hoge.cc -O2

とか.

  1. g++ --help

でいろいろ見られる.


コメント

行コメントとブロックコメントがある.

  1. int a; //これはコメント
  2. int b;
  3. /*
  4.  ここはコメント
  5.  */
  6. int c;

的な.


おまじない

  1. #include <iostream>
  2. #define rep(i, n) for(int i = 0; i < (n); ++i)
  3. using namespace std;
  4. typedef long long ll;

とか, その他もろもろ.

include

#includeはお馴染みの, 標準ライブラリをロードするやつ.
Cのstdio.hとかmath.hとかも#include <stdio.h>とかでinclude出来る.
#include <cstdio>とかcを先頭につけても良い.
includeして使わないというのは別に問題ないので, プロコンでは最初に30個くらいincludeしてる人とか多い.

namespace

日本語では名前空間とか言う.
これから出てくるcinとかcoutとか, その他様々なやつはstdというnamespaceに入っている.
本当はstd::cinとか, std::coutとかいちいち書かなければならないのを, using namespace std; することで省略できる.

define

Cと同じように, マクロが使える.
慣れるとおいしい.
最初はあんまり気にしなくていいけど, 他の人のソースを読むのに理解する必要がある.

typedef

型のエイリアス的な.
上の例では, long long 型を, llで使えるようにする.


型と変数宣言

C言語と同じように, いろいろな型がある.
C言語と同様, 型名 変数名 で変数宣言する.
C言語と違い, 割とどこでも変数宣言できる.

  1. int a = 0, b = 1;
  2. double p = 3.14;
  3. string s = "hoge";
  4. int arr[10] = {0, 1, 2, 3};
  5. arr[4] = 4;
  6. if(a == 0) b *= 2;
  7. int d = 0;

型& 名前 = 同じ型の別の変数; で宣言すると, エイリアスを作ることが出来る.
これのおかげで, あんまりポインタ使わなくてもよい感じになっている.(関数の項でもちょっと出てくる)

  1. int a = 0;
  2. int& b = a;
  3. b = 10; //aも10になる
  4. a = 2; //bも2になる

詳しくは, C++ 参照 でググるとよいです.


入出力

cinとcoutで大体なんとかなる.
多分console input/outputの略.
cstdioをincludeすればprintfとかscanfも使える.

  1. int a, b;
  2. string s;
  3. char c;
  4. cin >> a >> b >> s >> c;
  5. cout << a*b << ", " << b << endl << s << endl;

cin>> という演算子を再定義していて, cin >> hoge とやると, hoge の型にあわせて読み込み, hogeに入れてくれる.
さらに, cinはcin自体を返すので, cin >> hoge >> fugaとやると, hoge のあとに fuga に入力する.
空白と改行区切りでパースされるので, 一行全体を取得したいとかいう場合は,

  1. string s;
  2. getline(cin, s);

とかで.
coutも, 変数の型によって適当に出力してくれる.
endlは改行. 多分 end line だと思う.
このへんは std 内なので, using namespace std をしていないなら, std::cout << a << std::endl とかする.

doubleとかを出力する時は精度がよろしくないので,

  1. cout.setf(ios::fixed);
  2. cout.precision(10);

とかする.


制御構造

基本的にC言語と同じ.

条件

比較は ==, !=, <=, >=, >, <.
and, orは &&, ||

  1. if(a != 0 && b != 0) cout << "a*b != 0" << endl;
  2. if(a == 0 || b == 0) cout << "a*b = 0" << endl;

int, longなどの整数型は, 0の場合は偽, それ以外は真とみなされる.

  1. if(a) cout << "a != 0" << endl;
  2. a = !(!a) // aは0ならそのまま, それ以外なら1になる.

if

一行の時は, ブレース(波ガッコ:{})は付けても付けなくてもよい.

  1. if(a == 0) cout << "a equals to zero" << endl;
  2. else if(a == 1) {
  3. cout << "a equals to one" << endl;
  4. } else
  5. cout << "a*a != a" << endl;

switch-case

Cと同じ.
あんまり使わない.
breakを忘れずに.
charとか整数とかで使える.

  1. int a, b, res;
  2. char c;
  3. cin >> a >> c >> b;
  4. switch(c){
  5. case '+':
  6. res = a + b;
  7. break;
  8. case '-':
  9. res = a - b;
  10. break;
  11. case '*':
  12. res = a * b;
  13. break;
  14. case '/':
  15. res = a / b;
  16. break;
  17. default:
  18. res = 0;
  19. break;
  20. }
  21. cout << res << endl;

for

Cと同じ.
ただし, forの最初の処理のところで変数宣言とか出来る.
一行の時は, ブレース(波ガッコ:{})は付けても付けなくてもよい.

  1. for(int i = 0; i < 10; ++i){
  2. cout << i << endl;
  3. }
  4. for(int i = 0; i < 10; ++i){
  5. if(i) cout << ", ";
  6. cout << i;
  7. }
  8. cout << endl;

2つ目のはイディオムで, 間にスペースとかカンマとかを入れて出力したい時とかに使われる.
(iが0の時以外, cout << ", "; が実行される.)

while

Cと同じ.

  1. int n;
  2. cin >> n;
  3. while(n){
  4. cout << n << endl;
  5. --n;
  6. }
  7. do{
  8. cout << n << endl;
  9. --n;
  10. }while(n >= 0);

どちらもnから1を表示する.
do-while(後置while)は,

  1. int n;
  2. do{
  3. cin >> n;
  4. }while(n % 2 != 0);

のように, 最初の一回は必ず実行されて欲しい時に使う.
上の場合, 偶数が入力されるまで入力させ続ける.

関数

大体はC言語と同じ.

  1. int gcd(int a, int b){
  2. if(b == 0) return a;
  3. return gcd(b, a%b);
  4. }

C言語で, gcdとlcmを一気に計算したいとか思ったら, ポインタを使って

  1. void gcdlcm(int a, int b, int* g, int* l){
  2. int ab = a * b;
  3. while(b != 0){
  4. a %= b;
  5. swap(a, b);
  6. }
  7. *g = a;
  8. *l = ab / *g;
  9. }

とかやるが, C++で参照を使うと, 次のように書ける.

  1. void gcdlcm(int a, int b, int& g, int& l){
  2. int ab = a * b;
  3. while(b != 0){
  4. a %= b;
  5. swap(a, b);
  6. }
  7. g = a;
  8. l = ab / g;
  9. }

クラス

演算子の再定義

英語ではオペレータのオーバーロードとか言う. C++ 演算子 オーバーロード とかでググるとよい. 自分で作ったクラスで, a + b とかが出来るようになる.
更に, 入出力が cin >> a とかで出来るように作れる.
また, setmap のキーにする時は, 比較演算子を再定義する必要がある.


string

リンクのProgramming Placeとか見ると良い.


テンプレート

例えば, 絶対値を返す, my_absという関数を作りたいとする.

  1. int my_abs(int n){ return n > 0 ? n : -n; }

しかし, 数値の型はintだけじゃないわけで,

  1. double my_abs(double n){ return n > 0 ? n : -n; }

とかも要るだろうし, 他にもまだまだあるんじゃないかという感じである.
こういうのを解決したのがテンプレート.

テンプレート関数

上の例だと,

  1. 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> でもよい.

  1. template<typename T, typename U> U add(T a, T b){
  2. U au = a, bu = b;
  3. return au + bu;
  4. }

みたいに, 複数の型を使ったりしてもよい.
明示的には, add<int, long>(1, 2) とかで呼び出す.

テンプレートクラス

例えば二次元ベクトルを扱いたいけど, 要素が整数なのか実数なのかは後で決めたいみたいな.

  1. <class T>
  2. class Vec{
  3. T x, y;
  4. Vec(T xx, T yy){ x = xx; y = yy; }
  5. Vec add(Vec other){
  6. return Vec(x + other.x, y + other.y);
  7. }
  8. };
  9. int main(void){
  10. Vec<int> a(0, 1), b(1, 0);
  11. Vec<int> c = a.add(b);
  12. }

みたいな感じで使う.
注意すべきなのは,

  1. Vec<Vec<int>> matrix;

とかやると, Vec<Vec<int>>>> を右シフトとして捉えてしまい, コンパイルエラーが起きる事.

  1. Vec<Vec<int> > matrix;

と, スペースを開けましょう.

リンク

Programming Place

ここ.
C++ hoge 的なググり方をするとよく引っかかるサイト.

C++マニアック

ここ.
演算子の再定義ってどうやるんだっけとか, 何を再定義できるんだっけとか, ちょっとマニアックなのが載ってる.

C/C++リファレンス

ここ.
関数名が思い出せない時とか便利.

cplusplus.com

ここ.
詳しい. 便利.

編集

最終更新:2013年03月27日 16:44