Boost开发指南-2.3progress_display

Progress_display

progress_display可以在控制台上显示程序的执行进度,如果程序执行很耗费时间,那么它能够提供一个友好的用户界面,不至于让用户在等待中失去耐心。

progress_display位于名字空间boost,为了使用progress_display组件,需要包含头文件<boost/progress.hpp>,即:

#include <boost/progress.hpp>
using namspace boost;

类摘要

progress_display是一个独立的类,与 timer库中的其他两个组件——timer 和progress_timer没有任何联系,它的类摘要如下:

class progress_display : noncopyable
{
 public:
    progress_display( unsigned long expected_count );
    progress_display( unsigned long expected_count_,
                             std::ostream & os,
                             const std::string & s1 = "\n", 
                             const std::string & s2 = "",
                             const std::string & s3 = "" );

  void           restart( unsigned long expected_count );
  
  unsigned long  operator+=( unsigned long increment );
  
  unsigned long  operator++();
  unsigned long  count() const;
  unsigned long  expected_count() const;
};

progress_display的构造函数接受一个long型的参数expected_count,表示用于进度显示的基数,是最常用的创建progress_display的方法。

另一种形式的构造函数除了基数和流输出对象外,还接受三个字符串参数,定义显示的三行首字符串。但这个构造函数有点小问题,流输出对象通常都应该是cout,把进度输出到文件或者其他用户看不到的地方似乎没有多大的意义。

在构造后progress_display对象会显示出一个类似图形化进度条的界面,用两行以字符的形式显示百分比进度,像这样:
在这里插入图片描述
重载的加法操作符operator+=和 operator++用来增加计数,并在第三行用字符*显示进度百分比 count() / expected_count。成员函数count()可以返回当前的计数,当计数到达基数expected_count时表示任务已经完成,进度为100%。

用法

假设我们要把一些存储在std::vector中的字符串以每个一行的形式写入到文本文件中,因为字符串数量很多,而且有的很大,因此可能操作会耗费很多时间。progress_display可以让程序有一个友好的人机界面,让用户知道程序的进度。

使用progress_display首先要调用它的构造函数,传入进度基数,如:

progress_display pd(v.size());

随后就可以使用它重载的加法操作符(++pd)来根据程序的运行情况增加计数,直到完成任务。

#include <iostream>
#include <vector>
using namespace std;

// disable pragma warning
#define BOOST_ALLOW_DEPRECATED_HEADERS

#include <boost/progress.hpp>
using namespace boost;

//

void case1()
{
	vector<string> v(100); //一个字符串向量
	ofstream fs("./test.txt"); //文件输出流
    //声明一个progress_display对象,基数是v的大小
	//progress_display pd(v.size(),cout ,"%%%", "+++", "???");
	progress_display pd(v.size());

    //开始迭代遍历向量 处理字符串 写入文件
	for (auto& x : v)  //for+auto循环
	{
		fs << x << endl; //更新进度显示
		++pd;
	}
}

//

void case2()
{
	vector<string> v(100, "aaa");

	v[10] = ""; v[23] = "";
	ofstream fs("./test.txt");
	progress_display pd(v.size());

	for (auto pos = v.begin(); pos != v.end(); ++pos)  //使用迭代器遍历容器
	{
		fs << *pos << endl;
		++pd;
		if (pos->empty())
		{
			cout << "null string # "
				<< (pos - v.begin()) << endl;
		}
	}
}

//

int main()
{
	case1();
	case2();
}

在这里插入图片描述
当程序处理了75个字符串时,控制台的显示大概如下:
在这里插入图片描述
如果改用progress_display另一种形式的构造函数,如:

progress_display pd(v.size(),cout ,"%%%", "+++", "???");

那么显示就会变成这样:
在这里插入图片描述
这种输出形式颇有点“画蛇添足”的味道,建议读者最好不要这么用。

注意事项

progress_display可以用作基本的进度显示,但它有个固有的缺陷:无法把进度显示输出与程序的输出分离。

这是因为progress_display和所有c++程序一样,都向标准输出(cout)输出字符,如果使用progress_display的程序也有输出操作,那么progress_display的进度显示就会一片混乱。

仍然使用刚才的写入文本文件的例子,我们希望显示进度的同时还能报告空的字符串的行号,像这样:
在这里插入图片描述
如case2一样,似乎一切都很好,但实际的运行结果却是:
在这里插入图片描述
很显然,for循环中的输出打乱了progress_display的正常输出,而 progress_display对此毫不知情,仍然按部就班地显示着百分比进度。

这个显示混乱的问题很难解决,因为我们无法预知庞大的程序之中哪个地方会存在一个可能会干扰progress_display的输出。一个可能(但远非完美〉的办法是在每次显示进度时都调用restart()重新显示进度刻度,然后用operator+=来指定当前进度,而不是简单地调用operator++,例如:

pd.restart(v.size());
pd += (pos - v.begin() + 1);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

阳光开朗男孩

你的鼓励是我最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值