先日、Bash のシェルスクリプトでスピナーを表示する方法を示しました。スピナーとは、ざっくりいうと待ち時間を示すためのアニメーションですね。下記の例ではアスキー文字「-」「/」「|」「\」の4つを使って、風車のようにクルクル回るスクリプトを書きました。(環境によってはバックスラッシュが¥になってるかも…)
今回は、それをC言語で実装してみます。
C言語での実装
100秒間のループ中にスピナーを表示するコードを示します。
#include <stdio.h> #include <unistd.h> int main(void) { const int spinner_c[] = {'/', '-', '\\', '|'}; const int spinner_len = sizeof(spinner_c) / sizeof(spinner_c[0]); unsigned int i; for (i = 0; i < 100; i++) { (void) sleep(1); printf("\r%c", spinner_c[i % spinner_len]); fflush(stdout); // バッファを強制的に出力. } puts(""); // 改行表示. return 0; }
コード解説
配列 spinner_c
は風車アニメーションのための部品です。これらを1秒間隔で順番に表示していくことで風車のようなアニメーションを表示します。ちなみにバックスラッシュが2つ連続していますが、これは1つ目のバックラッシュはエスケープ文字です。例えば改行は \n
と書きますね、あれと同じです。バックスラッシュ自体は2つ連続させる必要があります。
spinner_len
は、配列の要素数です。配列の要素数を計算するための定石ですね。 sizeof(配列名) / sizeof(配列名[0])
とします。この書き方なら配列がint型でもchar型でもなんでも同じように要素数を計算できます。
次はprintf
の中身です。まず、%c
とspinner_c[i % spinner_len]
についてです。%c
は1文字出力するという意味ですね。spinner_c[i % spinner_len]
の添え字は、インクリメタルループカウンタのi
を配列の要素数で割った余りです。つまりi
が0, 1, 2, 3, 4, 5, ... と増加していくとi % spinner_len
は0, 1, 2, 3, 0, 1, ... と0から3の間をループします。
さて、このコードで一番大事なのは\r
です。これはキャリッジリターンで、「行の先頭へ移動する」という意味です。Emacs なら C-a ですね。これがあるおかげでスピナーのアニメーションを表示できています。仮にこのキャリッジリターンがなかった場合、アニメーションせずに単に
/-\|/-\|/-\|/-\|/-\|
のように横にずらずらと表示されていきます。エディタでもそうですよね、普通に入力するとこのように横につながって表示されますよね。
そこでこのキャリジリターンの出番です。これは行の先頭へ移動する、という意味でした。EmacsでいうならC-aと同じようなものです。つまり、ここのfor文では、先頭へ戻って1文字出力、先頭へ戻って1文字出力、を繰り返します。printf の出力はエディタの上書きモードと同じですので、ひたすら先頭行にspinner_c
の要素が上書きされます。これがアニメーションとなります。
まとめ
今回は、キャリジリターン(\r
)を使えば、C言語でもスピナーを簡単にかけるという例でした!同じようにしてプログレスバーなんかも表示できますね。
コメント