一、概述
progress_timer
和progress_display
这两个类定义在文件progress.hpp
。progress_timer
是继承自timer
的一个定时器,progress_timer
的行为类似timer
函数,只是progress_timer
的析构函数在适当的地方以正确的形式展示一条消逝的时间信息。也就是说,该函数会在析构时自动输出时间。progress_display
在适当的地方以适当的形式显示已程序的执行过程,也就是一个进度条,这样它可以提供一个友好的用户界面。
二、类的代码详解
#ifndef BOOST_PROGRESS_HPP
#define BOOST_PROGRESS_HPP
#include <boost/timer.hpp>
#include <boost/noncopyable.hpp>
#include <boost/cstdint.hpp> //为是使用这个变量uintmax_t
#include <iostream>
#include <string>
namespace boost {
// progress_timer类和timer一样,除了析构函数能在合适的地方以适当的形式显示已经消逝的时间信息
class progress_timer : public timer, private noncopyable
{
public:
explicit progress_timer( std::ostream & os = std::cout )
// os显示: 执行可能会被忽略,特别是在嵌入式系统中
: timer(), noncopyable(), m_os(os) {}
~progress_timer()
{
try
{
std::istream::fmtflags old_flags = m_os.setf( std::istream::fixed,
std::istream::floatfield );
std::streamsize old_prec = m_os.precision( 2 );
m_os << elapsed() << " s\n"
<< std::endl;
m_os.flags( old_flags );
m_os.precision( old_prec );
}
catch (...) {}
}
private:
std::ostream & m_os;
};
// progress_display在适当的地方一正确的形式显示一个程序的执行过程,也就是进度条
class progress_display : private noncopyable
{
public:
explicit progress_display( unsigned long expected_count_,
std::ostream & os = std::cout,
const std::string & s1 = "\n",
const std::string & s2 = "",
const std::string & s3 = "" )
// os显示: 执行可能会被忽略,特别是在嵌入式系统中
: noncopyable(), m_os(os), m_s1(s1), m_s2(s2), m_s3(s3) { restart(expected_count_); }
void restart( unsigned long expected_count_ )
// 显示合适的比例
// 后置条件: count()==0, expected_count()==expected_count_
{
_count = _next_tic_count = _tic = 0;
_expected_count = expected_count_;
m_os << m_s1 << "0% 10 20 30 40 50 60 70 80 90 100%\n"
<< m_s2 << "|----|----|----|----|----|----|----|----|----|----|"
<< std::endl
<< m_s3;
if ( !_expected_count ) _expected_count = 1; // 以0为分界线
}
unsigned long operator+=( unsigned long increment )
// 如果有需要,显示一个适当的过程
// 后置条件: count()== original count() + increment
// 返回: count().
{
if ( (_count += increment) >= _next_tic_count ) { display_tic(); }
return _count;
}
unsigned long operator++() { return operator+=( 1 ); }
unsigned long count() const { return _count; }
unsigned long expected_count() const { return _expected_count; }
private:
std::ostream & m_os;
const std::string m_s1;
const std::string m_s2;
const std::string m_s3;
unsigned long _count, _expected_count, _next_tic_count;
unsigned int _tic;
void display_tic()
{
//使用浮点型能确保大小计数器都能正常运行,static_cast<>() 在几个地方使用防止假的编译警告
unsigned int tics_needed = static_cast<unsigned int>((static_cast<double>(_count)
/ static_cast<double>(_expected_count)) * 50.0);
do { m_os << '*' << std::flush; } while ( ++_tic < tics_needed );
_next_tic_count =
static_cast<unsigned long>((_tic/50.0) * static_cast<double>(_expected_count));
if ( _count == _expected_count ) {
if ( _tic < 51 ) m_os << '*';
m_os << std::endl;
}
}
};
}
#endif
1、progress_timer详解
progress_timer继承自timer,因此它拥有timer的所有功能。但它又比timer多一些功能,构造函数explicit progress_timer( std::ostream & os = std::cout )默认的参数是std::cout,它允许将析构时的输出定向到指定的IO里。如果有特别的需求,可以用其他标准库输出流替换,或者使用cout.rdbuf()重定向cout输出。
下面的代码把progress_timer的输出转移到了stringstream中,他可以被转换为字符串供其他的应用使用
stringstream ss;
{
progress_timer t(ss);
}
cout << ss.str();
2、progress_display详解
progress_display构造后,会显示下图所示的图形化用户界面
_expected_count表示用于进度条显示的基数,成员函数count()可以返回当前计数,当计数达到_expected_count时,表示任务执行完成。
operator+=、operator++用来增加计数,用字符“*”来显示进度百分比count()/expected_count。
static_cast<>() 在几个地方使用防止假的编译警告
三、使用案例
1.progress_timer的使用案例
#include <iostream>
#include <boost/progress.hpp>
using namespace boost;
using namespace std;
int main()
{
progress_timer t;
int i;
for(i = 0; i < 100000; i++)
{
cout << "i=" << i << endl;
}
return 0;
}
执行结果如下:
2. progress_display的使用案例
案例 1
#include <boost/progress.hpp>
#include <iostream>
#include <vector>
using namespace std;
using namespace boost;
int main()
{
vector<string> v(100, "aaa");
v[10] = " "; v[23] = " ";
ofstream fs("./test.txt");
progress_display pd(v.size());
for(auto post = v.begin(); post != v.end(); ++post)
{
fs << *post << endl;
++pd;
if(post->empty())
{
cout << "null string #" << (post - v.begin()) << endl;
}
}
}
由于for
加auto
遍历是C++11的新特性,如果你的g++
版本比较低的话,这段代码是编译不过去,所以编译这段代码你需要升级你的g++
版本。也可以把auto
改成迭代器vector<string>::iterator post = v.begin()
。
案例 2
#include <boost/progress.hpp>
#include <iostream>
#include <vector>
#include <fstream>
using namespace std;
using namespace boost;
int main()
{
vector<string> v(100);
std::ofstream fs("./test.txt");
progress_display pd(v.size());
for(vector<string>::iterator it = v.begin(); it != v.end();)
{
fs << *it++ << endl;
++pd;
}
}
执行结果,表示执行到100%的时候