3

ばかげた質問ですが、printf(); を使用して改行せずに stdout で改行することは可能ですか? そうでない場合、可能であれば2行以上を上書きする方法に関するヒントはありますか?

一種のプログレスバーを生成しようとしていますが、複数の行があります。何か案は?

編集:だから、私の特定のケースではうまくいきませんが、私は以下の答えを受け入れました。1 行ではなく 2 行以上を上書きしようとしています。

printf("12345\r");
fflush(stdout);
printf("67890\n");

その結果は
$ ./a.out
67890 です

しかし、私が達成しようとしているのは、2 行以上を新しいデータで上書きすることです。プログレス バーに似ていますが、一部のデータのパーセンテージを除いて 2 行以上あります。

4

2 に答える 2

3

行のすべて (または一部) を書き換えるには、正しい数のバックスペース文字を使用する必要があります。例えば:

printf("some text");
printf("\b\b\b\bstuff");

出力します:

some stuff

これは単純なものには問題ありません。より複雑な場合は、ANSI エスケープの巧妙さを使用して画面上でカーソルを操作するncursesを使用する必要があります。

于 2013-03-06T15:46:43.007 に答える
2

端末(または、おそらく端末エミュレーター)が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;
}
于 2013-03-06T16:26:23.577 に答える