讲解
格式化输出库 -> 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");
}