How to display a progress indicator in pure C/C++ (cout/printf)?

C++CUser InterfaceC++11Io

C++ Problem Overview


I'm writing a console program in C++ to download a large file. I know the file size, and I start a work thread to download it. I want to show a progress indicator to make it look cooler.

How can I display different strings at different times, but at the same position, in cout or printf?

C++ Solutions


Solution 1 - C++

With a fixed width of your output, use something like the following:

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;

http://ideone.com/Yg8NKj

[>                                                                     ] 0 %
[===========>                                                          ] 15 %
[======================>                                               ] 31 %
[=================================>                                    ] 47 %
[============================================>                         ] 63 %
[========================================================>             ] 80 %
[===================================================================>  ] 96 %

Note that this output is shown one line below each other, but in a terminal emulator (I think also in Windows command line) it will be printed on the same line.

At the very end, don't forget to print a newline before printing more stuff.

If you want to remove the bar at the end, you have to overwrite it with spaces, to print something shorter like for example "Done.".

Also, the same can of course be done using printf in C; adapting the code above should be straight-forward.

Solution 2 - C++

You can use a "carriage return" (\r) without a line-feed (\n), and hope your console does the right thing.

Solution 3 - C++

For a C solution with an adjustable progress bar width, you can use the following:

#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);
}

It will output something like this:

 75% [||||||||||||||||||||||||||||||||||||||||||               ]

Solution 4 - C++

Take a look at boost progress_display

http://www.boost.org/doc/libs/1_52_0/libs/timer/doc/original_timer.html#Class%20progress_display

I think it may do what you need and I believe it is a header only library so nothing to link

Solution 5 - C++

You can print a carriage return character (\r) to move the output "cursor" back to the beginning of the current line.

For a more sophisticated approach, take a look at something like ncurses (an API for console text-based interfaces).

Solution 6 - C++

I know I am a bit late in answering this question, but I made a simple class that does exactly what you want. (keep in mind that I wrote using namespace std; before this.):

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
};

An example on how to use:

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;
}

Note: I made all of the classes' strings public so the bar's appearance can be easily changed.

Solution 7 - C++

Another way could be showing the "Dots" or any character you want .The below code will print progress indicator [sort of loading...]as dots every after 1 sec.

PS : I am using sleep here. Think twice if performance is concern.

#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;
}

Solution 8 - C++

Here is a simple one I made:

#include <iostream>
#include <thread>
#include <chrono>
#include <Windows.h>
using namespace std;

int main() {
   // Changing text color (GetStdHandle(-11), colorcode)
   SetConsoleTextAttribute(GetStdHandle(-11), 14);
   
   int barl = 20;
   cout << "["; 	
   for (int i = 0; i < barl; i++) { 		
      this_thread::sleep_for(chrono::milliseconds(100));
      cout << ":"; 	
   }
   cout << "]";

   // Reset color
   SetConsoleTextAttribute(GetStdHandle(-11), 7);
}

Solution 9 - C++

May be this code will helps you -

#include <iostream>
#include <string>
#include <thread>
#include <chrono>
#include <cmath>

using namespace std;

void show_progress_bar(int time, const std::string &message, char symbol)
{
    std::string progress_bar;
    const double progress_level = 1.42;

    std::cout << message << "\n\n";

    for (double percentage = 0; percentage <= 100; percentage += progress_level)
    {
        progress_bar.insert(0, 1, symbol);
        std::cout << "\r [" << std::ceil(percentage) << '%' << "] " << progress_bar;
        std::this_thread::sleep_for(std::chrono::milliseconds(time));       
    }
    std::cout << "\n\n";
}

int main()
{
	show_progress_bar(100, "progress" , '#');
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionxmllmxView Question on Stackoverflow
Solution 1 - C++leemesView Answer on Stackoverflow
Solution 2 - C++James CurranView Answer on Stackoverflow
Solution 3 - C++razzView Answer on Stackoverflow
Solution 4 - C++John BandelaView Answer on Stackoverflow
Solution 5 - C++Matt KlineView Answer on Stackoverflow
Solution 6 - C++Flare CatView Answer on Stackoverflow
Solution 7 - C++A JView Answer on Stackoverflow
Solution 8 - C++Kugel BlitzView Answer on Stackoverflow
Solution 9 - C++AkashView Answer on Stackoverflow