How to make console output fixed in place

房东的猫 提交于 2021-01-27 18:48:17

问题


My LAME (v3.99.5) outputs progress in console by moving up x lines in the console and overwriting the previous lines. It's pretty cool.

I've read in a different post that such behavior for a single line can be achieved with a mere "\r" instead of "\n" - although the post was for Ruby, it seems to be the same for C on my system at least:

#include <stdio.h>
#include <time.h>

int main() {

    time_t t;
    time_t t2;

    time(&t);
    t2 = t;

    printf("%u\r", (unsigned int)t);        
    fflush(stdout);

    while (1) {
        if (t2 - t > 0) {
            time(&t);
            printf("%u\r", (unsigned int)t);        
            fflush(stdout);
        }
        time(&t2);
    }

    return 0;
}

The post further suggests a curses library can be used to make the same behavior multi-line.

What would be a boilerplate example of such code in C?


回答1:


According to http://falsinsoft.blogspot.com/2014/05/set-console-cursor-position-in-windows.html

Windows:

void SetCursorPos(int XPos, int YPos)
{
    COORD Coord;
    Coord.X = XPos;
    Coord.Y = YPos;
    SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), Coord);
}

Linux:

void SetCursorPos(int XPos, int YPos)
{
    printf("\033[%d;%dH", YPos+1, XPos+1);
}



回答2:


You can use something like this:

/!\ Warning: If you stop your curses program without call endwin() before, the terminal used to launch the program will have a very strange behavior.

include <curses.h>

int main(int argc, char *argv[]) 
{
    // init curses
    Xinitscr(argc, argv); 

    // init time
    time_t t = 0, t2;
    time(&t2);

    // main loop
    while (1) {
        if (t2 - t > 0) 
        {
            time(&t);

            clear();
            mvprintw(1,1, "%u", (unsigned int)t);
            refresh();
        }
        time(&t2);

    }

    // end curses mode
    // warning: if you do not call this at the end of your program,
    // your terminal won't be usable.
    endwin();

    return 0;
}



回答3:


The example shown by @purplepsycho has some issues, addressed in this revision (works with "any" X/Open Curses implementation):

#include <curses.h>

int main(int argc, char *argv[]) 
{
    filter();
    initscr();

    // init time
    time_t t = 0, t2;
    time(&t2);

    // main loop
    while (1) {
        if (t2 - t > 0) 
        {
            time(&t);

            erase();
            mvprintw(1,1, "%u", (unsigned int)t);
            refresh();
        }
        time(&t2);

    }
    endwin();

    return 0;
}

That is:

  • use initscr for initializing curses (PDCurses provides a non-standard function Xinitscr which is not what OP had in mind: it certainly is not often used).
  • use erase rather than clear (to avoid screen-flicker):

    The clear and wclear routines are like erase and werase, but they also call clearok, so that the screen is cleared completely on the next call to wrefresh for that window and repainted from scratch.

  • use filter to keep the output on a single line.
    If your terminal switches to the alternate screen, the screen will appear to be cleared. There is a workaround available with ncurses (see filter.c in ncurses-examples).

Better than erase() would be wclrtoeol(), called after the mvprintw.



来源:https://stackoverflow.com/questions/39363157/how-to-make-console-output-fixed-in-place

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!