端末(または、おそらく端末エミュレーター)がVT100スタイルのエスケープシーケンスをサポートしている場合は、特定のコードシーケンスを印刷して、カーソル位置を制御したり、画面/ウィンドウの一部またはすべてをクリアしたりできます。
たとえば、カーソルを1行上に移動するには、次のようにします。
printf("\x1b[A");
fflush(stdout);
カーソルを2行上に移動するには、それを2回実行するか、次のようにします。
printf("\x1b[2A"});
fflush(stdout);
これらは一般にANSIエスケープコードと呼ばれます。リンクは、それらの多くをリストしたウィキペディアの記事へのリンクです。これらは、ほとんどの最新の端末およびエミュレーターによってエミュレートされる古いDECVT-100端末によって最初に実装されました。
この:
printf("\x1b[J");
fflush(stdout);
現在のカーソル位置から下まで、画面の一部をクリアします。
これらのシーケンスは、必要なことを実行するのに十分なはずです。(Windowsのコマンドウィンドウでは動作しない場合があります。)
より移植性が高いのは、システムがそれをサポートしている場合、termcap
またはterminfo
を使用して、現在の端末の適切なコマンドシーケンスを決定できることです($TERM
環境変数によって決定されます)。このtput
コマンドを使用すると、コマンドラインでこれを実行できます。man tput
詳細については。実際には、VT100と互換性のない端末でtermcapまたはterminfoをサポートするシステムを最近見つけることはほとんどありません。生のエスケープシーケンスの印刷は厳密には移植性がありませんが、おそらく十分です。
提案:あなたのプログラムには、おそらくそのような制御シーケンスを禁止するオプションがあるはずです。たとえば、出力をファイルにリダイレクトしたいユーザーが、ファイルにそれらのエスケープシーケンスを含めたくない場合です。一部のプログラムは、stdoutが端末であると判断できる場合にのみ制御シーケンスを使用しますが、明示的なオプションもお勧めします。
*更新:*
これは、でこれを行う方法を示す、私が一緒に作成したプログラムですterminfo
。ほぼすべてのUnixライクなシステムで動作するはずです。
#include <stdio.h>
#include <stdlib.h>
#include <curses.h>
#include <term.h>
#include <unistd.h>
int main(void) {
const char *term = getenv("TERM");
if (term == NULL) {
fprintf(stderr, "TERM environment variable is not set\n");
exit(EXIT_FAILURE);
}
setterm(term);
for (int i = 0; i < 10; i ++) {
putp(tparm(clr_eos));
printf("%d\n%d\n", i, i+1);
sleep(1);
putp(tparm(parm_up_cursor, 2));
}
return 0;
}