c言語で待ち時間を示すスピナーの簡単な表示法|キャリッジリターン

先日、Bash のシェルスクリプトでスピナーを表示する方法を示しました。スピナーとは、ざっくりいうと待ち時間を示すためのアニメーションですね。下記の例ではアスキー文字「-」「/」「|」「\」の4つを使って、風車のようにクルクル回るスクリプトを書きました。(環境によってはバックスラッシュが¥になってるかも…)

bash script で待ち時間を示すスピナーの表示
どうも、ながやすです。 今回はシェルスクリプトでスピナー(待ち時間中を示すアニメーション)を表示する方法についてです。 スピナーとは? ある程度長い時間(数秒以上)かかる処理を実行したと...

今回は、それを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の中身です。まず、%cspinner_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言語でもスピナーを簡単にかけるという例でした!同じようにしてプログレスバーなんかも表示できますね。