如何从cout回滚线?

时间:2010-07-18 20:10:52

标签: c++ cout

我正在编写一个任务监控,它使用cout更新任务的进度。我想在每行显示一个任务进度,因此我必须回滚几行控制台。

我坚持“几个”因为\b完成一行的工作,但不会删除行之间的\n

我尝试std::cout.seekp(std::cout.tellp() - str.length());tellp()返回-1(失败)。

6 个答案:

答案 0 :(得分:20)

您可以cout << '\r';跳转到当前行的开头,但向上移动是系统特定的。对于Unix,请参阅man termcapman terminfo(并搜索cursor_up)。在ANSI兼容的终端(例如Unix上可用的大多数现代终端)上,这可以向上移动:cout << "\e[A";

请勿尝试在cout中搜索,大部分时间都无法搜索(除非重定向到文件时)。

正如其他答案中所提到的,使用 ncurses (或 slang )库为Unix上的终端I / O提供了一个很好的抽象。

您可以执行\r + clr_eolstd::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;
}

enter image description here