在Windows上使用C清除命令提示符

时间:2014-10-02 18:16:17

标签: c windows ansi-escape

是否可以在命令提示符下使用C on Windows清除输出?

例如,在linux上我可以做到

printf("\033[2J");

但据我所知,Windows无法识别ANSI转义码 感谢。

编辑:我想我还需要在清除之后将光标恢复到下一个输出的0,0 ...

2 个答案:

答案 0 :(得分:5)

在Windows上有很多方法可以做到这一点。

您加入conio.h并致电_clrscr();

或者您可以致电system("cls");

答案 1 :(得分:4)

作为conio.h或系统调用的替代方案,只是一个实现(我认为类似于conio库),它是如何在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;
}

已修改以关注评论

经过一些测试,这是(或多或少)cls命令在cmd.exe中的实现方式(至少在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;
}

不是调用api函数来填充具有所需字符和属性的缓冲区,而是滚动整个缓冲区,并且当滚动操作填充空区域时,缓冲区被初始化。所有人都在一个api电话。

已编辑这是ansi转义序列的“等效”代码。清除控制台但保留历史记录。这不会初始化整个控制台缓冲区,只能确保控制台窗口干净,滚动可见窗口或缓冲区(如果需要)。

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