Question

Silly question but, Is it possible to break a line on stdout without the line feed using printf();? If not, any tips on how I would overwrite 2+ lines, if possible?

I'm trying to generate sort of a progress bar but on multiple lines. Any ideas?

EDIT: So yeah I accepted the below answer although it won't work for my specific case. I'm trying to overwrite 2+lines rather than a single line.

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

The result of which is
$ ./a.out
67890

But what I'm trying to achieve is have 2+ lines be overwritten with new data. Similar to a progress bar but on 2+ lines except I have a percentage number for some data.

Was it helpful?

Solution 2

If your terminal (or, much more likely, terminal emulator) supports VT100-style escape sequences, you can print specific code sequences to control the cursor position, clear some or all of the screen/window, etc.

For example, to move the cursor up 1 line:

printf("\x1b[A");
fflush(stdout);

To move the cursor up 2 lines, either do that twice or:

printf("\x1b[2A"});
fflush(stdout);

These are commonly referred to as ANSI escape codes; the link is to a Wikipedia article that lists many of them. They were first implemented by the old DEC VT-100 terminal, which is emulated by most modern terminals and emulators.

And this:

printf("\x1b[J");
fflush(stdout);

will clear part of the screen, from the current cursor position to the bottom.

These sequences should be enough to do what you need. (They might not work in a Windows command window.)

More portably, if your system supports it, you can use termcap or terminfo to determine the proper command sequences for your current terminal (as determined by the $TERM environment variable). The tput command lets you do this on the command line; man tput for more information. In practice, you're unlikely to find a system these days that supports termcap or terminfo with a terminal that's not VT100-compatible; printing raw escape sequences is strictly not portable, but probably good enough.

A suggestion: your program should probably have an option to inhibit any such control sequences; for example, if a user who wants to redirect the output to a file won't want to have those escape sequences in the file. Some programs use control sequences only if they can determine that stdout is a terminal, but an explicit option is also a good idea.

*UPDATE: *

Here's a program I threw together that demonstrates how to do this with the terminfo. It should work on just about any Unix-like system.

#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;
}

OTHER TIPS

To rewrite all (or part) of a line, you need to use the correct number of backspace characters. Eg:

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

Will output:

some stuff

This is fine for simple stuff; for something more complex you should use ncurses which uses ANSI-escape cleverness to manipulate the cursor around the screen.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top