【问题标题】:How to update a printed message in terminal without reprinting如何在不重新打印的情况下更新终端中的打印消息
【发布时间】:2010-11-23 04:16:46
【问题描述】:

我想为我的终端应用程序制作一个进度条,其工作方式如下:

 [XXXXXXX       ] 

这将直观地指示在该过程完成之前还剩下多少时间。

我知道我可以通过将它们添加到字符串中然后简单地 printf 来打印越来越多的 X,但这看起来像:

 [XXXXXXX       ] 
 [XXXXXXXX      ] 
 [XXXXXXXXX     ] 
 [XXXXXXXXXX    ] 

或类似的东西(显然你可以使用间距。)但这在视觉上并不美观。有没有办法在不重新打印的情况下用新文本更新终端中的打印文本?这都是在linux、c++下的。

【问题讨论】:

    标签: c++ linux text terminal


    【解决方案1】:

    在打印新的“版本”时尝试使用\r 而不是\n

    for(int i=0;i<=100;++i) printf("\r[%3d%%]",i);
    printf("\n");
    

    【讨论】:

      【解决方案2】:

      我会说像 ncurses 这样的库将用于此类事情。 curses 帮助在屏幕上移动光标并绘制文本等。

      NCurses

      【讨论】:

      • 这里听起来有点矫枉过正。
      • 是的,可能......如果有人想在未来变得更花哨,这只是一个建议;)
      • 是的...在我们等待进度条时,可能会进行 PONG 游戏。 :D
      • 谢谢你的提示;)我知道 ncurses,我以前用它来制作终端刽子手游戏,但我想在使用它之前问问周围,因为我知道它是矫枉过正
      【解决方案3】:

      类似这样的:

      std::stringstream out;
      for (int i = 0; i< 10; i++)
      {
        out << "X";
        cout << "\r" << "[" << out.str() << "]";
      }
      

      偷偷摸摸的位是回车符“\r”,它使光标移动到行首而不下一行。

      【讨论】:

        【解决方案4】:

        其他人已经指出,你可以使用\r 回到当前行的开头,并覆盖整行。

        另一种可能性是使用退格符(“\b”)删除一些空格,并仅覆盖这些空格。这可以有几个优点。首先,它显然避免了必须重新生成行中的所有内容,这有时会带来轻微的痛苦(尽管这是相当不寻常的)。其次,它可以避免在显示数据时(例如)在写入时缩小的数据的一些痛苦——例如,如果您要显示从 100 到 0 的倒计时,\r 您必须是小心覆盖之前的整个长度,否则您的倒计时将从(例如)100 变为 990(即,保持之前的“0”不变)。

        但是请注意,虽然行内的退格正常工作,但行首的退格可能会也可能不会将光标/写入位置移回前一行。对于大多数实际用途,您只能在一行内移动。

        【讨论】:

          【解决方案5】:

          '\r' 将执行回车。想象一下打印机在没有换行符('\n')的情况下执行回车。这会将写入点返回到行首...然后在原始行的顶部重新打印您的更新状态。

          【讨论】:

            【解决方案6】:

            这是一种不同的语言,但this question 可能会对您有所帮助。基本上,转义字符 \r(回车,而不是 \n 换行符)将您移回当前打印行的开头,以便您可以覆盖已经打印的内容。

            【讨论】:

              【解决方案7】:

              另一种选择是一次只打印一个字符。通常,stdout 是行缓冲的,因此您需要调用 fflush(stdout) --

              for(int i = 0; i < 50; ++i) {
                 putchar('X'); fflush(stdout);
                 /* do some stuff here */
              }
              putchar('\n');
              

              但这没有表示完成的漂亮终止“]”。

              【讨论】:

                【解决方案8】:

                我前段时间写过这个加载栏实用程序。可能有用...

                https://github.com/BlaDrzz/CppUtility/tree/master/LoadingBar

                你基本上可以在这里自定义任何东西。

                int max = 1000;
                LoadingBar* lb = new LoadingBar(10, 0, max);
                
                for (size_t i = 0; i <= max; i++)
                {
                    lb->print();
                    lb->iterate();
                }
                cout << lb->toString() << endl;
                

                非常简单和可定制的实现..

                【讨论】:

                  猜你喜欢
                  • 2020-12-17
                  • 1970-01-01
                  • 1970-01-01
                  • 2020-06-08
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2013-11-25
                  • 1970-01-01
                  相关资源
                  最近更新 更多