分享
 
 
 

Boost源码简析系列——timer(2)

王朝other·作者佚名  2006-01-09
窄屏简体版  字體: |||超大  

Boost源码简析系列——timer(2)

对于timer的第二个头文件中包含的两个类,我早就想写出来,但是最近忙着写代码,今天终于有时间写了,并且前段时间解决了一个问题,用的就是timer,所以也给了我动力。

剩下的两个类,grogress_timer和grogress_display都定义在头文件progress.hpp中,由Beman Dawes编写,最新版是2001年11月1日发表。

1. 类progress_timer

#ifndef BOOST_PROGRESS_HPP

#define BOOST_PROGRESS_HPP

#endif

同样,这是几乎每个头文件都会有的包含保护符。

#include <boost/timer.hpp> //因为progress_timer继承于类timer,所以包含进来。

#include <boost/utility.hpp> //timer定义中也遇到,其中包含了类noncopyable的定义,当progress_timer继承了这个类后,就没有了拷贝构造函数了。

#include <boost/cstdint.hpp> //boost在这里面定义了很多数据类型。

#include <iostream>

#include <string> //这两个没有什么好说的,但是现在写代码最好还是以标准库为准,比如用string,而不是用char *。

class progress_timer : public timer, private noncopyable

{

public:

explicit progress_timer( std::ostream & os = std::cout )

: 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_timer真是简单的可以了,她继承于timer和noncopyable。主要代码都在析构函数中,意思就是说在其对象析构的时候把,对象生存的时间显示出来。

构造函数用explicit表示不能用于隐藏类型转换。

计算流逝的时间的函数是elapsed(),是从timer继承而来。要读懂这段东西,我想最复杂就是对输出流的操作了,这里涉及到了,对输出流输出格式状态的设置,对输出流输出精度的设置。

fmtflags:是一种在标准库流中定义的一种数据类型,她的对象表示了流的i/o操作的一组标志和整数值控制。这些标志有很多,比如:

boolalpha

用符号形式表示真假。

dec

以10为基数输出

hex

以16为基数输出

fixed

浮点数输出格式

showbase

输出前缀,八进制为0,十六进制为0x

floatfield

与浮点数输出有关的标志组

unitbuf

每次输出操作之后刷新

在这里只是列出了极少的一部分,比较详细的描述可参考The C++ Programming Language 第21章。

std::istream::fmtflags old_flags = m_os.setf( std::istream::fixed,

std::istream::floatfield );

所以这条语句的意思就是说,给标准输出对象m_os设置输出格式是浮点数格式,并保存原来的格式,便于完成输出后恢复设置。

std::streamsize old_prec = m_os.precision( 2 );

这条设置了,输出精度为2。

剩下的工作就是输出,并恢复了。

在这段代码中用了异常处理技术。

try

{

//…

}

catch(…){//…}

在这里用catch后面的…表示捕捉所有的异常。

2. 类grogress_display

这个类好像与前面两个类没有一点关系,我们通过她可以在控制台程序中实现用一个进度条显示出我们任务的进展情况。

我们建造一个该类的对象时,会显示出一个进度条标尺,在调用operator ++函数时,决定是否增长进度条,直到到达标尺的最后停止。

class progress_display : private noncopyable

{

public:

explicit progress_display( unsigned long expected_count,

std::ostream & os = std::cout,

const std::string & s1 = "\n", //leading strings

const std::string & s2 = "",

const std::string & s3 = "" )

: m_os(os), m_s1(s1), m_s2(s2), m_s3(s3) { restart(expected_count); }

void restart( unsigned long 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 // endl implies flush, which ensures display

<< m_s3;

if ( !_expected_count ) _expected_count = 1;

}

unsigned long operator+=( unsigned long increment )

{

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()

{

unsigned int tics_needed =

static_cast<unsigned int>(

(static_cast<double>(_count)/_expected_count)*50.0 );

do { m_os << '*' << std::flush; } while ( ++_tic < tics_needed );

_next_tic_count =

static_cast<unsigned long>((_tic/50.0)*_expected_count);

if ( _count == _expected_count ) {

if ( _tic < 51 ) m_os << '*';

m_os << std::endl;

}

}

};

这个类代码也比较简单,有几个data member需要说明一下:

_count

标定现在计数到什么位置。

_expected_count

标定计数可以到达的最大数。

_next_tic_count

下个要打进度标志的计数位置。

创建对象的时候,调用restart函数,显示出标尺,标尺用m_s1,m_s2,m_s3标定标尺的显示规格。

然后,每次进度条需要增加的时候调用menber function:operator+=(),在这个函数中,_count += increment) >= _next_tic_count,增加_count,看是否到达下一个需要对进度条增加的位置,如果是,调用menber function:display_tic()。

而这个类理解的最困难的地方就在于display_tic(),这个函数做了几件事,首先是显示这次调用函数时,应该显示的进度条,计算出下次进度条增加的位置,当进度条也就是_count的计数到达最大值的时候,判断是否打最后一个进度条上的点。

在我们使用这个类的时候,需要的就是创建个对象,在该增加进度条的时候调用operator++()就行了。用起来也比较方便。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有