Как отобразить индикатор выполнения в чистом C / C++ (cout/printf)?
Я пишу консольную программу на C++ для загрузки большого файла. Я знаю размер файла, и я начинаю рабочий поток для загрузки. Я хочу показать индикатор прогресса, чтобы он выглядел круче.
Как отображать разные строки в разное время, но в одной и той же позиции, в cout или printf?
8 ответов:
вы можете использовать "возврат каретки" (\r) без подачи строки (\n) и надеяться, что ваша консоль сделает все правильно.
с фиксированной шириной вашего выхода, используйте что-то вроде следующего:
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% [|||||||||||||||||||||||||||||||||||||||||| ]
взгляните на boost progress_display
http://www.boost.org/doc/libs/1_52_0/libs/timer/doc/original_timer.html#Class%20progress_display
Я думаю, что это может сделать то, что вам нужно, и я считаю, что это только заголовок библиотеки, так что ничего не связывать
вы можете напечатать символ возврата каретки (
\r) для перемещения выходного "курсора" обратно в начало текущей строки.для более сложного подхода взгляните на что-то вроде ncurses (API для текстовых интерфейсов консоли).
другой способ может показать "точки" или любой символ, который вы хотите .Приведенный ниже код выведет индикатор выполнения [вид загрузки...]как точки каждые через 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; }
Я знаю, что немного опоздал с ответом на этот вопрос, но я сделал простой класс, который делает именно то, что вы хотите. (имейте в виду, что я писал
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; }Примечание: я сделал все строки классов общедоступными, поэтому внешний вид бара можно легко изменить.
вот простой, который я сделал: D
#include <iostream> #include<Windows.h> using namespace std; int barl = 20; int main() { system("color 0e"); cout << "["; for (int i = 0; i < barl; i++) { Sleep(100); cout << ":"; } cout << "]"; }
Comments