プログレス表示の方法について書きなおしています。以下を参照ください。
コンソールでプログレス表示(アニメーション)(1)
ある程度大きなプログラムを組むようになると、処理に非常に長い時間がかかるようになります。
まあ、プログラムの規模や処理の複雑さがそれほどでなくても、処理に長い時間がかかるもののほうが多いような気もしますが・・・。
ともかく、比較的時間のかかる、この場合人間が待たされると感じる程度、10秒程度以上の時間がかかるプログラムを実行すると、
処理がどこまで進んだのかを表示したくなることがあります。
ところが普通に printf 関数をつかってコンソールに状態を出力するだけでは
出力が画面の下から上へ流れていってしまうだけで見た目がよろしくない。
そこで、私なりのコンソールに進行状況をアニメーションっぽい表示をする方法を3回にわたって書いてみたいと思います。
この方法を応用すれば、進行状況に限らず、コンソールでアニメーションをしているような出力ができると思います。
(注:あんまり期待しないでください(汗))
'#'で垂れ流しプログレスバー
まず、一番シンプルな方法、テクニックでもなんでもないとツッコんでください。
RedHat 系列の Linux の簡易インストールパッケージ RPM ファイルの
インストールコマンド rpm を -h オプション付きで実行するとインストール進行状況が # の数(50個で完了?)で表示されます。
こいつのまねをしてみましょう。
#include <stdio.h>
#include <time.h>
void hoge();
main(){
int i;
int times=100;
setbuf(stdout,NULL);
for(i=0;i<times;i++){
/*適当な処理*/
hoge();
if(i%(times/20)==times/20-1)
printf("#");
}
printf("\nfinish!!\n");
}
/* 適当な処理をする関数、
いい表現方法が思い浮かばなかったんですんません */
void hoge(){
clock_t t;
/* 時間待ち開始 */
t = clock() + CLOCKS_PER_SEC/20;
while(t>clock());
/* 時間待ち終了 */
}
こいつは、時間のかかる処理の変わりに0.1秒間待つ処理を入れています。
ちなみに setbuf(stdout,NULL); っていうのは stdout 、つまりこの場合コンソールへの出力のバッファを
NULL 、つまりなしにするという意味。処理の高速化のために画面出力を一時バッファにためて出力する場合があるが、
そうするとプログレス表示の意味がないので念のためこう書いておく。(こいつはエラーの場所を探すときにも役に立つ)
こいつを実行すると一定間隔で#が増えていきます、
上のような感じに表示されると思います。(JavaScriptによって表現しています)
ただ単に、一定の回数が終わると # を1個ずつ出力するだけです。
毎回改行を入れないので、アニメーションしているように見えなくもないです。
このソースをまんま流用する場合の注意点として、 times が20未満だったりするとエラーになってしまいます、
たとえば 19/20 は整数演算では 0 になってしまうので。
また、20 以上でも割り切れる数より小さいと 20 以上の # が表示されてしまったりします。
厳密にするにはビットシフトで固定小数点演算の精度を上げるなどの工夫が必要ですね。
でも、そこまでする必要はめったにないでしょう。
この処理は見た目だけで処理そのものに影響は出ませんし、
表示するために無駄な計算をさせて処理の時間が増えてしまったのでは本末転倒です。
(処理時間のことをいうなら (times/20) とか times/20-1 はあらかじめバッファにとっておいた方がいいですが、
最近のコンパイラの最適化はすごいのであんまり変化ないかも)
それに times の値が精度(ここの場合では20)の二乗以上の数値では
if文のところで i%(times/20) を times/20-1 と比較していれば誤差は出ません、
たいていの場合 times の値は非常に大きいですから。
ここでの目的は、なんとな~く処理が進んでるんだな~ってことを表現できればいいだけですから、細かいことは考えない(笑)。