Boost(五)——字符串处理(四):格式化输出操作

讲解

格式化输出库 -> Boost.Format

%占位符

#include <boost/format.hpp> 
#include <iostream> 
using namespace std;
int main()
{
	cout << boost::format("%1%.%2%.%3%") % 2018 % 11 % 2 << endl;
	system("pause");
}

showpos:显示“+”号

#include <boost/format.hpp> 
#include <iostream> 
using namespace std;
int main()
{
	cout << boost::format("%2% %1% %2%") % boost::io::group(showpos,99) % 100 << endl;
	system("pause");
}

输出+99 100 +99

 为了只让第一个有加号,第二个没有的效果,需要改造格式化占位符

#include <boost/format.hpp> 
#include <iostream> 
using namespace std;
int main()
{
	try
	{
		std::cout << boost::format("%|1$+| %2% %1%") % 99 % 100 << std::endl;
		std::cout << boost::format("%|+| %|| %||") % 99 % 100 % 99 << std::endl;//省略占位符
		std::cout << boost::format("%+d %d %d") % 99 % 100 % 99 << std::endl;
		std::cout << boost::format("%+s %s %s") % 99 % 100 % 99 << std::endl;
	}
	catch (boost::io::format_error &ex)
	{
		std::cout << ex.what() << std::endl;
	}
	system("pause");
}

Boost.Format 库抛出的异常为boost::io::bad_format_string

Boost.Format 库中,这并不代表强制为字符串,它会结合适当的操作器

练习题:

1、编写程序,从以下 XML 流中提取并显示数据,包括姓名、生日以及账户余额。 <person><name>Karl-Heinz Huber</name><dob>1970-9-30</dob><account>2,900.64 USD</account></person>

姓、名要分开显示,生日使用 “日.月.年” 的格式,账户余额忽略小数位。 使用其他 XML 流测试你的程序,如包含多余空白、其他名字、账户余额为负数等等的 XML 流。

解答:

自己封装一个xml解析类

思路:

①理解题目

②找到标签:例如名字的标签是<name>...</name>可以通过regex_search方法找到对应标签和内容字符串(记作result)

③分割字符串:将result中"<" ">" " "隐藏并作为分割条件,即通过boost::tokenizer类作为支持,得到内容容器(记作v)

④整合:最后把v中剔除标签名,即将容器第一个和最后一个删除。

以下是我个人的实现方法,当然你也可以想出更好的。。。

#include <boost/format.hpp> 
#include <boost\algorithm\algorithm.hpp>
#include <boost\algorithm\string_regex.hpp>
#include <boost\regex.hpp>
#include <boost\tokenizer.hpp>
#include <algorithm>
#include <iostream> 
#include <vector>
#include <cstring>
using namespace std;
class xml_analysis
{
public:
	xml_analysis() {
		if (my_ret.size())
			my_ret.clear();
		my_combine_str = " ";
	}

	vector<string> getContent(string &s, string &label, char separator = ' ')
	{
		boost::format fmt = boost::format("<%1%>(.*)</%1%>") % label;
		string str = fmt.str();
		boost::regex reg(str);
		boost::smatch what;
		boost::regex_search(s, what, reg);
		string result = what[0];

		typedef boost::tokenizer<boost::char_separator<char>> token;
		fmt = boost::format("<> %1%") % separator;
		str = fmt.str();
		boost::char_separator<char> sep(str.c_str());
		token tok(result, sep);
		static vector<string> ret;
		if (ret.size())
			ret.clear();
		for_each(tok.begin(), tok.end(), [](string tmp_str) {ret.push_back(tmp_str);});
		if (ret.size() > 2)
		{
			ret.erase(ret.begin());
			ret.pop_back();
		}
		my_ret = ret;
		return ret;
	}

	vector<string> getContent2() const { return my_ret; }

	string getCombindString() const { return my_combine_str; }

	friend ostream &operator<<(ostream &stream, const xml_analysis &xml)
	{

		cout << boost::algorithm::join(xml.getContent2(), xml.getCombindString());
		return stream;
	}

	void setCombine(string & str) {
		my_combine_str = str;
	}

private:
	vector<string> my_ret;
	string my_combine_str;
};

int main()
{
	xml_analysis xml;
	string s = "<person><name>Karl-Heinz Huber</name><dob> 1970-9-30 </dob><account>2,900.64 USD</account></person>";

	//名字
	vector<string> vs_name = xml.getContent(s, string("name"), ' ');
	cout << "right of name >> " << vs_name[1] << endl << "left of name >> " << vs_name[0] << endl;
	vector<string> vs_dob = xml.getContent(s, string("dob"), '-');

	//年月日
	xml.setCombine(string("."));
	cout << "time >> " << xml << endl;

	//钱
	vector<string> vs_account = xml.getContent(s, string("account"), '.');
	xml.setCombine(string(" "));
	cout << "money >> " << vs_account[0] << endl;

	system("pause");
}

 实现结果:

