马上注册,结交更多好友,享用更多功能^_^
您需要 登录 才可以下载或查看,没有账号?立即注册
x
由于在控制台中只能以打印字符的形式来进行输出,很多时候我们在运行比较大的程序时无法知道完成进度,所以写了一个类来实现这一功能。//DosProgressBar header file
//"DosProgressBar"用于在控制台中实现进度显示
//版本号: 1.0.1
//作者:三点一洲
#pragma once
#include <cstring>
#include <cstdio>
#include <string>
#include <iostream>
#include <windows.h>
#define __ARR_CAPACITY 100
#define _INIT_VALUE 0
#define _MAX_VALUE 1
#define _PERCENT_MULTI 100
#define _BLOCK_NUMBERS 32
#define _DEFAULT_FLUSH_FREQUENCY 65536
#define _FLUSH_FREQUENCY 3
#define _FILL_BLOCK "█"
#define _STANDEARD_OUT_SIZE (_BLOCK_NUMBERS * 2 + 2)
#define _UNUSED_BAR 0
#define _USING_BAR 1
#define _USED_BAR 2
//设置光标位置(x, y)
void gotoxy(short, short);
//设置光标位置(COORD)
void gotoxy(COORD);
//返回当前光标位置
COORD wherexy();
//获取光标的位置y
int wherey();
//获取光标的位置x
int wherex();
//计算合适的刷新频率
int calcFrequency(int);
class DosProgressBar
{
typedef int bar_status;
typedef double progress_value;
private:
progress_value nowValue;
bar_status status;
COORD outPos;
int flushCount;
int flushFrequency;
public:
//格式化进度
inline std::string percentFormate()
/* 格式化当前进度 */
{
char s[__ARR_CAPACITY];
sprintf(s, "%.2f%%", nowValue * _PERCENT_MULTI);
//std::cout<<std::string(s)+"\n";
return std::string(s);
}
//设置当前进度
inline progress_value setNowValue(progress_value pv)
/* 设置进度值 */
{
nowValue = pv;
return pv;
}
//获得当前进度
inline progress_value getNowValue()
/* 获得当前进度 */
{
return nowValue;
}
private:
//int printProgressBar(const char end = '\0');
/* 按频率打印出进度条 */
//int printProgressBar(const std::string &, const char end = '\0');
/* 按频率打印出有后缀进度条 */
//回退到开始光标
void backToStartPos();
//立即打印进度条
int printProgressBarSoon(const char end = '\0');
//立即打印有后缀进度条
int printProgressBarSoon(const std::string &, const char end = '\0');
public:
//刷新进度条
void flushProgressBar(progress_value);
//重置进度条
void reSetBar();
//设置合理刷新频率
void setFrequency(int);
public:
inline DosProgressBar(void) : nowValue(0), flushCount(0), outPos({0, 0}), status(_UNUSED_BAR), flushFrequency(_DEFAULT_FLUSH_FREQUENCY)
{
}
inline DosProgressBar(progress_value _nowValue) : nowValue(_nowValue), flushCount(0), outPos({0, 0}), status(_UNUSED_BAR), flushFrequency(_DEFAULT_FLUSH_FREQUENCY)
{
}
~DosProgressBar(void) {}
};
//DosProgressBar source file
//"DosProgressBar"用于在控制台中实现进度显示
//版本号: 1.0.1
//作者:三点一洲
#include "DosProgressBar.h"
#include <cmath>
//获取光标的位置x
int wherex()
{
CONSOLE_SCREEN_BUFFER_INFO pBuffer;
GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &pBuffer);
return pBuffer.dwCursorPosition.X;
}
//获取光标的位置y
int wherey()
{
CONSOLE_SCREEN_BUFFER_INFO pBuffer;
GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &pBuffer);
return pBuffer.dwCursorPosition.Y;
}
//返回当前光标位置
COORD wherexy()
{
COORD _coord;
CONSOLE_SCREEN_BUFFER_INFO pBuffer;
GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &pBuffer);
_coord.X = pBuffer.dwCursorPosition.X;
_coord.Y = pBuffer.dwCursorPosition.Y;
return _coord;
}
//设置光标位置(x, y)
void gotoxy(short x, short y)
{
COORD pos = {x, y};
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleCursorPosition(hOut, pos);
}
//设置光标位置(COORD)
void gotoxy(COORD _coord)
{
COORD pos = _coord;
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleCursorPosition(hOut, pos);
}
//计算合适的刷新频率
int calcFrequency(int _t)
{
int t = (int)(_t / _BLOCK_NUMBERS / ((int)(log( _t < exp(2) ? exp(2) : _t ) / 2)) + 1);
return t;
}
//回退到开始光标
void DosProgressBar::backToStartPos()
{
gotoxy(outPos);
return;
}
//立即打印进度条
int DosProgressBar::printProgressBarSoon(const char end)
{
std::string outs("|");
int block = (int)(nowValue * _BLOCK_NUMBERS);
for (int i = 0; i < block; i++)
{
outs += _FILL_BLOCK;
}
outs += std::string(_STANDEARD_OUT_SIZE - 2 - block * 2, ' ');
outs += "|";
outs += " " + percentFormate();
if (end != '\0')
outs += end;
return printf("%s", outs.c_str());
}
//立即打印有后缀进度条
int DosProgressBar::printProgressBarSoon(const std::string &suffix, const char end)
{
int n = printProgressBarSoon('\0') + printf("%s", suffix.c_str());
if (end != '\0')
return n + printf("%c", end);
else
return n;
}
//刷新进度条
void DosProgressBar::flushProgressBar(progress_value pv)
{
if (status == _UNUSED_BAR)
{
//std::cout<<"\n"<<flushFrequency<<std::endl;
status = _USING_BAR;
COORD _co = wherexy();
if (_co.X > 0)
{
_co.Y++;
_co.X = 0;
}
outPos = _co;
gotoxy(outPos);
}
else if (status == _USED_BAR)
{
std::cerr << "进度条已使用,请重置后继续使用" << std::endl;
//exception 1
//exit(0);
}
setNowValue(pv);
++flushCount;
int resetFlag = flushCount / flushFrequency;
flushCount %= flushFrequency;
if (resetFlag || nowValue == 1.0)
{
gotoxy(outPos);
printProgressBarSoon('\n');
if (!(nowValue == 1.0))
{
gotoxy(outPos);
}
else
{
status = _USED_BAR;
}
}
}
//重置进度条
void DosProgressBar::reSetBar()
{
}
//设置合理刷新频率
void DosProgressBar::setFrequency(int total)
{
flushFrequency = calcFrequency(total);
return;
}
#include "DosProgressBar.h"
#define N 100000000 //总循环次数
int main()
{
DosProgressBar dpb(0.0);
dpb.setFrequency(N);
for (int i = 0; i <= N ; i++)
{
dpb.flushProgressBar(i * 1.0 / N);
}
return 0;
}
|