我正在编写一个任务监控,它使用cout更新任务的进度。我想在每行显示一个任务进度,因此我必须回滚几行控制台。
我坚持“几个”因为\b
完成一行的工作,但不会删除行之间的\n
。
我尝试std::cout.seekp(std::cout.tellp() - str.length());
但tellp()
返回-1(失败)。
答案 0 :(得分:20)
您可以cout << '\r';
跳转到当前行的开头,但向上移动是系统特定的。对于Unix,请参阅man termcap
和man terminfo
(并搜索cursor_up
)。在ANSI兼容的终端(例如Unix上可用的大多数现代终端)上,这可以向上移动:cout << "\e[A";
。
请勿尝试在cout
中搜索,大部分时间都无法搜索(除非重定向到文件时)。
正如其他答案中所提到的,使用 ncurses (或 slang )库为Unix上的终端I / O提供了一个很好的抽象。
您可以执行\r
+ clr_eol
:std::cout << "\r\e[K" << std::flush
,而不是填充空格(容易出错,因为不是每个终端都是80个字符)。
答案 1 :(得分:8)
如果可以,请使用输出格式库,例如ncurses;这大大简化了终端操作。
答案 2 :(得分:5)
C和C ++都没有定义这样的东西。您需要明确的终端操作。在Unix上,您可以使用curses。不知道Windows有什么用。
答案 3 :(得分:2)
我知道这是一篇旧帖子,但被接受的并不包括cout通过管道传输到程序或文件的情况,这是我谷歌搜索的首选。以下内容将处理管道和非管道stdout,行为略有不同。
#include <iostream>
#include <functional>
#include <stdio.h>
#ifdef _WIN32
#include <io.h>
#else
#include <unistd.h>
#define _isatty isatty
#define _fileno fileno
#endif
const std::function<void(const size_t&)> progress_printer(_isatty(_fileno(stdout)) == 1 ?
[](const size_t& i) {
std::cout << "\rNumber " << i << std::flush;
} :
[](const size_t& i) {
static std::ios::off_type last(-1);
if(last != -1)
std::cout.seekp(last, std::ios::beg);
last = std::cout.tellp();
std::cout << "Number " << i << std::endl;
}
);
这在Windows上未经测试,但应该可以使用。它的作用是检测文件描述符或者是tty。如果它是那么它只是写&#39; \ r&#39;如果pos自上次打印或换行后没有改变。如果它不是换行符,它会寻找它打印后的最后一个位置。
文件的行为与tty的行为不同。对于文件,如果某些内容在打印之间输出到流,则它可以覆盖部分或全部写入的内容,即使在换行之后也是如此。对于ttys,它只是覆盖当前行开头的字符。
答案 4 :(得分:0)
希望它有所帮助;)[它应该适用于Linux。]
// "\e[0K" Clear line from cursor to the end
cout << "\e[A\r\e[0K"<<what_you_want<<endl;
答案 5 :(得分:0)
您可以使用第一个系统(“”);因为您可以使用\ e [A(Dev-C ++)或\ u001B [A(Visual Studio)
#include <iostream>
using namespace std;
int main()
{
system(" ");
string Input;
do
{
cout << "[#][\e[s";
cin >> Input;
cout << "[\e[u" << Input << "]"<<endl;
} while (2==2);
return 0;
}