コース目次 / 第4章

自分のものにする

回数を数えるようにして、1億回ループで速さを体感します。配り方つき。

第4章 / 全5章目安 約45分この章のゴール: 友だちに渡せる実行ファイルができて、C++の速さを自分の目で見る
お使いのパソコン
手順が切り替わります
お使いのエディタ
ファイル操作が切り替わります

最後の章です。ゲームを仕上げて、C++を選ぶ理由そのものを体験します。

1. 何回で当てたかを出す

kazuate.cpp+1 / -0
     std::cout << "1から100までの数を当ててください。" << std::endl; +    int kaisuu = 0;     std::string gyou;     while (true) {

行頭の + - は変更の目印です。コピーすると、記号と削除された行を除いたこの章を終えた時点の内容が入ります。

kazuate.cpp+1 / -0
         int kotae_kouho = std::atoi(gyou.c_str());+        kaisuu++;          if (kotae_kouho < kotae) {

行頭の + - は変更の目印です。コピーすると、記号と削除された行を除いたこの章を終えた時点の内容が入ります。

kazuate.cpp+1 / -0
         } else {             std::cout << "当たり! 答えは " << kotae << " でした。" << std::endl;+            std::cout << kaisuu << " 回で当てました。" << std::endl;             break;         }

行頭の + - は変更の目印です。コピーすると、記号と削除された行を除いたこの章を終えた時点の内容が入ります。

コンパイルし直して遊んでください。

Mac をお使いの方

VS Codeのターミナルターミナル
clang++ -std=c++17 -Wall -Wextra -o kazuate kazuate.cpp

行頭の $ は「ここからコマンド」という目印です。$ は打たないでください。

Windows をお使いの方

VS Codeのターミナルターミナル
g++ -std=c++17 -Wall -Wextra -o kazuate kazuate.cpp

行頭の $ は「ここからコマンド」という目印です。$ は打たないでください。

こう出る
当たり! 答えは 43 でした。
4 回で当てました。

kaisuu++ は kaisuu = kaisuu + 1 の短い書き方です。この ++ という記号が、C++という名前の由来です。「Cを1つ進めたもの」という洒落になっています。

2. C++を選ぶ理由 — 速さを見る

新しいファイル sokudo.cpp を作ります。やることは足し算を1億回するだけです。

sokudo.cpp
#include <chrono>
#include <cstdlib>
#include <iostream>

#ifdef _WIN32
#include <windows.h>
#endif

int main(int argc, char** argv) {
#ifdef _WIN32
    SetConsoleOutputCP(CP_UTF8);
#endif

    // 回数は実行するときに決める。決め打ちにすると、コンパイラが答えを先に
    // 計算してしまい、ループが丸ごと消えて時間が測れなくなる。
    long long kaisuu = 100000000;
    if (argc >= 2) {
        kaisuu = std::atoll(argv[1]);
    }

    auto hajime = std::chrono::steady_clock::now();

    long long goukei = 0;
    for (long long i = 0; i < kaisuu; i++) {
        goukei += i % 7;
    }

    auto owari = std::chrono::steady_clock::now();
    long long ms = std::chrono::duration_cast<std::chrono::milliseconds>(owari - hajime).count();

    std::cout << kaisuu << " 回まわして、合計は " << goukei << std::endl;
    std::cout << "かかった時間: " << ms << " ミリ秒" << std::endl;

    return 0;
}

配るときの旗 -O2 を付けてコンパイルします。

Mac をお使いの方

VS Codeのターミナルターミナル
clang++ -std=c++17 -Wall -Wextra -O2 -o sokudo sokudo.cpp

行頭の $ は「ここからコマンド」という目印です。$ は打たないでください。

Windows をお使いの方

VS Codeのターミナルターミナル
g++ -std=c++17 -Wall -Wextra -O2 -o sokudo sokudo.cpp

行頭の $ は「ここからコマンド」という目印です。$ は打たないでください。

VS Codeのターミナルターミナル
./sokudo 100000000

行頭の $ は「ここからコマンド」という目印です。$ は打たないでください。

この教材を書いた環境では
100000000 回まわして、合計は 299999995
かかった時間: 41 ミリ秒

1億回で、0.04秒です。

-O2 は「速くなるように工夫して翻訳して」という指示です。作っている間は付けず、配るときに付けるのがふつうです(付けると翻訳に時間がかかり、デバッグもしにくくなるため)。
なお、回数を実行時に決めているのには理由があります。決め打ちにすると、コンパイラが答えを先に計算してしまい、ループが丸ごと消えて時間が測れません。それくらい賢く翻訳されているということでもあります。

発展: 同じことを Python で

Python の試食をやった方は、比べてみてください。

sokudo.py
import sys, time

kaisuu = int(sys.argv[1])
hajime = time.perf_counter()

goukei = 0
for i in range(kaisuu):
    goukei += i % 7

owari = time.perf_counter()
print(f"{kaisuu} 回まわして、合計は {goukei}")
print(f"かかった時間: {int((owari - hajime) * 1000)} ミリ秒")
この教材を書いた環境では
100000000 回まわして、合計は 299999995
かかった時間: 8205 ミリ秒

0.04秒 と 8.2秒。約200倍です。(数字はパソコンによって変わります。)
これがC++が今も使われる理由です。ゲームエンジン、動画のエンコード、金融の計算、他の言語の処理系そのもの——「速さが値打ちに直結する場所」では、いまだにC++が現役です。
そして逆も言えます。0.04秒が8秒になっても困らない用途なら、書きやすい言語のほうが得です。Pythonが遅いのではなく、用途が違うのです。

3. 配る

できた実行ファイルを、別のフォルダにコピーして動かしてみてください。

VS Codeのターミナルターミナル
mkdir ~/haitatsucp kazuate ~/haitatsu/cd ~/haitatsu./kazuate

行頭の $ は「ここからコマンド」という目印です。$ は打たないでください。

動きます。ソースコードも、コンパイラも、そこには無いのに。

これが「1個のファイルで配れる」ということです。友だちに送っても、USBに入れても動きます。ただし同じ種類のOS・同じ種類のCPUに限ります(Macで作ったものはWindowsでは動きません)。
そこがGoとの違いです。Goは他のOS向けにも作れる仕組みを標準で持っていますが、C++で同じことをするのはかなり手間です。

あなたの番

3つとも、数字と文字を変えるだけです。

(1) 範囲を変える

% 100 の 100 を変えれば、当てる範囲が変わります。1000にすると急に難しくなります。

(2) 回数に上限をつける

kaisuu が7を超えたら「残念、答えは○○でした」で終わる、という遊びにできます。if を1つ足すだけです。

(3) 言葉を変える

もっと大きい 当たり! を、自分の言い方に変えてください。ここが遊ぶ人の目に入る文字です。

持ち帰りカード

フォルダに README.md を置いておきます。3か月後のあなたが読む用です。

README.md
# はるとの数当てゲーム

Tsumiki のミニ体験コース「C++ — コンピュータの素顔に触れる」の成果物です。

## また動かすとき(3行)

1. ターミナルを開く
2. `cd` でこのフォルダに入る
3. できあがっている実行ファイルを `./kazuate`(Windowsは `kazuate.exe`)で動かす

実行ファイルが無いとき(ZIPから戻したときなど)は、先に1回ビルドします。

clang++ -std=c++17 -Wall -Wextra -o kazuate kazuate.cpp # Mac g++ -std=c++17 -Wall -Wextra -o kazuate kazuate.cpp # Windows(w64devkit)


## 中身

| ファイル | 何をするか |
|---|---|
| `kazuate.cpp` | 数当てゲーム。ここだけ書き換えれば自分用になる |
| `sokudo.cpp` | 1億回まわして時間を測るだけのプログラム |
| `hello.cpp` | 第2章で書いた最初のファイル |

**実行ファイル(`kazuate` / `kazuate.exe`)は配布ZIPに入っていません。** OSごとに
別物になるので配れないからです。**自分でビルドしたものが、あなたの成果物です。**

## 覚えておくこと

- **できた実行ファイルは、同じOSの別のパソコンでもそのまま動きます。** C++ が
  入っていなくても動きます。それがコンパイルするということです
- **答えは種で決まります。** `SEED=42 ./kazuate` と打つと、いつでも同じ答え(43)に
  なります。友だちと同じ問題を解きたいときに使えます
- 配るときは `-O2` を付けてビルドし直すと、速さを引き出せます

## この先に進むなら

- cpprefjp(日本語のリファレンス) https://cpprefjp.github.io/
- ロベールのC++入門講座など、腰を据えた入門書が向いている言語です
- 「実用の道具を作りたい」なら Go や Python のほうが近道です。C++ は
  **速さと、コンピュータの仕組みそのものに用があるとき**の言語です

配布ZIPに実行ファイルは入っていません。OSごとに別物になるので配れないからです。自分でビルドしたものだけが、あなたの成果物になります。

試食レポート

おつかれさまでした。手元には遊べるゲームと、それを1個で配れる形にしたものが残りました。

C++は「コンピュータに一番近いところで書く」言語です。今日触ったのはほんの入口ですが、コンパイルするとは何か・型を先に決めるとは何か・速いとはどれくらいかを、目で見て手で触りました。この3つは、他のどの言語をやるときにも効いてきます。

この言語、合いそうでしたか?
書くことの多さ、翻訳のひと手間、そのかわりの速さと「機械が見える」感覚。合いそうなら、cpprefjp(日本語のリファレンス)が調べもののお供になります。C++は独学の難易度が高い言語なので、腰を据えた入門書を1冊決めるのが結局いちばん速いです。
「実用の道具を早く作りたい」のであれば、正直に言って Go や Python のほうが近道です。C++が要るのは、速さとハードウェアに用があるとき。それが分かったなら、この試食は成功です。
試食コーナーに戻る

ハマったら

ZIPで戻したい

このページの下のZIPは、この章を終えた状態のフォルダです。解凍して、その中で作業を続けられます。自分で書き換えた部分は消えてしまうので、先に自分のファイルを別の場所へ待避してから使ってください。

こうなっていればOK

うまくいかないときは、この章の完成ファイル一式(ZIP)をダウンロードして続きから進めても大丈夫です。

この章で卒業です。

この章はまだ完了していません。