我应该如何向生成终端输出的 C++ 程序添加固定进度条(在 Linux 中)?
How should I add a stationary progress bar to a C++ program that produces terminal output (in Linux)?
我有一个包含文件循环的现有程序。它做各种各样的事情,提供大量的终端输出。我想要一个整体进度条,它在终端底部的同一行上保持静止,同时文件操作的所有输出都打印在它上面。我应该如何尝试做这样的事情?
编辑:所以,为了清楚起见,我正在尝试解决类似于以下内容的固有显示问题:
#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 上,你可以使用终端转义码在终端中自由移动。看这个例子:
#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 << "\r3[F" << i << "\n" << progress << flush;
usleep(10000);
}
}
在这里,我添加了在进度条上方打印进度值的功能,方法是使用 \r
移动到行的开头,并在打印前使用转义码 3[F
一行。然后,打印一行,用 \n
向下移动一行
并重新打印进度。
您可以更进一步,在打印前将光标移动到终端中的任意 X、Y 位置。为此,请在输出前使用转义码 3[Y;Xf
。
有关转义码的完整列表,请查看维基百科:https://en.wikipedia.org/wiki/ANSI_escape_code#CSI_codes
因此,无需使用像 ncurses
这样的额外库也可以实现该行为,但如果您打算创建更像 gui 的体验,这也许正是您想要的。
修复您的尝试:
void print_progress_bar(int percentage){
string progress = "[" + string(percentage, '*') + string(100 - percentage, ' ') + "]";
cout << progress << "\r3[F3[F3[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;
}
我有一个包含文件循环的现有程序。它做各种各样的事情,提供大量的终端输出。我想要一个整体进度条,它在终端底部的同一行上保持静止,同时文件操作的所有输出都打印在它上面。我应该如何尝试做这样的事情?
编辑:所以,为了清楚起见,我正在尝试解决类似于以下内容的固有显示问题:
#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 上,你可以使用终端转义码在终端中自由移动。看这个例子:
#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 << "\r3[F" << i << "\n" << progress << flush;
usleep(10000);
}
}
在这里,我添加了在进度条上方打印进度值的功能,方法是使用 \r
移动到行的开头,并在打印前使用转义码 3[F
一行。然后,打印一行,用 \n
向下移动一行
并重新打印进度。
您可以更进一步,在打印前将光标移动到终端中的任意 X、Y 位置。为此,请在输出前使用转义码 3[Y;Xf
。
有关转义码的完整列表,请查看维基百科:https://en.wikipedia.org/wiki/ANSI_escape_code#CSI_codes
因此,无需使用像 ncurses
这样的额外库也可以实现该行为,但如果您打算创建更像 gui 的体验,这也许正是您想要的。
修复您的尝试:
void print_progress_bar(int percentage){
string progress = "[" + string(percentage, '*') + string(100 - percentage, ' ') + "]";
cout << progress << "\r3[F3[F3[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;
}