我正在编写一个任务监控,它使用 cout 更新任务的进度。我想每行显示一个任务进度,因此我必须回滚控制台的几行。
我坚持“几个”,因为\b
只为一行完成这项工作,但不会\n
在两行之间擦除。
我试过std::cout.seekp(std::cout.tellp() - str.length());
但tellp()
返回-1(失败)。
您可以cout << '\r';
跳到当前行的开头,但向上移动是系统特定的。对于 Unix,请参见man termcap
和man terminfo
(并搜索cursor_up
)。在 ANSI 兼容的终端(例如 Unix 上可用的大多数现代终端)上,这可以向上移动:cout << "\e[A";
.
不要尝试在 中搜索cout
,大多数时候它是不可搜索的(重定向到文件时除外)。
正如其他答案中提到的,使用ncurses(或slang)库为 Unix 上的终端 I/O 提供了一个很好的抽象。
\r
您可以使用+ clr_eol
:代替填充空格(这很容易出错,因为并非每个终端都是 80 个字符宽)std::cout << "\r\e[K" << std::flush
。
如果可以,请使用输出格式库,例如ncurses ;这大大简化了终端操作。
C 和 C++ 都没有定义类似的东西。您需要明确的终端操作。在 Unix 上,您可以使用curses。不知道 Windows 有什么。
我知道这是一个旧帖子,但接受的不包括 cout 被管道传输到程序或文件的情况,这是我的谷歌搜索的顶部。以下将处理管道和非管道标准输出,其行为略有不同。
#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。如果是,那么如果自上次打印后 pos 没有更改或换行,它只会写入 '\r'。如果它不是换行符,它会寻找打印后的最后一个位置。
它对文件的行为与对 tty 的行为不同。对于一个文件,如果某些内容在打印之间输出到流,那么即使在换行符之后,它也可以覆盖部分或全部写入的内容。对于 ttys,它只是覆盖当前行开头的字符。
您可以使用第一个系统(“”);因为您可以使用 \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;
}
希望它有所帮助;) [它应该在 Linux 上工作。]
// "\e[0K" Clear line from cursor to the end
cout << "\e[A\r\e[0K"<<what_you_want<<endl;