Подтвердить что ты не робот

Стереть текущую печатную консольную линию

Как я могу удалить текущую печатную консольную строку в C? Я работаю над системой Linux. Например -

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

Я хочу напечатать сообщение на той же строке вместо приветствия.

4b9b3361

Ответ 1

Вы можете использовать коды экранов VT100. Большинство терминалов, включая xterm, знают VT100. Для стирания строки это ^[[2K. В C это дает:

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

Ответ 2

Вы можете использовать \r (возврат каретки), чтобы вернуть курсор в начало строки:

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

Это будет показываться в одной строке. Тем не менее, он не будет стирать существующие символы, и потому что bye короче, чем привет, вы попадете в beelo. Чтобы стереть его, вы можете сделать свой новый шрифт дольше, чтобы перезаписать дополнительные символы:

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

Или сначала удалите его с помощью нескольких пробелов, затем напечатайте новую строку:

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

Это будет печатать привет, затем перейдите к началу строки и перезапишите его пробелами, затем вернитесь к началу и распечатайте.

Ответ 3

Некоторые стоящие тонкости...

\33[2K стирает всю строку, на которой курсор находится в данный момент

\033[A перемещает курсор вверх на одну строку, но в тот же столбец, а не на начало строки

\r приводит курсор к началу строки (r для перемотки назад), но не удаляет что-либо

В xterm специально, я пробовал ответы, упомянутые выше, и единственный способ, которым я нашел стирание строки и начать снова в начале, - это последовательность (из комментария выше, опубликованного @Stephan202, а также @vlp и @mantal) \33[2K\r

В примечании к реализации, чтобы заставить его работать должным образом, например, в сценарии обратного отсчета, поскольку я не использовал новый символ строки '\n' в конце каждого fprintf(), поэтому мне приходилось fflush() поток каждый раз (чтобы дать вам некоторый контекст, я начал xterm с помощью вилки на Linux-машине без перенаправления stdout, я просто писал буферный указатель 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);
}

Ответ 4

Вы можете удалить строку, используя \b

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

Ответ 5

Обычно, когда у вас есть символ "\ r" в конце строки, возвращается только возврат каретки без какой-либо новой строки. Если у вас есть следующее:

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

вывод будет:

barooo

Одна вещь, которую я могу предложить (возможно, обходной путь), - это иметь фиксированную строку с фиксированным размером NULL, которая инициализируется всеми символами пробега, заканчивающаяся на "\ r" (каждый раз перед печатью), а затем используйте команду 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 всегда был по крайней мере на один меньше длины, чем str, но вы получаете основную идею.

Ответ 6

i выполняет итерацию через слова массива char. 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;
}

Ответ 7

Этот script жестко запрограммирован для вашего примера.

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

Нажмите здесь для источника.

Ответ 8

существует простой трюк, в котором вы можете работать здесь, но перед началом печати вам нужно подготовить, вы должны указать, что когда-либо хотите распечатать в переменной, а затем распечатать, чтобы вы знали длину, чтобы удалить строку. пример.

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

}

Ответ 9

Просто нашел этот старый поток, искал какую-то escape-последовательность, чтобы очистить фактическую строку.

Довольно забавно, что никто не пришел к мысли (или я пропустил это), что 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, кажется, я должен придерживаться этого решения

Ответ 10

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

Что будет делать приведенная выше команда:

  1. Он напечатает привет и курсор останется на "o" (используя\c)

  2. Потом будет ждать 1 сек (сон 1)

  3. Тогда он заменит привет с пока. (Используя\r)

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

Ответ 11

в Windows 10 можно использовать стиль VT100, активировав режим VT100 в текущей консоли, чтобы использовать escape-последовательности следующим образом:

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

}

см. следующую ссылку: windows VT100