Created
February 8, 2026 17:49
-
-
Save zaphodikus/6698c0a1d6477351184536f3974fe388 to your computer and use it in GitHub Desktop.
Console Progress bar
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // ProgressBar.h | |
| #pragma once | |
| #include <iostream> | |
| #include <fstream> | |
| #include <cstdint> | |
| #include <cassert> | |
| #include <cmath> | |
| #include <chrono> | |
| #include <thread> | |
| constexpr char ASCII_START_CH = (char)204; | |
| constexpr char ASCII_MIDDLE_CH = (char)205; | |
| constexpr char ASCII_END_CH = (char)185; | |
| constexpr char ASCII_LOWDENSITY_CH = (char)176; | |
| constexpr char ASCII_SOLID_CH = (char)219; | |
| /// <summary> | |
| /// | |
| /// </summary> | |
| /// <param name="stream&">stream to write to</param> | |
| /// <param name="width"></param> | |
| /// <param name="fillto"></param> | |
| static std::ostream& DrawBar(std::ostream &stream, | |
| uint32_t const width, | |
| uint32_t const fillto | |
| ) | |
| { | |
| uint32_t startlen = 0, endlen = 0; | |
| uint32_t middlelen = 0, index = 0; | |
| assert(width >= fillto); | |
| if (fillto <= 0) startlen = 1; | |
| if (fillto < width) endlen = width; | |
| if (width > 2) middlelen = width -1; | |
| for (; index < startlen; index++) | |
| stream << ASCII_START_CH; | |
| for (; index < fillto; index++) | |
| stream << ASCII_SOLID_CH; | |
| for (; index < middlelen; index++) | |
| stream << ASCII_MIDDLE_CH; | |
| for (; index < endlen; index++) | |
| stream << ASCII_END_CH; | |
| return stream; | |
| } | |
| /// <summary> | |
| /// A progress bar for test mode console apps | |
| /// </summary> | |
| class ProgressBar { | |
| private: | |
| char start_char, middle_char, end_char, fill_char; | |
| uint32_t bar_width; | |
| std::string message; | |
| std::ostream& PaintBar(std::ostream& stream, float percentage) { | |
| uint32_t startlen = 0, endlen = 0; | |
| uint32_t middlelen = 0, index = 0; | |
| uint32_t fillto = (uint32_t)std::ceil(percentage * bar_width); | |
| assert(bar_width >= fillto); | |
| if (fillto <= 0) startlen = 1; | |
| if (fillto < bar_width) endlen = bar_width; | |
| if (bar_width > 2) middlelen = bar_width - 1; | |
| for (; index < startlen; index++) | |
| stream << start_char; | |
| for (; index < fillto; index++) | |
| stream << fill_char; | |
| for (; index < middlelen; index++) | |
| stream << middle_char; | |
| for (; index < endlen; index++) | |
| stream << end_char; | |
| stream << " " << message << "\r"; | |
| return stream; | |
| } | |
| uint32_t startlen = 0, endlen = 0; | |
| uint32_t middlelen = 0, index = 0; | |
| void _constr(uint32_t width) { | |
| _constr(width, 0.0f, ""); | |
| } | |
| void _constr(uint32_t width, | |
| float start_percent, | |
| std::string const pre_message) | |
| { | |
| _constr(width, start_percent, pre_message); | |
| } | |
| void _constr(uint32_t width, | |
| float start_percent, | |
| std::string const pre_message, | |
| char start, | |
| char end, | |
| char middle, | |
| char fill | |
| ) { | |
| bar_width = width; | |
| message = pre_message; | |
| start_char = start; | |
| end_char = end; | |
| middle_char = middle; | |
| fill_char = fill; | |
| PaintBar(std::cout, 0.0f); | |
| } | |
| public: | |
| ProgressBar(uint32_t width) { | |
| _constr(width); | |
| } | |
| ProgressBar(uint32_t width, float start_percent, std::string const pre_message) { | |
| _constr(width, start_percent, pre_message, ASCII_START_CH, ASCII_END_CH, ASCII_MIDDLE_CH, ASCII_SOLID_CH); | |
| } | |
| ProgressBar( | |
| uint32_t width, | |
| float start_percent, | |
| std::string const pre_message, | |
| char start, | |
| char end, | |
| char middle, | |
| char fill | |
| ) { | |
| _constr(width, start_percent, pre_message, start, end, middle, fill); | |
| } | |
| std::ostream& UpdateBar(std::ostream& stream, float percentage) { | |
| return PaintBar(stream, percentage); | |
| } | |
| void UpdateMessage(std::string const new_message) { message = new_message; } | |
| }; | |
| // example usage | |
| int main() { | |
| { | |
| ProgressBar bar = ProgressBar(50, 0.0f, ""); | |
| for (uint16_t full = 0; full <= 50; full++) { | |
| float percent = (float)(full / (float)50); | |
| std::string msg = std::to_string((uint32_t)(percent * 100)) + "%"; | |
| bar.UpdateMessage(msg); | |
| bar.UpdateBar(std::cout, percent); | |
| std::this_thread::sleep_for(std::chrono::milliseconds(100)); | |
| } | |
| std::cout << std::endl; | |
| } { | |
| ProgressBar bar = ProgressBar(80, 0.0f, "", ASCII_LOWDENSITY_CH, ASCII_LOWDENSITY_CH, ASCII_LOWDENSITY_CH, ASCII_SOLID_CH); | |
| for (uint16_t full = 0; full <= 50; full++) { | |
| float percent = (float)(full / (float)50); | |
| std::string msg = std::to_string((uint32_t)(percent * 100)) + "%"; | |
| bar.UpdateMessage(msg); | |
| bar.UpdateBar(std::cout, percent); | |
| std::this_thread::sleep_for(std::chrono::milliseconds(100)); | |
| } | |
| } | |
| return 0; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment