C++のプログラムのコンパイルは以下のようなコマンドで行いますが、速度が求められる競技プログラミングではタイピングの時間がもったいなく感じます。
$ g++ -o hoge hoge.cpp
C++14とデバッグのオプションをつけると、こんなに長くなってします。
$ g++ -std=c++14 -g -O0 -o hoge hoge.cpp
私はコンテスト開始前に上記のコマンドを入力しておき、シェルの履歴を利用して時間短縮をしていたのですが~~(アホくさ)~~、zshのSuffix Aliasesという素晴らしい機能でそれが改善できたので、記事にしました。
環境
macOS 10.13.5
zsh 5.5.1
zshとは
シェルの一つです。強力な補完やワイルドカードを利用したファイルの指定、コマンド修正など便利な機能が盛りだくさんです。私は最近使い始めたのですが、大変満足しています。
Suffix Aliasesとは
Suffix Aliasesはzshの便利な機能の一つです。ファイルの拡張子に関連したエイリアスを作成し、ファイル名を打ち込むだけでそのエイリアスを実行することができるようになります。
例えば、hoge.py
を実行するときは
$ python hoge.py
と実行すると思いますが、Suffix Aliasesでファイル名だけで実行できます。
$ alias -s py=python # エイリアスの作成
$ hoge.py # python hoge.pyと同じ
やりたいこと
Suffix Aliasesを使ってC++のプログラムのコンパイルとプログラムの実行を
$ hoge.cpp
で自動で行えるようにします。プログラムの実行だけをしたい時にコンパイルをすることは無駄なので、ファイルの更新日時を見て、コンパイルが必要か判断することにします。以下のフローに詳細を示します。
シェルスクリプトを書く
~/.zshrc
に以下を追加します
function with_echo() {
echo $@
$@
}
function cpp_compile() {
with_echo g++ -std=c++14 -g -O0 -o $1 $2
}
function cpp_run() {
cpp_file=$1
exe_file=${cpp_file:0:-4}
shift
if [ -s $cpp_file ]; then
if [ ! -f $exe_file ]; then
cpp_compile $exe_file $cpp_file && ./$exe_file $@
else
cpp_date=`date -r $cpp_file +%s`
exe_date=`date -r $exe_file +%s`
if [ $cpp_date -gt $exe_date ]; then
cpp_compile $exe_file $cpp_file && ./$exe_file $@
else
./$exe_file $@
fi
fi
else
echo $cpp_file is empty
fi
}
alias -s cpp=cpp_run
with_echo()
echo
で実行するコマンドを出力してから、コマンドを実行します。
cpp_compile()
C++14とデバッグのオプションをつけてg++でコンパイルをします。with_echo()
でコンパイルが行われたことを示します。
cpp_run()
$1
でコンパイル対象のファイル名を取得し、${cpp_file:0:-4}
で実行ファイル名を作成します。また、if [ -s $cpp_file ]
、if [ ! -f $exe_file ]
、if [ $cpp_date -gt $exe_date ]
がフローチャートの分岐に対応しています。
cpp_date
とexe_date
は、C++のプログラムファイルと実行ファイルの更新日時のUNIX時間を変数に入れたもので
date -r $file_name +%s
で取得することができます。
cpp_compile $exe_file $cpp_file && ./$exe_file $@
shift
で引数を一つずらすことで$@
で必要なコマンドライン引数を全取得できるようにし、&&
でコンパイルが成功した場合のみプログラムをそのまま実行するようにします。
結果
最高ですね!!!!!
おわりに
プログラムのコンパイルと実行が$ hoge.cpp
だけで済むようになったので、めっちゃ捗ってます。皆さんもこの方法で一秒でも早くプログラムを提出しちゃってください!