3

Is it possible to modify text I printed to the terminal without clearing the screen?

For instance, if I'm showing progress of something in percentage, can I modify that percentage without having to clear the screen and printing again? I'm looking for a cross-platform way, if there is one.

Talking C++.

thanks

Lockhead
  • 2,423
  • 7
  • 35
  • 48

4 Answers4

5

There are a number of ways to do this, and depending on how much effort you want to put into it, you can do a lot of cool things with ascii text in a terminal window.

  1. Advanced: ncurses library

  2. Easier: ansi escape characters with printf or cout

  3. Easiest: As others have said, simply use \r for a carriage return without a linefeed.

Edit: example of using the ESC sequence to go back two characters:

#include <iostream>
#define ESC char(0x1B)

int main(){
  std::cout << "This will overwrite 'rs' in the following: characters" << ESC << "[2D" << "xx" << std::endl;
  return 0;
}
Chris Gregg
  • 2,376
  • 16
  • 30
  • ANSI escape characters seem to work for what I need. How would I go about going left 2 characters? something like std::cout << \2d; ? – Lockhead Aug 05 '11 at 15:59
  • @MisterSir - use uppercase `D`: `std::cout << "This will overwrite 'rs' in the following: characters" << char(0x1B) << "[2D" << "xx" << std::endl;` – Chris Gregg Aug 05 '11 at 16:09
  • 1
    Don't hard-code 0x1B, though, if you can avoid it, if you want this to work generally. You should favor using ncurses (it's not very complicated to use it to look up a code) or the tput program (if writing a shell script) to lookup the appropriate terminal codes from the terminfo database. – Chris Page Oct 01 '11 at 04:08
3

A very simple way to do it is to print out a string followed by a '\r' character. That is carriage return by itself and on most consoles, it returns the cursor to the beginning of the line without moving down. That allows you to overwrite the current line.

If you are writing to stdout or cout or clog remember to fflush or std::flush the stream to make it output the line immediately. If you are writing to stderr or cerr then the stream is unbuffered and all output is immediate (and inefficient).

A more complicated way to do it is to get into using a screen drawing library like curses.

1

On Linux systems, check out the ncurses package. This package provides support for cursor movement on most terminals.

Thomas Matthews
  • 56,849
  • 17
  • 98
  • 154
1

You can use the "\r" character to return to the first character of that line:

for(int i = 0; i < 60; i++){ cout << "\rValue of i: " << i;}

Keep in mind to NOT put an end line (endl or '\n') at the end of your output, or you'll just skip to the beginning of the new line each time, losing that desired effect.

lightningmanic
  • 2,025
  • 5
  • 20
  • 41