C++ 如何从 cout 回滚行?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3277058/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 12:30:25  来源:igfitidea点击:

How to rollback lines from cout?

c++cout

提问by Mister Mystère

I'm coding a task monitoring, which updates tasks' progress using cout. I'd like to display one task progress per line, therefore I have to rollback several lines of the console.

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

I insist on "several" because \bdoes the job for one line, but does not erase \nbetween lines.

我坚持“几个”,因为\b可以为一行完成工作,但不会在行\n之间擦除。

I tried std::cout.seekp(std::cout.tellp() - str.length());but tellp()returns -1 (failure).

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

回答by pts

You can do cout << '\r';to jump to the beginning of the current line, but moving upwards is system-specific. For Unix, see man termcapand man terminfo(and search for cursor_up). On ANSI-compatible terminals (such as most modern terminals available on Unix), this works to move up: cout << "\e[A";.

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

Don't try seeking in cout, it's unseekable most of the time (except when redirected to a file).

不要尝试寻找 in cout,它在大多数情况下是不可搜索的(除非重定向到文件)。

As mentioned in other answers, using the ncurses(or slang) library provides a good abstraction for terminal I/O on Unix.

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

Instead of filling with spaces (which is error-prone, because not every terminal is 80 characters wide), you can do \r+ clr_eol: std::cout << "\r\e[K" << std::flush.

而不是填充空格(这很容易出错,因为不是每个终端都是 80 个字符宽),你可以做\r+ clr_eol: std::cout << "\r\e[K" << std::flush

回答by You

Use an output formatting library such as ncursesif you can; this simplifies terminal manipulation significantly.

如果可以,请使用输出格式库,例如ncurses;这大大简化了终端操作。

回答by Nikolai Fetissov

Neither C nor C++ define anything like that. You need explicit terminal manipulation. On Unix you can use curses. Have no idea what's there for Windows.

C 和 C++ 都没有定义类似的东西。您需要明确的终端操作。在 Unix 上你可以使用curses。不知道 Windows 有什么。

回答by Erroneous

I know this is an old post, but the accepted doesn't cover cases where cout is piped to a program or file and this is the top of my google searches. The following will handle both piped and non-piped stdout with slightly different behavior.

我知道这是一篇旧帖子,但接受的内容不包括将 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;
    }
);

This is untested on windows, but should work. What it does is detect if the file descriptor or is a tty. If it is then it just writes '\r' if the pos hasn't changed since last time it printed or a newline. If it isn't a newline, it seeks to the last place it was after it printed.

这在 Windows 上未经测试,但应该可以工作。它的作用是检测文件描述符是否为 tty。如果是,那么它只是写 '\r' 如果自上次打印或换行以来 pos 没有改变。如果它不是换行符,它会寻找它打印后的最后一个位置。

It behaves differently for files than for tty. For a file, if something outputs to the stream between prints then it can overwrite some or all of what was written even after newlines. For ttys it just overwrites the chars at the beginning of the current line.

它对文件的行为与对 tty 的行为不同。对于文件,如果某些内容输出到打印之间的流,那么即使在换行符之后它也可以覆盖部分或全部写入的内容。对于 ttys,它只是覆盖当前行开头的字符。

回答by Alex Xu

Hope it helps ;) [It should work on Linux.]

希望它有所帮助;) [它应该可以在 Linux 上运行。]

// "\e[0K" Clear line from cursor to the end
cout << "\e[A\r\e[0K"<<what_you_want<<endl;

回答by Julian David Trejos Rueda

You can use first system(" "); for you can use \e[A (Dev-C++) or \u001B[A (Visual Studio)

您可以使用第一个 system(" "); 因为你可以使用 \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

在此处输入图片说明