【问题标题】:C++ Console Progress IndicatorC++ 控制台进度指示器
【发布时间】:2010-11-28 08:07:23
【问题描述】:

为正在执行的任务实现基于控制台的进度指示器的简单方法是什么,但我无法预计需要多长时间?

当我在 Clipper 中编码时,我曾经这样做过,这只是遍历字符 '/'、'-'、'\'、'|' 的问题并将它们定位在同一个地方。

任何方式/链接/库在 C++ 中执行此操作(或类似的东西)?

目标是 *nix 环境。

编辑:

  • 将标题更改为更加连贯和通用;
  • 添加了目标环境。

【问题讨论】:

  • 是什么阻止你在 C++ 控制台应用程序中做同样的事情?
  • @Tal:我是 C++ 和控制台应用程序的新手,所以我可以使用元代码或关于该主题的良好链接来指点我正确的方向。

标签: c++ linux console


【解决方案1】:

一个非常简单的方法是打印一个字符串,后跟一个'\r' 字符。那是回车本身,在大多数控制台上,它将光标返回到行首而不向下移动。这允许您覆盖当前行。

如果您正在写入 stdout 或 cout 或 clog,请记住 fflush 或 std::flush 流以使其立即输出该行。如果您正在写入 stderr 或 cerr,则流是无缓冲的,所有输出都是即时的(并且效率低下)。

一个更复杂的方法是使用像curses这样的屏幕绘图库。 Windows 控制台有一些其他方法可以将它们设置为直接屏幕书写,但我不知道它们是什么。

【讨论】:

  • 谢谢 Zan,'\r' 提示听起来值得一试!
  • 正如 Zan 所建议的,我会使用诅咒。快速搜索“诅咒教程”将为您提供所需的内容...
  • \r 解决方案有效,正是我所需要的 - 最简单的情况。
  • 如果要使用特定于 Windows 的解决方案,则无需打扰 conio.h(因为它是特定于平台的) - 只需使用 Win32 API 控制台函数。
【解决方案2】:

你可以试试这样的:

void
spinner(int spin_seconds) {
    static char const spin_chars[] = "/-\\|";
    unsigned long i, num_iterations = (spin_seconds * 10);
    for (i=0; i<num_iterations; ++i) {
        putchar(spin_chars[i % sizeof(spin_chars)]);
        fflush(stdout);
        usleep(100000);
        putchar('\b');
    }
}

当然,这是非标准的,因为 usleep() 是亚秒级的,我不确定是否有任何保证 \b 会擦除字符,但它适用于大多数平台。如果\b 不起作用,您也可以尝试\r。否则,请尝试查找curses 的版本。

编辑(诅咒示例)

这应该让你开始:

#include <curses.h>
#include <unistd.h>

void spinner(int spin_seconds) {
    static char const spin_chars[] = "/-\\|";
    unsigned long i, num_iterations = (spin_seconds * 10);
    for (i=0; i<num_iterations; ++i) {
        mvaddch(0, 0, spin_chars[i & 3]);
        refresh();
        usleep(100000);
    }
}

int main() {
    initscr();    /* initializes curses */
    spinner(10);  /* spin for 10 seconds */
    endwin();     /* cleanup curses */
    return 0;
}

确保与-lcurses-lncurses 链接。这应该适用于任何类似的 UNIX。

【讨论】:

  • 太棒了,非常感谢。我将出于学习目的对此进行一些实验,因为 \r 解决方案对我来说已经足够了。这是让我无法选择您的 - 彻底解释 - 答案的唯一原因。谢谢!
【解决方案3】:

Boost 有一个进度库,可以帮助其中一些事情

【讨论】:

    【解决方案4】:

    哇,clipper,也许你在谈论语言中内置的 @row,col 东西? (仅限反问...)

    您可以使用 printf 制作简单的进度条:您可以省略尾随的换行符。您显然可以使用 \b 开始或结束字符串以叠印字符。用这种方式做传统的 -\|/ 很容易。

    我记得 Eclipse UI 指南推荐了进度指示器,无论您能说出多少实际进度。我认为理论是,有总比没有好,尽你所能。

    您可能需要的唯一技巧是潜在地破坏行缓冲。每次输出操作后请务必fflush(stdout)。 (或 ostream::flush())

    【讨论】:

    • 如果您不介意我回答您的反问问题,是的,我们曾经做过类似的事情。美好的旧快船时代:-)
    • 我想知道为什么我的工作没有刷新,然后我意识到我使用的是无缓冲的 stderr。
    猜你喜欢
    • 1970-01-01
    • 2010-12-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-13
    相关资源
    最近更新 更多