にちにちメモ

天文系大学院生のブログ。日々の生活の中で忘れがちなこと/忘れたくないことをメモ。

C言語の出力を上書きする

C言語のプログラムで、実行中に進捗を表示させたくなった。

しかし、
10%
20%
...
100%
などと連続して表示させるのもどこか格好わるい。

できれば、
|-| 10%
と出たあと、それに上書きする形で
|--| 20%
と出て、最終的には
|----------| 100%
しか標準出力に残っていない形が望ましい。

 

printf()にそんな機能があるか調べてみたら、やはりあった。
(正確にはprintf自体の機能ではなく、エスケープシーケンスで
 その動作が実行できるだけだが……。)

 

まず、printfを使い
printf("hogehoge row No. 1");
適当な文字列を出力する。ここで改行"\n"を使わないのがポイント。

これに上書きしたい文字を、またprintfを使い出力する。
このとき、文字列の先頭に"\r"(その行の先頭に戻る)を入れる。
printf("\rhogehoge row No. 2");

こうすると、最初のhogehoge row No. 1が上書きされて
hogehoge row No. 2だけが標準出力に残るようになる。

 

なお、処理系によっては"\n"を入れないとバッファを吐き出してくれない
(準備は整っているのに出力してくれない)場合があるので、
その場合は最初のprintfと次のprintfの間に
fflush(stdout);
を入れると、"\n"を入れなくても標準出力に出してくれる。

 

使用するライブラリまで明示的に書くと以下の通り。

#include<stdio.h>
#include<unistd.h>  // sleep()関数のためのライブラリ。

int main(void)
{
  printf("hogehoge row No. 1");
  fflush(stdout);
  sleep(1);  // 次の処理に移る前に1秒待つ。これをしないとすぐに表示が切り替わる。
  printf("\rhogehoge row No. 2");
  printf("\n");

  return 0;
}

 

ちなみに、"\b"(バックスペース)で以前表示した文字列を消して、
その上から書き始めるというテクニックもあるらしい。
こちらの方が、普段キーボードを使っている感覚に近いかもしれない。

 

以下を参考にしました。

標準出力の上書き - C・C++ - 教えて!goo

標準入出力関数(1)

fflush