我正在用C ++编写一个控制台程序来下载大文件。我知道文件大小,然后开始工作线程下载。我想显示一个进度指示器,使其看起来更酷。
如何在cout或printf中的不同时间但在相同位置显示不同的字符串?
我正在用C ++编写一个控制台程序来下载大文件。我知道文件大小,然后开始工作线程下载。我想显示一个进度指示器,使其看起来更酷。
如何在cout或printf中的不同时间但在相同位置显示不同的字符串?
wget
进程不是一种选择吗?
Answers:
您可以使用不带换行符(\ n)的“回车”(\ r),并希望您的控制台执行正确的操作。
man termios
)
#include <termios.h>
,在M $ Windows上尝试:)无论如何,感谢您的提示,我可能会在Linux上尝试。
在输出具有固定宽度的情况下,请使用以下内容:
float progress = 0.0;
while (progress < 1.0) {
int barWidth = 70;
std::cout << "[";
int pos = barWidth * progress;
for (int i = 0; i < barWidth; ++i) {
if (i < pos) std::cout << "=";
else if (i == pos) std::cout << ">";
else std::cout << " ";
}
std::cout << "] " << int(progress * 100.0) << " %\r";
std::cout.flush();
progress += 0.16; // for demonstration only
}
std::cout << std::endl;
[> ] 0 %
[===========> ] 15 %
[======================> ] 31 %
[=================================> ] 47 %
[============================================> ] 63 %
[========================================================> ] 80 %
[===================================================================> ] 96 %
请注意,此输出在彼此之间一行下面显示,但是在终端仿真器中(我认为也在Windows命令行中),它将输出在同一行上。
最后,不要忘记在打印更多内容之前先打印换行符。
如果要最后删除该条,则必须用空格覆盖它,以打印较短的内容,例如"Done."
。
而且,当然可以printf
在C中使用相同的方法;修改上面的代码应该简单明了。
对于C
进度栏宽度可调的解决方案,可以使用以下方法:
#define PBSTR "||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||"
#define PBWIDTH 60
void printProgress(double percentage) {
int val = (int) (percentage * 100);
int lpad = (int) (percentage * PBWIDTH);
int rpad = PBWIDTH - lpad;
printf("\r%3d%% [%.*s%*s]", val, lpad, PBSTR, rpad, "");
fflush(stdout);
}
它将输出如下内容:
75% [|||||||||||||||||||||||||||||||||||||||||| ]
';'
第一个结尾应该没有#define
!
看一下boost progress_display
http://www.boost.org/doc/libs/1_52_0/libs/timer/doc/original_timer.html#Class%20progress_display
我认为它可以满足您的需求,而且我相信这是仅标头的库,因此无需链接
您可以打印回车符(\r
),将输出“光标”移回当前行的开头。
对于更复杂的方法,请看一下ncurses之类的东西(用于基于控制台文本的界面的API)。
'\b'
用于将光标向左移动一个位置。
我知道回答这个问题有点晚了,但是我做了一个简单的课程,完全可以满足您的要求。(请记住,我using namespace std;
在此之前写过。):
class pBar {
public:
void update(double newProgress) {
currentProgress += newProgress;
amountOfFiller = (int)((currentProgress / neededProgress)*(double)pBarLength);
}
void print() {
currUpdateVal %= pBarUpdater.length();
cout << "\r" //Bring cursor to start of line
<< firstPartOfpBar; //Print out first part of pBar
for (int a = 0; a < amountOfFiller; a++) { //Print out current progress
cout << pBarFiller;
}
cout << pBarUpdater[currUpdateVal];
for (int b = 0; b < pBarLength - amountOfFiller; b++) { //Print out spaces
cout << " ";
}
cout << lastPartOfpBar //Print out last part of progress bar
<< " (" << (int)(100*(currentProgress/neededProgress)) << "%)" //This just prints out the percent
<< flush;
currUpdateVal += 1;
}
std::string firstPartOfpBar = "[", //Change these at will (that is why I made them public)
lastPartOfpBar = "]",
pBarFiller = "|",
pBarUpdater = "/-\\|";
private:
int amountOfFiller,
pBarLength = 50, //I would recommend NOT changing this
currUpdateVal = 0; //Do not change
double currentProgress = 0, //Do not change
neededProgress = 100; //I would recommend NOT changing this
};
有关如何使用的示例:
int main() {
//Setup:
pBar bar;
//Main loop:
for (int i = 0; i < 100; i++) { //This can be any loop, but I just made this as an example
//Update pBar:
bar.update(1); //How much new progress was added (only needed when new progress was added)
//Print pBar:
bar.print(); //This should be called more frequently than it is in this demo (you'll have to see what looks best for your program)
sleep(1);
}
cout << endl;
return 0;
}
注意:我公开了所有类的字符串,以便可以轻松更改栏的外观。
另一种方法可能是显示“点”或您想要的任何字符。下面的代码将每隔1秒钟将进度指示器[正在加载...]打印为点。
PS:我在这里睡觉。如果要考虑性能,请三思而后行。
#include<iostream>
using namespace std;
int main()
{
int count = 0;
cout << "Will load in 10 Sec " << endl << "Loading ";
for(count;count < 10; ++count){
cout << ". " ;
fflush(stdout);
sleep(1);
}
cout << endl << "Done" <<endl;
return 0;
}