C言語で、くるくる回るスピナーを表示するかんたんな方法を説明します。


Bash scriptでのスピナー

先日、bash script で待ち時間を示すスピナーの表示にてBashのシェルスクリプトでスピナーを表示する方法を示しました。 スピナーとは、ざっくりいうと待ち時間を示すためのアニメーションですね。 下記の例ではアスキー文字- / \| \\ の4つを使って、風車のようにクルクル回るスクリプトを書きました。 今回は、それをC言語で実装してみます。

C言語での実装

100秒間のループ中にスピナーを表示するコードを示します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
#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の中身です。まず、%cspinner_c[i % spinner_len]についてです。 %cは1文字出力するという意味ですね。 spinner_c[i % spinner_len]の添え字は、インクリメンタルループカウンタのiを配列の要素数で割った余りです。 つまりi0 1 2 3 4 5 … と増加していくとi % spinner_len0 1 2 3 0 1 2… と0から3の間をループします。

さて、このコードで一番大事なのは\rです。これはキャリッジリターンで、「行の先頭へ移動する」という意味です。 Emacs なら C-aですね。これがあるおかげでスピナーのアニメーションを表示できています。 仮にこのキャリッジリターンがなかった場合、アニメーションせずに単に /-\|/-\|/-\|/-\|/-\|のように横にずらずらと表示されていきます。 エディタでもそうですよね、普通に入力するとこのように横につながって表示されますよね。 そこでこのキャリッジリターンの出番です。これは行の先頭へ移動する、という意味でした。 EmacsでいうならC-aと同じようなものです。つまり、ここのfor文では、先頭へ戻って1文字出力、先頭へ戻って1文字出力、を繰り返します。 printfの出力はエディタの上書きモードと同じですので、ひたすら先頭行にspinner_cの要素が上書きされます。これがアニメーションとなります

まとめ

今回は、キャリッジリターン(\r)を使えば、C言語でもスピナーを簡単にかけるという例でした!同じようにしてプログレスバーなんかも表示できますね。