2、编写程序,使得格式与显示的数据记录如下:输入 Munich Hamburg 92.12 8:25 9:45, 这条记录表示从 Munich 到 Hamburg 的航班票价为 92.12 欧元,上午 8:25 起飞 9:45 到达目的地。要得到以下输出

Munich    -> Hamburg      92.12 EUR (08:25-09:45)

具体地说,城市名称长度为10并且左对齐而票价长度为7并且右对齐,货币在价格后显示。 起飞与降落时间一起显示在圆括号中,以连字符分隔,不留空格。对早于10点(上午或下午)的时间,必须在前面补0。 用不同的数据记录测试你的程序,例如使用长度大于10的城市名。

解答:

对齐需要用到"iomanip"库

左对齐长度为10:cout << left << setw(10) << ... << 

右对齐长度为7:cout << right << setw(7) << ... << 

如果原字符串长度大于设置的长度,则需要改写原字符串内容。如下面的code中的_getString()函数。

#include <boost/format.hpp> 
#include <boost\algorithm\algorithm.hpp>
#include <boost\algorithm\string_regex.hpp>
#include <boost\regex.hpp>
#include <boost\tokenizer.hpp>
#include <algorithm>
#include <iostream> 
#include <vector>
#include <cstring>
#include <iomanip>
using namespace std;
class flight
{

public:
	flight() : flight(string(" "), string("RMB")) {}
	flight(string & str, string &cur_kind) { s = str; 
		this->cur_kind = cur_kind;
	}
	void analysis() {
		if (s == string(" "))
			return;
		typedef boost::tokenizer<boost::char_separator<char>> token;

		boost::char_separator<char> sep(" ");
		token tok(s, sep);
		static int size = 0;
		if (size != 0)
			size = 0;
		for_each(tok.begin(), tok.end(), [](string str) {size++;});
		if (size != 5)
		{
			cerr << "msg error!!!" << endl;
			return;
		}
		token::iterator it = tok.begin();
		org = *it++;
		dst = *it++;
		price = *it++;
		start_t = _modify_time(string(*it++));
	
		end_t = _modify_time(string(*it++));
	}

	string getOrigin(int length = -1) const { 
		if(length == -1 
			|| org.size() < length)
			return org;
		return _getString(org, length);	
	}
	string getDestination(int length = -1) const {
		if (length == -1
			|| dst.size() < length)
			return dst;
		return _getString(dst, length);
	}
	string getPrice() const { return price; }
	string getStartTime() const { return start_t; }
	string getEndTime() const { return end_t; }
	string getCurKind() const { return cur_kind; }
	

	friend ostream &operator<<(ostream &stream, const flight &f)
	{

		vector<string> v;
		v.push_back(f.getOrigin());
		v.push_back(f.getDestination());
		
		cout.fill(' ');
		cout << left << setw(10) << f.getOrigin(10);
		cout << left << setw(10) << "->";
		cout << left << setw(10) << f.getDestination(10);
		cout << left << setw(7) << f.getPrice();
		cout << f.getCurKind();
		cout << '(' << f.getStartTime() << '-' << f.getEndTime() << ')';
		
		//cout << v[0] << v[1] << v[2] << v[3] << v[4] << endl;
		return stream;
	}
private:
	string s;
	string cur_kind;//票价种类
	string org;//起点
	string dst;//终点
	string price;//票价
	string start_t;//出发时刻
	string end_t;//到达时刻
private:
	string _getString(const string & str, int length) const
	{
		boost::scoped_ptr<string> s_ptr(new string(new char[length + 1]));

		//strncpy_s(data, length, org.data(), org.size());
		memcpy((char *)(*s_ptr).data(), str.data(), length);
		char *tmp = (char *)(*s_ptr).data();
		tmp[length] = '\0';
		return (*s_ptr).data();
	}
	string _modify_time(string &time) const
	{
		boost::char_separator<char> sep(" ", ":");
		typedef boost::tokenizer<boost::char_separator<char>> token;
		token tok(time, sep);
		vector<string> v_time;
		for_each(tok.begin(), tok.end(), [&](string str) {v_time.push_back(str);});
		string hour = *tok.begin();
		if (atoi(hour.data()) < 10
			&& hour.size() < 2)
		{
			v_time[0] = string("0") + hour;
		}
		return boost::algorithm::join(v_time, "");
	}
};

int main()
{
	string s = "Municha Hamburg 92.12 8:25 9:45";
	string s2 = "XiaMen ShangHai 598.98 12:25 15:45";
	flight ff(s, string("EUR"));
	ff.analysis();
	
	flight ff2(s2, string("RMB"));
	ff2.analysis();
	cout << ff << endl;
	cout << ff2 << endl;
	system("pause");
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值