БлогNot. C++: индикатор прогресса для консоли :)

C++: индикатор прогресса для консоли :)

Понадобился человеку в консольном приложении хотя бы простейший "бегунок", показывающий из цикла, какая часть расчёта выполнена (у нас шаги расчёта заменяются задержкой на 20 миллисекунд).

Вот пример простейшего класса для этой задачи и его вызова. Предполагается, что длина бегунка всегда равна WIDTH символов, где WIDTH - константа класса. Она описана равной 80 символов, такова обычно ширина текстовой консоли.

В конструкторе можно указать позицию бегунка (столбец и строка экрана, счёт строк и столбцов - с левого верхнего угла начиная с единицы) и значение max - номер максимального шага расчёта, номер первого шага всегда ноль.

Метод draw "рисует" бегунок из символов вертикальной черты (16-ричный код 0x7C), а go "ставит" его в нужную позицию, выводя символы '#' (0x23) поверх чёрточек. Предполагается, что go вызывается в цикле с верхней границей max.

Так как заголовочный файл conio.h нестандартен для C++, работу по позиционированию курсора и выводу в консоль выполняет сторонний класс coniow, версию coniow, работающую со Studio 2015, можно взять в архиве из этой заметки.

Стандартный метод round появился только в новом стандарте C++11, поэтому класс включает собственную реализацию округления чисел round1. Вот полный листинг примера, проверенный в Studio 2015.

#include <cmath>
#include "coniow.h"

class Progress {
 static const int WIDTH = 80;
 int max,xpos,ypos,prev_ps;
 char cvoid, cfill;
 double round1(double x) { return ((x - floor(x)) >= 0.5) ? ceil(x) : floor(x); }
public:
 Progress(int max = 100, int xpos=1, int ypos=1) { 
  this->max = max; this->xpos = xpos; this->ypos = ypos;
  this->cvoid = 0x7C; this->cfill = 0x23; this->prev_ps = -1;
 }
 void draw() {
  gotoxy(this->xpos, this->ypos);
  for (int i = 1; i <= WIDTH; i++) cprintf("%c", this->cvoid);
 }
 void go(int ps) {
  ps = (ps < 0 ? 0 : (ps>this->max ? this->max : ps));
  ps = round1(ps*(double)(WIDTH)/max);
  if (ps == this->prev_ps || ps<1) return;
  gotoxy(this->xpos, this->ypos);
  for (int i = 1; i <= ps; i++) cprintf("%c", this->cfill);
  this->prev_ps = ps;
 }
};

int main(void) {
 const int n = 3456;
 Progress p(n);
 p.draw();
 for (int i = 0; i<n; i++) {
  p.go(i);
  delay(20);
 }
 gotoxy(1, 2); cprintf("ok");
 getch();  return 0;
}

Версия подобного приложения для старых DOS-совместимых консолей могла бы выглядеть, например, так:

#include <math.h>
#include <conio.h>
#include <dos.h>
int WIDTH =80;

class Progress {
 int max,xpos,ypos,prev_ps;
 char cvoid, cfill;
 double round1(double x) { return ((x - floor(x)) >= 0.5) ? ceil(x) : floor(x); }
public:
 Progress(int max = 100, int xpos=1, int ypos=1) { 
  this->max = max; this->xpos = xpos; this->ypos = ypos;
  this->cvoid = 0x7C; this->cfill = 0x23; this->prev_ps = -1;
 }
 void draw() {
  gotoxy(this->xpos, this->ypos);
  for (int i = 1; i <= WIDTH; i++) cprintf("%c", this->cvoid);
 }
 void go(int ps) {
  ps = (ps < 0 ? 0 : (ps>this->max ? this->max : ps));
  ps = round1(ps*(double)(WIDTH)/max);
  if (ps == this->prev_ps || ps<1) return;
  gotoxy(this->xpos, this->ypos);
  for (int i = 1; i <= ps; i++) cprintf("%c", this->cfill);
  this->prev_ps = ps;
 }
};

int main(void) {
 const int n = 3456;
 clrscr();
 Progress p(n);
 p.draw();
 for (int i = 0; i<n; i++) {
  p.go(i);
  delay(10); //Make any actions here!
 }
 gotoxy(1, 2); cprintf("ok");
 getch();  return 0;
}

24.03.2017, 15:23 [3565 просмотров]


теги: c++ учебное studio

К этой статье пока нет комментариев, Ваш будет первым