If you want to see more Frequently Given Answers then enable the navigation bar support in your WWW browser, and hit your WWW browser's "Up" button. You can navigate all around this WWW site with your navigation bar. Your navigation bar will also enable you to more easily navigate to a specific section on this page, as all of the sections are listed on it.
There's a lot of incorrect or misleading information on how to perform what is on the face of it a very simple task: clearing the screen in a TUI program. This is the Frequently Given Answer to the question:
How do I clear the screen (in a C or C++ TUI program)?
(You can find a different approach to this answer written by Michael Thomas Greer.)
This Frequently Given Answer only addresses TUI programs. Clearing the screen in a GUI program is a very different kettle of fish, and one that doesn't even exist at all as a concept in several GUI systems.
There are several widely-touted ways of clearing the screen that are, quite simply, wrongheaded. They won't work in the general case, and are fragile. There's lots of advice handed around that involves them, but in the main this is advice given by people who didn't actually read their programmers' documentation to find out the right ways to clear the screen, but instead found a quick bodge that just happened to work on the one or two machines that they tried.
One common mistake to avoid is using the system()
standard library function to clear the screen, executing either of:
system("cls") ;
system("clear") ;
There are a large number of things wrong with this approach:
The function may not do anything at all.
Although the system()
function is a standard C library function, there's no guarantee that it actually does anything.
An implementation of the C or C++ languages is free to implement a quite minimal system()
function, if it so desires.
The target machine might not be configured with a command
intepreter.
Even if system()
is implemented to run a command interpreter and pass it a command string to execute, there's no guarantee that the system administrator has configured the system so that this will happen.
It's not unknown for system administrators to alter, for example, the value of the COMSPEC
environment variable on OS/2, Win32, or PC/MS/DR-DOS systems.
So even if one's system()
function tries to run a command interpreter, there's no guarantee that it
can.
The command to clear the screen isn't uniform across all
systems.
As can be seen above, sometimes the command to clear the screen in a command script is CLS
, and sometimes it's clear
.
Sometimes it's neither.
Sometimes the CLS
and clear
commands do something else entirely, quite different to clearing the screen, with unintended consequences.
Sometimes the user running the application has a private command script called CLS
or clear
, which does something unpredictable and unwanted.
The command to clear the screen doesn't necessarily
work.
For reasons that will be discussed in full later, what a CLS
or clear
command does in the default case won't necessarily actually work.
Here's just one example, of several such, showing how the CLS
command can fail to clear the screen on OS/2:
[C:\]ANSI OFF [C:\]CLS ←[2J[C:\]
This is part of the reason why, of course, the CLS
commands in The 32-bit Command Interpreter for OS/2 and in JP Software's 4DOS/4NT/TCC/TCCLE have options such as /D
and /S
.
Moreover: All of the aforementioned is to gloss over the fact that this is a grossly inefficient way of clearing the screen, an operation that, as we shall see, can be done quite simply, in-process with system API or library function calls, without the overhead of spawning one — possibly two — entirely separate processes, with all of their setup and teardown overheads, to achieve the goal.
One common mistake to avoid is writing strings of characters to standard output (or some other appropriate I/O stream) that are simply hardwired into the program code. The simplest form of this is writing the ASCII FF (Form Feed) character:
fputc('\x0C', stdout) ;
But there are several variations, such as hardwiring the escape sequence for ECMA-48 conformant terminals:
fputs("\x1B[2J", stdout) ;
Or writing large numbers of newlines:
for ( unsigned i = 100 ; i > 0 ; --i ) puts("") ;
These approaches suffer from four fundamental errors:
Standard output isn't necessarily the console or terminal device. Simply put, standard I/O streams can be redirected.
The TUI might not employ the "terminal" paradigm. For reasons that will be discussed in full later, not every Textual User Interface employs platform I/O devices that have the "terminal" paradigm. Even for those that do, sometimes it is optional.
In OS/2, for example, support for ECMA-48 control sequences can be turned on and off programmatically for consoles.
This is what the ANSI
command, given in the earlier example, is doing.
If ECMA-48 control sequence support happens to be turned off, then all hardwired ECMA-48 control sequences in one's program, such as the one to clear the screen, will not have the desired effects.
In the earlier example, witness that the escape sequence is just dumped out to the screen as-is when ECMA-48 control sequence support is turned off.
Don't make the mistake of thinking that this is specific to OS/2, moreover.
On PC/MS/DR-DOS, for example, ECMA-48 control sequence support is only available if one has installed an ANSI.SYS
device driver of some sort.
The default console device (CON:
) behaviour, in the absence of such a device driver, is to do as OS/2 does with ECMA-48 control sequence support disabled.
Windows NT consoles, moreover, have no support for such ECMA-48 control sequences, or any other terminal's control character sequences apart from very basic support for the ASCII control characters, at all.
Here's 4NT demonstrating that:
[C:\]ECHOS %@CHAR[27][2J ←[2J [C:\]
Even if the platform I/O device is of the "terminal" kind, "clearing the screen" may not make sense for the device. It makes no sense on a teletype printer terminal device, for example.
Even if the platform I/O device is of the "terminal" kind, and the concept of clearing the screen makes sense for the device, whatever is hardwired into the program might not be the correct control character sequence. It should go without saying, so long ago was this lesson learned, that not all terminals support the same set of control character sequences. Not every terminal is an "ANSI" terminal. So-called "ANSI" terminals are called that because they adhere to the ECMA-48 standard (decades ago briefly also an ANSI standard for a few years, but not actually developed by ANSI, nor associated with ANSI since the 1990s) for terminal control character sequences. But that's not the only standard around, and there were (and to an extent still are) many terminals that have quite different control character sequences. This heterogeneity was, after all, the reason that the termcap and terminfo mechanisms were invented in the first place.
This should go without saying, but the prevalence of these common mistakes indicates otherwise.
People mistakenly think that just because the terminal emulator for a Linux virtual console, or for an xterm
, acts a particular way for a particular control character sequence, that control sequence is standard across all types of terminals that could ever be attached to the system.
By the way: If one reads the C standard one finds that it makes no real guarantees about the '\f'
escape sequence.
It merely states the intention that it have the display semantics, if written to a C stream attached to a display device, of moving "to the initial position at the start of the next logical page".
The C standard is deliberately vague as to the semantics of, and even the execution character set value represented by, '\f'
.
This is for many of the same reasons as laid out above.
There's no guarantee that there's a way to clear a screen.
There's no guarantee that if there is a way that it will be a single control character.
And there's no guarantee that that control character is even the same for all terminal communications
protocols on the target platform.
One common mistake to avoid is mistaking the the DOS system API for a general API.
The symptom of this mistake is using the <conio.h>
header and thinking that one has a clrscr()
function:
#include <conio.h> … clrscr() ;
The <conio.h>
header properly forms one part of the C and C++ language bindings to the DOS system API.
It isn't a standard library facility, and shouldn't be mistaken for one.
It's part of the language bindings for a specific platform's API.
Ironically, the clrscr()
function that is declared in the <conio.h>
header in some DOS C and C++ language compilers isn't even a DOS API facility in the first place.
As will be shown later, clearing the screen on PC/MS/DR-DOS isn't done through an operating system API function at all.
The operating system has no functions for doing this, and no guaranteed capability in its CON:
device for supporting ECMA-48 standard control character sequences, either.
The clrscr()
function is one of Borland's extensions to the DOS API bindings.
They don't exist in all DOS C and C++ compilers, and don't necessarily exist in porting libraries for compilers that target other platforms.
It's a mistake to think that a clrscr()
function will be always available on every DOS compiler.
It's a mistake to think that it will be available on compilers that aren't targetting PC/MS/DR-DOS.
It's even a mistake to think that it's better to write new code that uses a porting library aimed at providing source-level compatibility with Borland C/C++ for DOS programs, than to just write that new code to directly use the native mechanisms provided on the platform that one is targetting.
The correct way to clear the screen varies from platform to platform. Operating systems have differing paradigms for TUI programs. Clearing the screen involves platform-specific code, that is not general across multiple platforms. Any program that expects to clear the screen on multiple platforms will either contain conditional compilation or platform-specific libraries.
Platforms can be grouped into two broad categories, platforms with "consoles" and platforms with "terminals", according to the paradigms that they present to TUI programs. These are not firm divisions, and several platforms are admixtures of the two approaches. The procedures for clearing the screen on each of the paradigms are:
Platforms with "consoles".
The procedures for clearing the screen on a "console" follow two basic patterns:
Set all character cells in the console to the same (usually the space character and a fixed attribute) value. This can be done in two ways:
Scroll the entire screen buffer up, by as many lines as there are lines in the screen buffer.
Write a single cell value across all rows of the screen.
Move the cursor to the top-left-hand corner of the console.
Platforms with "terminals".
The procedures for clearing the screen on a "terminal" follow one basic pattern:
Determine, from some configuration information, what the "terminal type" is — i.e. what communications protocol it speaks.
Look up, in a database provided by the platform, the appropriate character sequences in that communications protocol for clearing the terminal's screen.
Send the character sequence to the terminal.
OS/2 primarily provides a "console" paradigm to applications softwares. The 16-bit console API is the so-called KBD/VIO/MOU API. There's no IBM-provided 32-bit console API, but there is an add-on 32-bit Unicode Console API that pure 32-bit programs can use. Whatever the API, as mentioned earlier, the procedures for clearing the screen follow two basic patterns, scrolling or filling.
For the 32-bit Unicode Console API, clearing the screen involves the DosQueryConsoleWindow()
, DosScrollConsoleUp()
, DosWriteConsoleOutputNCell()
, and DosSetConsoleCursorPos()
API functions, as follows:
Filling:
size_t Top, Left, Height, Width; DosQueryConsoleWindow(ConsoleHandle, Top, Left, Height, Width) ; CONSOLE_CELL space(' ', attr) ; for ( size_t N = 0 ; N < Height ; ++N ) DosWriteConsoleOutputNCell(ConsoleHandle, space, Width, Top + N, Left) ; DosSetConsoleCursorPos(ConsoleHandle, Top, Left) ;
Scrolling:
size_t Top, Left, Height, Width; DosQueryConsoleWindow(ConsoleHandle, Top, Left, Height, Width) ; CONSOLE_CELL space(' ', colour) ; DosScrollConsoleUp(ConsoleHandle, Top, Left, Height, Width, Height, space) ; DosSetConsoleCursorPos(ConsoleHandle, Top, Left) ;
Note that the above code clears the console window, not the entire screen buffer. On current versions of OS/2, the two are effectively coterminous, and clearing the console window will clear the entire screen. However, it is possible that in a future API the two will be separated, as they are in Win32 (more on which later), in which case the above code is future-proof.
For the 16-bit KBD/VIO/MOU API, clearing the screen involves the
VioGetMode()
,
VioScrollUp()
,
VioWrtNCell()
,
and
VioSetCurPos()
API functions, as follows:
Filling:
VIOMODEINFO ModeInfo ; ModeInfo.cb = sizeof ModeInfo ; VioGetMode(&ModeInfo, 0) ; BYTE space[2] = { ' ', attr } ; for ( size_t N = 0 ; N < Info.row ; ++N ) VioWrtNCell(space, Info.col, N, 0, 0) ; VioSetCurPos(0, 0, 0) ;
Scrolling:
VIOMODEINFO ModeInfo ; ModeInfo.cb = sizeof ModeInfo ; VioGetMode(&ModeInfo, 0) ; BYTE space[2] = { ' ', attr } ; VioScrollUp (0, 0, Info.row, Info.col, Info.row, space, 0) ; VioSetCurPos(0, 0, 0) ;
Note that this code is not future-proof, as the 32-bit Unicode Console API code is. It will always clear the entire screen buffer.
OS/2 also provides a "dumb TTY" interface to consoles, with a terminal communications protocol that follows a limited subset of the ECMA-48 standard, including the ESC+'['+'2'+'J' escape sequence for clearing the screen.
However, ECMA-48 control sequence support can be turned on and off for OS/2 consoles.
In order to detect whether it is currently on or off one calls the DosQueryConsoleMode()
(32-bit API) or the VioGetAnsi()
(16-bit API) functions, in which case one is invoking the platform-specific API anyway, and might as well use that API itself, rather than mucking around with escape sequences at all.
Win32 primarily provides a "console" paradigm to applications softwares.
As mentioned earlier, the procedures for clearing the screen follow two basic patterns, scrolling or filling.
Clearing the screen involves the GetConsoleScreenBufferInfo()
, FillConsoleOutputCharacter()
, FillConsoleOutputAttribute()
, ScrollConsoleScreenBuffer()
, and SetConsoleCursorPosition()
API functions, as follows:
Filling:
CONSOLE_SCREEN_BUFFER_INFO Info GetConsoleWindowInfo(ConsoleHandle, &Info) ; SHORT Width = Info.srWindow.Right - Info.srWindow.Left + 1 ; for ( SHORT N = Info.srWindow.Top ; N <= Info.srWindow.Bottom ; ++N ) { DWORD Chars ; COORD Pos = { Info.srWindow.Left, N } ; FillConsoleOutputCharacter(ConsoleHandle, ' ', Width, Pos, &Chars) ; FillConsoleOutputAttribute(ConsoleHandle, attr, Width, Pos, &Chars) ; } COORD TopLeft = { Info.srWindow.Left, Info.srWindow.Top } ; SetConsoleCursorPosition(ConsoleHandle, TopLeft) ;
Scrolling:
CONSOLE_SCREEN_BUFFER_INFO Info GetConsoleWindowInfo(ConsoleHandle, &Info) ; CHAR_INFO space ; space.Char.AsciiChar = ' ' ; space.Attributes = attr ; SHORT Height = Info.srWindow.Bottom - Info.srWindow.Top + 1 ; COORD Origin = { Info.srWindow.Left, Info.srWindow.Top - Height } ; ScrollConsoleScreenBuffer(ConsoleHandle, &Info.srWindow, NULL, Origin, &space) ; COORD TopLeft = { Info.srWindow.Left, Info.srWindow.Top } ; SetConsoleCursorPosition(ConsoleHandle, TopLeft) ;
Note that the above code clears the console window, not the entire screen buffer. This accomodates TUI programs with "scroll back" capabilities. Under the scroll back conventions, the console window is always at the bottom of the console screen buffer, and the area of the screen buffer that is above the window is the "scroll back" area. Alternative clear screen procedures, that don't enable "scroll back" areas and that clear the entire screen buffer, are described in Microsoft KnowledgeBase article 99261.
POSIX provides a "terminal" paradigm to applications softwares. As standard, this includes a set of "terminfo" library functions, for accessing a database of terminal information, indexed by terminal type and function. Many POSIX systems also include the older "termcap" library, which does the same thing except in a slightly different way. It is the "terminfo" library that is standardized.
The procedure is very simple and involves the setupterm()
, tigetstr()
, and putp()
API functions:
Ensure that the program has initialized the "terminfo" library, by executing the following at some point before one needs to clear the screen:
#include <term.h> … setupterm(NULL, fileno(stdout), NULL) ;
Read and output the appropriate control character sequence:
#include <term.h> … putp(tigetstr("clear")) ;
Usually, TUI applications on POSIX systems employ some form of "curses" library, which is layered on top of the raw "terminfo" library.
Clearing the screen with curses is simply a matter of obtaining a full-screen window (such as the result of the initscr()
function) and calling:
#include <curses.h> … wclear(window) ; wrefresh(window) ;
Technically, it's possible to gain direct access to terminal screen buffers on GNU Hurd and Linux, and use the "console" paradigm.
On Hurd, for example, the /hurd/console
dæmon provides device files that allow direct access, via read()
and write()
, to the character cells of a virtual console's screen buffer.
However, these mechanisms are very much non-portable, and not even general-purpose.
Several platforms, most notably the BSDs and Solaris, don't have them; they differ in their exact mechanics from platform to platform; and even within any given single platform they only apply to the terminal devices that are actually displayed on the machine's display adapter.
(They don't exist at all for serial terminal devices, for pseudo-terminals as used by xterm
and the like, or for the "raw", non-virtualized, terminal device provided by Hurd's /hurd/term
dæmon on /dev/console
.)
PC/MS/DR-DOS provides no system API function for clearing the screen.
Although it has a "CON:
" device that is capable of responding to ECMA-48 control sequences, that device is contained within an optional installable device driver, ANSI.SYS
.
This installable device driver usurps the built-in "CON:
" that PC/MS/DR-DOS contains by default, which does not support ECMA-48 control sequences.
Unlike OS/2, which has one "CON:
" device whose support for ECMA-48 control sequences can be turned on and off at run-time by applications, with (vanilla) PC/MS/DR-DOS one fixes the support for ECMA-48 control sequences at operating system IPL time.
(There are several after-market TSR programs that can load and unload ECMA-48 control sequence support.
But even they cannot switch it on and off whilst a single applications program is running; and they don't come as standard with the operating system.)
PC/MS/DR-DOS programs therefore have two avenues of approach for clearing the screen: directly accessing the video RAM or using firmware API functions.
These two approaches are built into the Borland C/C++ for DOS clrscr()
function, mentioned earlier, which in fact selects between these very two approaches, according to the setting of the directvideo
global variable.
Both approaches have their disadvantages.
Direct access to video RAM in PC/MS/DR-DOS involves far more complexities than direct access to a console screen buffer does on OS/2 or Win32. Whilst OS/2 and Win32 consoles provide an abstraction of an array of character cells, direct access to video RAM hardware on PC/MS/DR-DOS does not. An application performing direct access therefore has to be aware of whether the display adapter is in text or graphics mode, and which particular mode that is. The mode selection determines both the exact mechanism for writing to video RAM and where in the system memory map the video RAM even is. PC/MS/DR-DOS programs have to accommodate monochrome display adapters (and (S)VGA display adapters emulating them), Hercules display adapters, CGA display adapters, EGA adapters in graphics mode, and (S)VGA display adapters in graphics mode, all of which have subtly or indeed blatantly different mechanisms for direct access to the video hardware.
The subject of direct video access by PC/MS/DR-DOS softwares is too extensive for this Frequently Given Answer. There are books on PC/MS/DR-DOS applications programming that devote entire chapters to just this, including lengthy source listings of how to detect what display adapter hardware is present and how to access it in the several modes that it is possible for the hardware to be in. Two of the better ones are:
Of course, the PC/AT firmware was intended to abstract all of this away in the first place. And as long as one doesn't worry too much about graphics modes, it can and does when it comes to clearing the screen. Clearing the screen using the PC/AT firmware API is done in much the same way as with the "console" APIs in OS/2 and Win32, as a matter of fact. One either scrolls the screen buffer by as many lines as it contains, or fills the screen buffer with a single given character and attribute pair; in both cases setting the cursor position, maintained by the firmware, to the top-left-hand corner of the screen as well.
How one accesses the PC/AT firmware API from the C and C++ languages when targetting PC/MS/DR-DOS is entirely compiler-dependent.
The API is not designed to be directly callable as a high-level language function.
That idea came later on in the world of the IBM PC/AT compatible.
Here's a version of the cls()
and gotoxy()
functions, taken from chapter 5 of the aforementioned DOS Programmer's Reference and adapted to OpenWatcom C/C++, which in combination implement the "Scrolling" method of clearing the screen:
void cls () ; #pragma aux cls = \ "push ds" \ "push es" \ "mov ax, 0600h" \ "mov bh, 07h" \ "mov cx, 0000h" \ "mov dx, 1950h" \ "int 10h" \ "pop es" \ "pop ds" \ parm [] \ value [] \ modify [ax bx cd dx] ; void gotoxy(uint8_t x, uint8_t y) ; #pragma aux gotoxy = \ "push ds" \ "push es" \ "mov ah, 02h" \ "mov bh, 00h" \ "int 10h" \ "pop es" \ "pop ds" \ parm [dl] [dh] \ value [] \ modify [ax bx cd dx] ;
Note that this code is hardwired for writing the space character, in white on black, for 80 columns and 25 rows. Parameterizing it is left as an exercise for the reader. Note also that, as with OS/2, the PC/AT firmware API makes no provision for separating the concepts of a screen buffer from a console window, and thus there is no standard "scroll back" convention in PC/MS/DR-DOS programs.