我应该如何向生成终端输出的 C++ 程序添加固定进度条(在 Linux 中)? [英] How should I add a stationary progress bar to a C++ program that produces terminal output (in Linux)?

查看:60
本文介绍了我应该如何向生成终端输出的 C++ 程序添加固定进度条(在 Linux 中)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个包含文件循环的现有程序.它做各种各样的事情,提供大量的终端输出.我想要一个整体进度条,它在终端底部的同一行上保持静止,而文件操作的所有输出都打印在它上面.我应该如何尝试做这样的事情?

I have an existing program that contains a loop over files. It does various things, providing lots of terminal output. I want to have an overall progress bar that remains stationary on the same line at the bottom of the terminal while all of the output from the file operations is printed above it. How should I try to do something like this?

所以,为了清楚起见,我正在尝试解决一些类似于以下内容的固有显示问题:

So, just to be clear, I'm trying to address the display problems inherent in something a bit like the following:

#include <unistd.h>
#include <iostream>
#include <string>

using namespace std;

int main(){
  for (int i = 0; i <= 100; ++i){
    std::cout << "processing file number " << i << "\n";
    string progress = "[" + string(i, '*') + string(100-i, ' ') + "]";
    cout << "\r" << progress << flush;
    usleep(10000);
  }
}

推荐答案

我所知道的唯一一种移动光标的便携方式是使用 \r 移动到行首.你提到你想输出高于进度的东西.幸运的是,您很幸运,因为您使用的是 Linux,您可以使用终端转义码在终端中自由移动.看这个例子:

The only portable way of moving the cursor around that I know of is using \r to move to the beginning of the line. You mention that you would like to output stuff above the progress. Fortunately, you are in luck since you're on Linux and you can use the terminal escape codes to move around the terminal freely. Look at this example:

#include <unistd.h>
#include <iostream>
#include <string>

using namespace std;

int main()
{
  cout << endl;
  for (int i=0; i <= 100; ++i)
  {
    string progress = "[" + string(i, '*') + string(100-i, ' ') + "]";
    cout << "\r\033[F" << i << "\n" << progress << flush;
    usleep(10000);
  }
}

在这里,我添加了通过使用 \r 移动到行首并使用转义码 \033[F 打印前.然后,打印一行,用 \n 向下移动一行并重新打印进度.

Here, I added the ability to print the progress value above the progress bar by moving to the beginning of the line using \r and one line up using escape code \033[F before printing. Then, printed one line, moved down one line with \n and re-printed the progress.

您可以更进一步,在打印前将光标移动到终端中的任何 X、Y 位置.为此,请在输出之前使用转义码 \033[Y;Xf.

You can go even further and move your cursor to any X,Y position in the terminal before printing. For that use the escape code \033[Y;Xf before your output.

有关转义码的良好列表,请查看维基百科:https://en.wikipedia.org/wiki/ANSI_escape_code#CSI_codes

For a good list of escape codes, check out Wikipedia: https://en.wikipedia.org/wiki/ANSI_escape_code#CSI_codes

因此,可以在不使用诸如 ncurses 之类的额外库的情况下实现该行为,但如果您打算创建更像 gui 的体验,这可能正是您想要的.

So, it is possible to achive that behavior without using additional libs like ncurses, but maybe it is actually what you want if you intend to create a more gui-like experience.

解决您的尝试:

void print_progress_bar(int percentage){
  string progress = "[" + string(percentage, '*') + string(100 - percentage, ' ') + "]";
  cout << progress << "\r\033[F\033[F\033[F" << flush;
}

int main(){
  cout << endl;
  for (int i=0; i <= 100; ++i){
    std::cout << "processing file number " << i << "\n";
    std::cout << "    doing thing to file number " << i << "\n";
    std::cout << "    doing another thing to file number " << i << "\n";
    print_progress_bar(i);
    usleep(10000);
  }
  cout << endl;
  cout << endl;
  cout << endl;
  cout << endl;
}

这篇关于我应该如何向生成终端输出的 C++ 程序添加固定进度条(在 Linux 中)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