画面を継続的に更新し、リアルタイムで更新するCプログラムをLinuxで作成したいと考えています(たとえば、top
ターミナルのコマンドと同様)。誰でも私を正しい方向に向けることができますか?
6 に答える
端末タイプ間での移植性を維持するには、 ncursesなどのライブラリを使用する必要があります。そのリンクをチェックしてください。完全なチュートリアルです。
以下は、画面の左上隅に増え続ける数字を出力する基本的なプログラムです。
#include <stdio.h>
#include <ncurses.h>
int main (void)
{
/* compile with gcc -lncurses file.c */
int c = 0;
/* Init ncurses mode */
initscr ();
/* Hide cursor */
curs_set (0);
while (c < 1000) {
/* Print at row 0, col 0 */
mvprintw (0, 0, "%d", c++);
refresh ();
sleep (1);
}
/* End ncurses mode */
endwin();
return 0;
}
それがウィンドウを更新する方法です。現在、データの行を表示したい場合top
は、表示するデータを順序付けられたデータ構造で維持する必要があります (データによっては、配列またはリンクされたリストのような単純なものかもしれません)。ロジックが指示するものに基づいてデータを並べ替え、clear()
またはwclear()
.
以下の場合、xterm
または互換性がある場合は、コンソール コードVT100
を使用できます。例:
#include <stdio.h>
#include <unistd.h> /* for sleep */
#define update() printf("\033[H\033[J")
#define gotoxy(x, y) printf("\033[%d;%dH", x, y)
int main(void)
{
update();
puts("Hello");
puts("Line 2");
sleep(2);
gotoxy(0, 0);
puts("Line 1");
sleep(2);
return(0);
}
エスケープ シーケンスを使用してほぼすべてを実行できますが、wikipedia で指摘されているようにncurses
、リモート シェルを使用するときに発生する遅延を減らすために、画面の変更を最適化します。
Ncurses が進むべき道かもしれません。あなたがプログラムと言ったので、ncurses、c、c++。それをすべて調べてください。しかし、「シェル」に関連することだけを計画している場合は、perl を使用してください。
編集:私のポイントに追加するために、ここにアイデアを与えることができるいくつかのモジュールがあります。
http://metacpan.org/pod/Curses::UI::Dialog::Progress
http://metacpan.org/pod/Smart::コメント
window.clrtobot()
そしておまけに、curses を呼び出してウィンドウ全体をクリアします。
状況によっては、コマンド ラインで「watch」コマンドを使用して、top のようなクイック ビューを取得できます。複数のコマンドを同時に監視することもできます。
元:
watch 'ls -l <somefile>; ps -fC <someprocess>; ./some_script'
他の人が言ったように、おそらく ncurses ライブラリを見たいと思うでしょう。ただし、高度な書式設定が必要ない場合は、おそらく次のような単純なもので十分です。
#include <stdio.h>
#include <unistd.h>
int main(void) {
int number = 0;
while (1) {
++number;
printf("\rThe number is now %d.", number);
fflush(stdout);
sleep(1);
}
return 0;
}
ncurses ライブラリを使用して画面処理を行うだけでなく、それを「継続的に」かつ「リアルタイムで」更新したい場合は、おそらくタイマーとシグナル処理も検討する必要があります。タイマーを動かしてtimer_create()
から、ハンドラー関数を設定してシグナルをトラップし、更新を行うことができます。timer_settime()
sigaction()
SIGALRM
編集: 要求に応じて、サンプル コードを次に示します。
#define TIMESTEP 200000000
timer_t SetTimer(void) {
struct itimerspec new_its;
struct sigevent sevp;
timer_t main_timer;
sevp.sigev_notify = SIGEV_SIGNAL;
sevp.sigev_signo = SIGALRM;
timer_create(CLOCK_REALTIME, &sevp, &main_timer);
new_its.it_interval.tv_sec = 0;
new_its.it_interval.tv_nsec = TIMESTEP;
new_its.it_value.tv_sec = 0;
new_its.it_value.tv_nsec = TIMESTEP;
timer_settime(main_timer, 0, &new_its, NULL);
return main_timer;
}
void SetSignals(void) {
struct sigaction sa;
/* Fill in sigaction struct */
sa.sa_handler = handler;
sa.sa_flags = 0;
sigemptyset(&sa.sa_mask);
/* Set signal handler */
sigaction(SIGALRM, &sa, NULL);
}
void handler(int signum) {
switch (signum) {
case SIGALRM:
update_stuff(); /* Do your updating here */
break;
}
}