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

Как обновить печатное сообщение в терминале без переиздания (Linux)

Я хочу сделать индикатор выполнения для моего приложения терминала, который будет работать примерно так:

 [XXXXXXX       ] 

который даст визуальную индикацию того, сколько времени осталось до завершения процесса.

Я знаю, что могу делать что-то вроде печати все больше и больше X, добавляя их в строку, а затем просто printf, но это будет выглядеть так:

 [XXXXXXX       ] 
 [XXXXXXXX      ] 
 [XXXXXXXXX     ] 
 [XXXXXXXXXX    ] 

или что-то в этом роде (очевидно, вы можете играть с интервалом.) Но это не визуально эстетично. Есть ли способ обновить напечатанный текст в терминале с новым текстом без переиздания? Это все под linux, С++.

4b9b3361

Ответ 1

попробуйте использовать \r вместо \n при печати новой "версии".

for(int i=0;i<=100;++i) printf("\r[%3d%%]",i);
printf("\n");

Ответ 2

Я бы сказал, что для таких вещей будет использоваться библиотека, такая как ncurses. curses помогает перемещать курсор вокруг экрана и рисовать текст и т.д.

NCurses

Ответ 3

Что-то вроде этого:

std::stringstream out;
for (int i = 0; i< 10; i++)
{
  out << "X";
  cout << "\r" << "[" << out.str() << "]";
}

Скрытый бит - это символ возврата каретки "\ r", который заставляет курсор перемещаться в начало строки, не переходя к следующей строке.

Ответ 4

Другие уже указали, что вы можете использовать \r для возврата к началу текущей строки и перезаписать всю строку.

Другая возможность заключается в использовании символа backspace ( "\ b" ) для удаления нескольких пробелов и перезаписи только тех пробелов. Это может иметь несколько преимуществ. Во-первых, он, очевидно, избегает необходимости регенерировать все в линии, что иногда может быть слегка болезненным (хотя это довольно необычно). Во-вторых, он может избежать некоторой боли при отображении данных, которые (на одном примере) уменьшаются по размеру, когда вы его пишете, например, если вы показываете обратный отсчет от 100 до 0, с \r вы должны быть осторожно переписывая всю предыдущую длину, или ваш обратный отсчет будет идти от (например) от 100 до 990 (т.е. оставит прежний "0" неповрежденным).

Обратите внимание, однако, что, хотя back-space внутри строки нормально работает, backspace в начале строки может или не может перемещать позицию курсора/записи назад в предыдущую строку. Для большинства практических целей вы можете перемещаться только в одной строке.

Ответ 5

'\ r' выполнит возврат каретки. Представьте, что принтер выполняет возврат каретки без перевода строки ('\n'). Это вернет точку записи обратно к началу строки... затем перепечатайте обновленный статус поверх исходной строки.

Ответ 6

Это другой язык, но этот вопрос может вам помочь. В принципе, escape-символ\r (возврат каретки, в отличие от \n Newline) возвращает вас к началу вашей текущей печатной строки, чтобы вы могли перезаписать то, что вы уже напечатали.

Ответ 7

Другой вариант - просто напечатать один символ за раз. Как правило, stdout является строковым буфером, поэтому вам нужно вызвать fflush (stdout) -

for(int i = 0; i < 50; ++i) {
   putchar('X'); fflush(stdout);
   /* do some stuff here */
}
putchar('\n');

Но это не имеет прекрасного завершения "]", который указывает на завершение.