C语言实现进度条

progressBar.hpp:

#ifndef __PROGRESSBAR_HPP
#define __PROGRESSBAR_HPP

#include 
#include 
#include 

// the following are UBUNTU/LINUX ONLY terminal color codes.
#define RESET "\033[0m"
#define BLACK "\033[30m"              /* Black */
#define RED "\033[31m"                /* Red */
#define GREEN "\033[32m"              /* Green */
#define YELLOW "\033[33m"             /* Yellow */
#define BLUE "\033[34m"               /* Blue */
#define MAGENTA "\033[35m"            /* Magenta */
#define CYAN "\033[36m"               /* Cyan */
#define WHITE "\033[37m"              /* White */
#define BOLDBLACK "\033[1m\033[30m"   /* Bold Black */
#define BOLDRED "\033[1m\033[31m"     /* Bold Red */
#define BOLDGREEN "\033[1m\033[32m"   /* Bold Green */
#define BOLDYELLOW "\033[1m\033[33m"  /* Bold Yellow */
#define BOLDBLUE "\033[1m\033[34m"    /* Bold Blue */
#define BOLDMAGENTA "\033[1m\033[35m" /* Bold Magenta */
#define BOLDCYAN "\033[1m\033[36m"    /* Bold Cyan */
#define BOLDWHITE "\033[1m\033[37m"   /* Bold White */

class progressbar {
   public:
    // default destructor
    ~progressbar() = default;

    // delete everything else
    progressbar(progressbar const&) = delete;
    progressbar& operator=(progressbar const&) = delete;
    progressbar(progressbar&&) = delete;
    progressbar& operator=(progressbar&&) = delete;

    // default constructor, must call set_niter later
    progressbar();
    progressbar(const std::string& type, int n, bool showbar = true);

    // reset bar to use it again
    void reset();
    // set number of loop iterations
    void set_niter(int iter);
    // chose your style
    void set_done_char(const std::string& sym) { done_char = sym; }
    void set_todo_char(const std::string& sym) { todo_char = sym; }
    void set_opening_bracket_char(const std::string& sym) { opening_bracket_char = sym; }
    void set_closing_bracket_char(const std::string& sym) { closing_bracket_char = sym; }
    // to show only the percentage
    void show_bar(bool flag = true) { do_show_bar = flag; }
    // main function
    void update();
    void update(int n);
    // default style
    void setDefaultStyle();

   private:
    std::string m_type;
    int progress;
    int n_cycles;
    int last_perc;
    bool do_show_bar;
    bool update_is_called;

    std::string done_char;
    std::string todo_char;
    std::string opening_bracket_char;
    std::string closing_bracket_char;
};

progressbar::progressbar()
    : progress(0),
      m_type(GREEN),
      n_cycles(0),
      last_perc(0),
      do_show_bar(true),
      update_is_called(false),
      done_char("#"),
      todo_char(" "),
      opening_bracket_char("["),
      closing_bracket_char("]") {}

progressbar::progressbar(const std::string& type, int n, bool showbar)
    : progress(0),
      m_type(type),
      n_cycles(n),
      last_perc(0),
      do_show_bar(showbar),
      update_is_called(false),
      done_char("#"),
      todo_char(" "),
      opening_bracket_char("["),
      closing_bracket_char("]") {}

void progressbar::reset() {
    progress = 0, update_is_called = false;
    last_perc = 0;
    return;
}

void progressbar::set_niter(int niter) {
    if (niter <= 0)
        throw std::invalid_argument("progressbar::set_niter: number of iterations null or negative");
    n_cycles = niter;
    return;
}

void progressbar::update() {
    if (n_cycles == 0)
        throw std::runtime_error("progressbar::update: number of cycles not set");

    if (!update_is_called) {
        if (do_show_bar == true) {
            std::cout << m_type << ":" << opening_bracket_char;
            for (int _ = 0; _ < 50; _++)
                std::cout << todo_char;
            std::cout << closing_bracket_char << " 0%";
        } else
            std::cout << "0%";
    }
    update_is_called = true;

    // compute percentage, if did not change, do nothing and return
    int perc = progress * 100. / (n_cycles - 1);
    if (perc < last_perc)
        return;

    // update percentage each unit
    if (perc == last_perc + 1) {
        // erase the correct  number of characters
        if (perc <= 10)
            std::cout << "\b\b" << perc << '%';
        else if (perc > 10 and perc < 100)
            std::cout << "\b\b\b" << perc << '%';
        else if (perc == 100)
            std::cout << "\b\b\b" << perc << '%';
    }
    if (do_show_bar == true) {
        // update bar every ten units
        if (perc % 2 == 0) {
            // erase closing bracket
            std::cout << std::string(closing_bracket_char.size(), '\b');
            // erase trailing percentage characters
            if (perc < 10)
                std::cout << "\b\b\b";
            else if (perc >= 10 && perc < 100)
                std::cout << "\b\b\b\b";
            else if (perc == 100)
                std::cout << "\b\b\b\b\b";

            // erase 'todo_char'
            for (int j = 0; j < 50 - (perc - 1) / 2; ++j) {
                std::cout << std::string(todo_char.size(), '\b');
            }

            // add one additional 'done_char'
            if (perc == 0)
                std::cout << todo_char;
            else
                std::cout << done_char;

            // refill with 'todo_char'
            for (int j = 0; j < 50 - (perc - 1) / 2 - 1; ++j)
                std::cout << todo_char;

            // readd trailing percentage characters
            std::cout << closing_bracket_char << ' ' << perc << '%';
            if (perc == 100)
                std::cout << std::endl;
        }
    }
    last_perc = perc;
    ++progress;
    std::cout << std::flush;

    return;
}

void progressbar::update(int n) {
    for (int i = 0; i < n; i++) {
        update();
    }
}

void progressbar::setDefaultStyle() {
    set_todo_char(" ");
    set_done_char("*");
    set_opening_bracket_char("[");
    set_closing_bracket_char("]");
}

#endif

 测试代码test.cpp:

#include 

#include "progressbar.hpp"

int main(int argc, char* argv[]) {
    progressbar bar;
    bar.set_niter(60);
    bar.setDefaultStyle();
    for (size_t i = 0; i < 60; i++) {
        // if ((i % 20) == 0) {
        //     bar.reset();
        // }
        bar.update();
        sleep(1);
    }
    return 0;
}

编译:g++ ./test.cpp -o main, 运行./main, 结果输出:

C语言实现进度条_第1张图片

 

还有点小问题是:输出*不连续,暂时未发现问题在哪里,待修改。

你可能感兴趣的:(c语言,c++,开发语言)