Clear command prompt with C on windows

10,161

Solution 1

There are many way to do that on windows.

You include conio.h and call _clrscr();

Or you can call system("cls");

Solution 2

Just as an alternative to the conio.h or the system call, just an implementation (i suposse that similar to the conio library) of how it is supossed to be done in windows.

#include <windows.h>

int main(void){
    HANDLE hStdout; 
    CONSOLE_SCREEN_BUFFER_INFO csbiInfo; 
    DWORD dwCells, dwWritten;

    // Get console handle
    hStdout = GetStdHandle(STD_OUTPUT_HANDLE);     

    // Retrieve console information
    if (GetConsoleScreenBufferInfo(hStdout, &csbiInfo)) {

        // Calc console cells
        dwCells = csbiInfo.dwSize.Y * csbiInfo.dwSize.X;

        // Initialize cursor position
        csbiInfo.dwCursorPosition.X = 0;
        csbiInfo.dwCursorPosition.Y = 0;

        // Replace all characters in console with spaces
        FillConsoleOutputCharacterA( hStdout, ' ', dwCells, csbiInfo.dwCursorPosition,  &dwWritten);
        // Replace all attributes in console with the default
        FillConsoleOutputAttribute( hStdout, csbiInfo.wAttributes, dwCells, csbiInfo.dwCursorPosition, &dwWritten );
        // Position the cursor
        SetConsoleCursorPosition( hStdout, csbiInfo.dwCursorPosition );
    }

    return 0;
}

edited to follow comments

After some testing, this is (more or less) how the cls command is implemented in cmd.exe (at least in windows 7 64)

#include <windows.h>

int main(void){
    HANDLE hStdout; 
    CONSOLE_SCREEN_BUFFER_INFO csbiInfo; 
    COORD destinationPoint;
    SMALL_RECT sourceArea;
    CHAR_INFO Fill;

    // Get console handle
    hStdout = GetStdHandle(STD_OUTPUT_HANDLE);     

    // Retrieve console information
    if (GetConsoleScreenBufferInfo(hStdout, &csbiInfo)) {
        // Select all the console buffer as source
        sourceArea.Top = 0;
        sourceArea.Left = 0;
        sourceArea.Bottom = csbiInfo.dwSize.Y - 1;
        sourceArea.Right = csbiInfo.dwSize.X - 1;

        // Select a place out of the console to move the buffer
        destinationPoint.X = 0;
        destinationPoint.Y = 0 - csbiInfo.dwSize.Y;

        // Configure fill character and attributes
        Fill.Char.AsciiChar = ' ';
        Fill.Attributes =  csbiInfo.wAttributes;

        // Move all the information out of the console buffer and init the buffer
        ScrollConsoleScreenBuffer( hStdout, &sourceArea, NULL, destinationPoint, &Fill);

        // Position the cursor
        destinationPoint.X = 0;
        destinationPoint.Y = 0;
        SetConsoleCursorPosition( hStdout, destinationPoint );
    }

    return 0;
}

Instead of call the api functions to fill the buffer with the required character and attribute, the full buffer is scrolled out and, as the scroll operation fills the empty area, the buffer get initialized. All in one api call.

edited This is the "equivalent" code to the ansi escape sequence. Clear the console but keeping the history. This does not initialize the full console buffer, only ensures the console window is clean, scrolling the visible window or the buffer if needed.

#include <windows.h>

