program tip

현재 인쇄 된 콘솔 줄 지우기

radiobox 2020. 12. 3. 07:44
반응형

현재 인쇄 된 콘솔 줄 지우기


C에서 현재 인쇄 된 콘솔 줄을 어떻게 지울 수 있습니까? Linux 시스템에서 작업 중입니다. 예를 들면-

printf("hello");
printf("bye");

hello 대신 같은 줄에 bye를 인쇄하고 싶습니다.


VT100 이스케이프 코드를 사용할 수 있습니다 . xterm을 포함한 대부분의 터미널은 VT100을 인식합니다. 줄을 지우려면 이것은입니다 ^[[2K. C에서는 다음을 제공합니다.

printf("%c[2K", 27);

\r( 캐리지 리턴 )을 사용하여 커서를 줄의 시작 부분으로 되돌릴 수 있습니다 .

printf("hello");
printf("\rbye");

이것은 같은 줄에 작별 인사인쇄 합니다. 그래도 기존 문자는 지워지지 않으며 byehello 보다 짧기 때문에 byelo로 끝납니다 . 지우려면 새 인쇄물을 더 길게 만들어 추가 문자를 덮어 쓸 수 있습니다.

printf("hello");
printf("\rbye  ");

또는 먼저 몇 개의 공백을 사용하여 지운 다음 새 문자열을 인쇄하십시오.

printf("hello");
printf("\r          ");
printf("\rbye");

즉 인쇄됩니다 안녕하세요 다시 처음으로 돌아가서 인쇄, 다음 줄의 시작 부분으로 이동 공간으로 덮어, 안녕 .


가치있는 미묘함 ...

\33[2K 현재 커서가있는 전체 줄을 지 웁니다.

\033[A커서를 한 줄 위로 이동하지만 같은 열, 즉 줄의 시작 부분이 아닙니다.

\r커서를 줄의 시작 부분으로 가져 오지만 (r은 되감기) 아무것도 지우지 않습니다 .

특히 xterm에서는 위에서 언급 한 답변을 시도했으며 줄을 지우고 처음부터 다시 시작하는 유일한 방법은 시퀀스입니다 (@ Stephan202와 @vlp 및 @mantal이 게시 한 위의 주석에서) \33[2K\r

구현 메모에서 예를 들어 카운트 다운 시나리오에서 제대로 작동하도록하려면 '\n'각 끝에 줄 바꿈 문자 사용하지 않았기 fprintf()때문에 fflush()매번 스트림으로 이동 해야했습니다 (일부 컨텍스트를 제공하기 위해 xterm은 stdout을 리디렉션하지 않고 Linux 시스템에서 포크를 사용하여 버퍼링 된 FILE 포인터 fdfile에 비 블로킹 파일 설명자를 사용하여 필자의 경우 의사 터미널 주소에 앉아있었습니다. /dev/pts/21)

fprintf(fdfile, "\33[2K\rT minus %d seconds...", i);
fflush(fdfile);

줄을 지우는 데 \ 33 [2K 시퀀스를 모두 사용하고 줄 \r의 시작 부분에 커서를 재배치하기 위해 되감기 시퀀스를 사용했습니다. 나는 끝에 줄 바꿈 문자가 없기 때문에 fflush()매번마다 fprintf()해야했습니다 '\n'. fflush ()가 필요없는 동일한 결과는 한 줄 위로 올라 가기 위해 추가 시퀀스가 ​​필요합니다.

fprintf(fdfile, "\033[A\33[2K\rT minus %d seconds...\n", i);

쓰려는 줄 바로 위에있는 줄에 무언가가 있으면 첫 번째 fprintf ()로 덮어 쓰게됩니다. 한 줄 위로 첫 번째 이동을 허용하려면 위에 추가 줄을 남겨야합니다.

i = 3;
fprintf(fdfile, "\nText to keep\n");
fprintf(fdfile, "Text to erase****************************\n");
while(i > 0) { // 3 second countdown
    fprintf(fdfile, "\033[A\33[2KT\rT minus %d seconds...\n", i);
    i--;
    sleep(1);
}

\ b를 사용하여 줄을 삭제할 수 있습니다.

printf("hello");
int i;
for (i=0; i<80; i++)
{
  printf("\b");
}
printf("bye");

일반적으로 문자열 끝에 '\ r'이 있으면 개행없이 캐리지 리턴 만 인쇄됩니다. 다음이있는 경우 :

printf("fooooo\r");
printf("bar");

출력은 다음과 같습니다.

barooo

내가 제안 할 수있는 한 가지 (해결 방법 일 수 있음)는 모든 공백 문자로 초기화되고 '\ r'(인쇄 전 매번)로 끝나는 NULL로 끝나는 고정 크기 문자열을 보유한 다음 strcpy를 사용하여 문자열을 복사하는 것입니다. (개행없이), 따라서 모든 후속 인쇄는 이전 문자열을 덮어 씁니다. 이 같은:

char str[MAX_LENGTH];        
// init str to all spaces, NULL terminated with character as '\r'
strcpy(str, my_string);       // copy my_string into str
str[strlen(my_string)] = ' '; // erase null termination char
str[MAX_LENGTH - 1] = '\r';
printf(str);

오류 검사를 수행하여 my_string항상 길이가 .NET보다 적어도 하나 짧아 str지지만 기본 아이디어를 얻을 수 있습니다.


i문자 배열 단어를 반복합니다. j단어 길이를 추적합니다. "\b \b"줄을 넘기는 동안 단어를 지 웁니다.

#include<stdio.h>

int main()
{
    int i = 0, j = 0;

    char words[] = "Hello Bye";

    while(words[i]!='\0')
    {
        if(words[i] != ' ') {
            printf("%c", words[i]);
        fflush(stdout);
        }
        else {
            //system("ping -n 1 127.0.0.1>NUL");  //For Microsoft OS
            system("sleep 0.25");
            while(j-->0) {
                printf("\b \b");
            }
        }

        i++;
        j++;
    }

printf("\n");                   
return 0;
}

이 스크립트는 예제를 위해 하드 코딩되었습니다.

#include <stdio.h>

int main ()
{

    //write some input  
    fputs("hello\n",stdout);

    //wait one second to change line above
    sleep(1);

    //remove line
    fputs("\033[A\033[2K",stdout);
    rewind(stdout);

    //write new line
    fputs("bye\n",stdout);

    return 0;
}

소스를 보려면 여기를 클릭하십시오 .


여기에서 작업 할 수있는 간단한 트릭이 있지만 인쇄하기 전에 준비가 필요합니다. 인쇄하려는 내용을 변수에 넣은 다음 인쇄하여 문자열을 제거 할 길이를 알아야합니다. 여기에 예제가 있습니다.

#include <iostream>
#include <string> //actually this thing is not nessasory in tdm-gcc

using namespace  std;

int main(){

//create string variable

string str="Starting count";

//loop for printing numbers

    for(int i =0;i<=50000;i++){

        //get previous string length and clear it from screen with backspace charactor

        cout << string(str.length(),'\b');

        //create string line

        str="Starting count " +to_string(i);

        //print the new line in same spot

        cout <<str ;
    }

}

방금이 오래된 스레드를 찾았고 실제 줄을 비울 어떤 종류의 이스케이프 시퀀스를 찾습니다.

printf가 쓰여진 문자 수를 반환한다는 생각에 아무도 오지 않았다는 것은 매우 재미 있습니다. 따라서 '\ r'+ printf가 반환 된만큼의 공백 문자를 인쇄하면 이전에 작성된 텍스트를 정확히 비울 것입니다.

int BlankBytes(int Bytes)
{
                char strBlankStr[16];

                sprintf(strBlankStr, "\r%%%is\r", Bytes);
                printf(strBlankStr,"");

                return 0;
}

int main(void)
{
                int iBytesWritten;
                double lfSomeDouble = 150.0;

                iBytesWritten = printf("test text %lf", lfSomeDouble);

                BlankBytes(iBytesWritten);

                return 0;
}

VT100을 사용할 수 없어서 그 솔루션을 고수해야 할 것 같습니다


echo -e "hello\c" ;sleep 1 ; echo -e "\rbye  "

위의 명령이 수행하는 작업 :

  1. hello를 인쇄하고 커서는 "o"에 유지됩니다 (\ c 사용).

  2. 그런 다음 1 초 동안 대기합니다 (슬립 1).

  3. 그런 다음 hello를 bye로 대체합니다 (\ r 사용).

NOTE : Using ";", We can run multiple command in a single go.


under windows 10 one can use VT100 style by activating the VT100 mode in the current console to use escape sequences as follow :

#include <windows.h>
#include <iostream>

#define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004
#define DISABLE_NEWLINE_AUTO_RETURN  0x0008

int main(){

  // enabling VT100 style in current console
  DWORD l_mode;
  HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
  GetConsoleMode(hStdout,&l_mode)
  SetConsoleMode( hStdout, l_mode |
            ENABLE_VIRTUAL_TERMINAL_PROCESSING |
            DISABLE_NEWLINE_AUTO_RETURN );

  // create a waiting loop with changing text every seconds
  while(true) {
    // erase current line and go to line begining 
    std::cout << "\x1B[2K\r";
    std::cout << "wait a second .";
    Sleep(1);
    std::cout << "\x1B[2K\r";
    std::cout << "wait a second ..";
    Sleep(1);
    std::cout << "\x1B[2K\r";
    std::cout << "wait a second ...";
    Sleep(1);
    std::cout << "\x1B[2K\r";
    std::cout << "wait a second ....";
 }

}

see following link : windows VT100

참고URL : https://stackoverflow.com/questions/1508490/erase-the-current-printed-console-line

반응형