Как сделать progress bar?

258
09 сентября 2021, 04:30

Выполняется сортировка в потоках. В любой момент из переменной last_index я могу узнать сколько отсортированных элементов уже есть. Так же в переменной count есть их количество. Нужно сделать чтоб отдельный поток выводил progress bar в консоль. Не могу понять как это сделать на с++. Если не сложно можно код для этого потока.

Answer 1

Логика следующая:

Есть ширина width, есть прогресс progress. Ширина - размер прогресс-бара в единицах консоли, прогресс - текущий прогресс сортировки (принимает значения [0; 1]). В каждый момент времени прогресс равен отношению количества отсортированных к общему количеству элементов массива. Для отрисовки прогресс-бара отрисовываем progress * width активных ячеек и width - progress * width неактивных ячеек.

Решение для Windows.

#include <iostream> // std::cout
#include <thread>   // std::thread
#include <Windows.h> // WinApi
auto handle = GetStdHandle(STD_OUTPUT_HANDLE);
// устанавливает курсор в консоли на указанную позицию
void set_cursor(int x, int y)
{
    SetConsoleCursorPosition(handle, { static_cast<SHORT>(x), static_cast<SHORT>(y) });
}
// отрисовывает прогресс-бар в консоли по указанным координатам
// x - х-координата для прогресс-бара
// y - у-координата для прогресс-бара
// width - ширина прогресс-бара
// progress - пройденный прогресс [0; 1]
// fill_symbol - символ, которым будет заполнятся пройденный отрезок
//
void render_progress_bar(int x, int y, int width, double progress, char fill_symbol)
{
    int fill_w = static_cast<int>(width * progress);
    int empty_w = width - fill_w;
    set_cursor(x, y);
    for (int i = 0; i < fill_w; ++i)
        std::cout << fill_symbol;
    for (int i = 0; i < empty_w; ++i)
        std::cout << ".";
}
int main()
{
    const int progress_x = 1;
    const int progress_y = 1;
    const int progress_width = 50;
    double progress = 0;
    // поток отрисовки
    auto thread = std::thread{ [progress_x, progress_y,
            progress_width, &progress]
    {
        const int size = 3;
        char symbols[size] = { '|', '/', '-' };
        int symbol_idx = 0;
        do
        {
            render_progress_bar(progress_x, progress_y, progress_width, progress, symbols[symbol_idx]);
            std::this_thread::sleep_for(std::chrono::milliseconds(100));
            ++symbol_idx;
            if (symbol_idx >= size)
                symbol_idx = 0;
        } while (progress < 1);
        render_progress_bar(progress_x, progress_y, progress_width, progress, symbols[symbol_idx]);
    }};
    int count = 100;
    int last_index = 0;
    // имитация изменения прогресса
    while (last_index < count)
    {
        last_index += 1 + rand() % 5;
        if (last_index > count)
            last_index = count;
        progress = static_cast<double>(last_index) / count;
        std::this_thread::sleep_for(std::chrono::milliseconds(400));
    }
    thread.join();
    return 0;
}
READ ALSO
Как выводить элементы массива в приоритетном порядке , создавая кучу из массива

Как выводить элементы массива в приоритетном порядке , создавая кучу из массива

Чтобы вытащить элементы из вектора в приоритетном порядке, кроме как сортировать вектор, можно еще превратить его в кучуВот такая простенькая...

77
Как быстро переименовать переменные в VS C++

Как быстро переименовать переменные в VS C++

Допустим, у меня есть много переменных с названием "a", я хочу их все переименовать в "b" во время редактирования кодаКак можно это быстро сделать?

166
Bootstrap 4 выбор табов Select

Bootstrap 4 выбор табов Select

Доброе время суток господа, вопрос вроде и простой а вроде и сложный, необходимо выбирать стандартные bootstrap 4 табы выпадающим списком select,...

314