int main(void){
    HANDLE hStdout; 
    CONSOLE_SCREEN_BUFFER_INFO csbiInfo; 
    COORD destinationPoint;
    SMALL_RECT sourceArea;
    CHAR_INFO Fill;
    SHORT delta, end;

    // Get console handle
    hStdout = GetStdHandle(STD_OUTPUT_HANDLE);     

    // Retrieve console information
    if (GetConsoleScreenBufferInfo(hStdout, &csbiInfo)) {

        // How many lines needs the window to be moved to be clear
        delta = (csbiInfo.dwCursorPosition.Y) - csbiInfo.srWindow.Top;

        // Where the bottom of the window will fall after moving
        end = csbiInfo.srWindow.Bottom + delta;

        // If the window get out of the console buffer, it is necessary to scroll the buffer
        if (end >= csbiInfo.dwSize.Y){
            // Select all the console buffer as source
            sourceArea.Top = 0;
            sourceArea.Left = 0;
            sourceArea.Bottom = csbiInfo.dwSize.Y-1;
            sourceArea.Right = csbiInfo.dwSize.X-1;

            // Select the target point for the movement
            destinationPoint.X = 0;
            destinationPoint.Y = 0 - delta ;

            // Configure fill character and attributes for the empty area
            Fill.Char.AsciiChar = ' ';
            Fill.Attributes =  csbiInfo.wAttributes;

            // Scroll the buffer and init the end zone
            ScrollConsoleScreenBuffer( hStdout, &sourceArea, NULL, destinationPoint, &Fill);

            // Adjust new cursor position
            destinationPoint.X = 0;
            destinationPoint.Y = csbiInfo.dwSize.Y - (csbiInfo.srWindow.Bottom - csbiInfo.srWindow.Top + 1);

        } else {
            // No buffer scroll is needed. Adjust the new cursor position
            destinationPoint.X = 0;
            destinationPoint.Y = csbiInfo.dwCursorPosition.Y + 1;
        }

        // In any case, the visible window needs to be moved depending on the new cursor position
        sourceArea.Top = destinationPoint.Y;
        sourceArea.Left = destinationPoint.X;
        sourceArea.Bottom = destinationPoint.Y + (csbiInfo.srWindow.Bottom - csbiInfo.srWindow.Top + 1) -1 ;
        sourceArea.Right = csbiInfo.dwSize.X-1;

        // Place the visible window in the required place over the buffer
        SetConsoleWindowInfo(hStdout, TRUE, &sourceArea);

        // Place the cursor in its final position
        SetConsoleCursorPosition( hStdout, destinationPoint );
    }

    return 0;
}
Share:
10,161

Related videos on Youtube

Toby
Author by

Toby

Updated on September 15, 2022

Comments

  • Toby
    Toby over 1 year

    Is it possible to clear the output at the command prompt using C on windows?

    For example, on linux I could do

    printf("\033[2J");
    

    But as far as I know windows doesn't recognise the ANSI escape codes Thanks.

    EDIT: I guess I'll also need to get the cursor back to 0,0 fo r the next output after the clear...

    • Carl Norum
      Carl Norum over 9 years
      Any answer will depend on what terminal environment you run your program in. Do you have some more details?
  • Rustam
    Rustam over 9 years
    _clrscr(); or clrscr();
  • Eryk Sun
    Eryk Sun over 9 years
    The cls command takes a different route. It also grabs the screen buffer info to get the buffer size and fill-character attributes. Then it calls ScrollConsoleScreenBuffer to scroll the screen completely out of the buffer, i.e. to a destination of (0, 0 - dwSize.Y). A more useful command (call it clear.exe) would use the window size in srWindow to shift the buffer by only a single display page. This would preserve the output history when using a screen layout with (many) more rows than the window.
  • Eryk Sun
    Eryk Sun over 9 years
    FYI, clrscr is in C++Builder, but not in VC++.
  • MC ND
    MC ND over 9 years
    @eryksun, I have readed it (and the docs) and i still do not see the need for the ScrollConsoleScreenBuffer, sorry, maybe i am missing something. Anyway, rereading the question and the effect of the ansi escape, i think you are right with the clear.exe approach. I have not a C compiler at hand to test, but when i can i will add the corresponding code.
  • MC ND
    MC ND over 9 years
    @eryksun, done. I've included a closer version to what Microsoft does to clean the console, just one api call to clean the console and one api call to position the cursor. Also the clear.exe code has been included.
  • Eryk Sun
    Eryk Sun over 9 years
    This should be the accepted answer. clear.exe works like clear or ^J in a Unix terminal.