Как говорится в ответе Натана Эрнста, если вам нужен надежный и правильный способ сделать это, используйте проклятия, в частности ncurses< /а>.
Если вам нужен простой хакерский способ, который работает, продолжайте...
Терминалы командной строки для Linux, UNIX, MacOS, Windows и т. д., как правило, поддерживают небольшой набор основных управляющих символов ASCII, включая десятичный символ 13, известный как возврат каретки и закодировано в C++ как '\r' или эквивалентно в восьмеричном '\015' или шестнадцатеричном '\x0D' - указание терминалу вернуться к начало линии.
Что вы обычно хотите сделать, это...
int line_width = getenv("COLUMNS") ? atoi(getenv("COLUMNS")) : 80;
std::string spaces{line_width - 1, ' '};
for (const auto& filename : filenames) {
std::cout << '\r' << spaces << '\r' << filename << std::flush;
process_file(filename);
}
std::cout << std::endl; // move past last filename...
При этом используется строка пробелов для перезаписи старого имени файла перед записью следующего, поэтому, если у вас более короткое имя файла, вы не видите завершающие символы из более ранних более длинных имен файлов.
std::flush
гарантирует, что программа C++ вызовет функцию ОС write()
для отправки текст на терминал перед началом обработки файла. Без этого текст, необходимый для обновления — \r
, пробелы, \r
и имя файла — будет добавлен в буфер и записан только в ОС — например, в 4k куски — когда буфер заполнен, поэтому отображаемое имя файла будет отставать от фактического обрабатываемого файла на десятки файлов. Кроме того, скажем, буфер равен 4 КБ — 4096 байт — и в какой-то момент у вас буферизовано 4080 байт, затем выведите текст для следующего имени файла: в итоге вы получите \r
и 15 пробелов в буфере, который при автоматической очистке будет в конечном итоге стереть первые 15 символов в строке на экране и оставить остальную часть предыдущего имени файла (если оно было длиннее 15 символов), а затем подождать, пока буфер снова не заполнится, прежде чем обновлять экран (все еще бессистемно).
Последний std::endl
просто перемещает курсор из строки, где вы печатали имена файлов, чтобы вы могли написать «все готово» или просто оставить main()
и вывести приглашение оболочки на красивую чистую строку, вместо того, чтобы потенциально перезаписывать часть вашего файла. последнее имя файла (отличные оболочки, такие как zsh, проверяют это).
person
Tony Delroy
schedule
15.05.2020