如何从cout回滚行?

发布于 2024-09-10 13:01:11 字数 236 浏览 6 评论 0原文

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

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

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

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.

I insist on "several" because \b does the job for one line, but does not erase \n between lines.

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

江心雾 2024-09-17 13:01:11

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

不要尝试在 cout 中查找,大多数情况下它是不可查找的(重定向到文件时除外)。

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

您可以执行 \r + clr_eol: std:: ,而不是填充空格(这很容易出错,因为并非每个终端都是 80 个字符宽)。计算<< “\r\e[K”<< std::flush

You can do cout << '\r'; to jump to the beginning of the current line, but moving upwards is system-specific. For Unix, see man termcap and 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";.

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

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

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.

烟燃烟灭 2024-09-17 13:01:11

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

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

蘸点软妹酱 2024-09-17 13:01:11

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

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.

栖迟 2024-09-17 13:01:11

我知道这是一篇旧文章,但接受的内容不包括 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,它只是覆盖当前行开头的字符。

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.

#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.

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.

伪装你 2024-09-17 13:01:11

您可以使用第一个系统(“”);因为您可以使用 \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;
}

输入图像此处描述

You can use first system(" "); for you can use \e[A (Dev-C++) or \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

大姐,你呐 2024-09-17 13:01:11

希望它有帮助;) [它应该在 Linux 上工作。]

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

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

// "\e[0K" Clear line from cursor to the end
cout << "\e[A\r\e[0K"<<what_you_want<<endl;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文