boost lexical_cast format

Boost中包括五个字符串与文本处理领域的程序库:
 【1】两个与c标准库函数功能类似的lexical_cast和format,它们关注与字符串的表示,可以将数值转化为字符串,对输出做精确的格式化。
 【2】string_algo库提供了大量常用的字符串处理函数
 【3】tokenizer和xpressive,前者是一个分词器,后者则是一个灵活的正则表达式分析器,同时也是一个语法分析器.

lexical_cast:
 lexical_cast库进行"字面量"的转换,类似c中的atio函数,可以进行字符串,整数/浮点数之间的字面转换。
#include<boost/lexical_cast.hpp>
using namespace boost;
用法:

 lexcial_cast使用类似c++98标准转型操作符(xxx_cast)的形式给出了通用,一致,可理解的语法。
 使用lexcical_cast可以很容易地在数值与字符串之间转换,只需要在模板参数中指定转换的目标类型即可,示例:
#include <iostream>
#include <boost/lexical_cast.hpp>
using namespace boost;
using namespace std;
int main()
{
 int x = lexical_cast<int>("100");
 long y = lexical_cast<long>("2000");
 float pai = lexical_cast<float>("3.14159e5");
 double e = lexical_cast<double>("2.71828");
 cout<<x<<","<<y<<","<<pai<<","<<e<<endl;
 string str = lexical_cast<string>(456);
 cout<<str<<endl;
 cout<<lexical_cast<string>(0.618)<<endl;
 cout<<lexical_cast<string>(0x10)<<endl;
 system("pause");
 return 0;
}
 注意:要转换成数字的字符串中只能有数字和小数点,不能出现字母(表示指数的e/E除外)或其他非数字字符,也就是说,lexcical_cast不能转换如"123L","0x100"这样的c++语法许可的数字字面量字符串,而且lexcical_cast不支持高级的格式控制,不能把数字转换成指定格式的字符串,如果要更高级的格式控制,可使用std::stringstream或者boost::format;
 除了转换数值与字符串,lexcical_cast也可以转换bool类型,但功能很有限,不能使用true/false字面量,只能使用1或0;
cout<<lexical_cast<bool>("1")<<endl;

异常bad_lexical_cast
 当lexcical_cast无法执行转换操作时会抛出异常bad_lexical_cast,它是std::bad_cast的派生类,为了使程序更加健壮,使用try/catch块来保护转换代码;
示例:
#include <iostream>
#include <boost/lexical_cast.hpp>
using namespace boost;
using namespace std;
int main()
{
 try
 {
  cout<<lexical_cast<int>("0x100")<<endl;
  cout<<lexical_cast<double>("HelloWorld")<<endl;
  cout<<lexical_cast<long>("100L")<<endl;
  cout<<lexical_cast<bool>("false")<<endl;
 }
 catch (bad_lexical_cast& e)
 {
  cout<<"error: "<<e.what()<<endl;
 }
 system("pause");
 return 0;
}
 也可以利用bad_lexical_cast来验证数字字符串的合法性,实现一个模板函数num_valid()代码如下:
template<typename T>
bool num_valid(const char *str)
{
 try
 {
  lexical_cast<T>(str);
  return true;
 }
 catch(bad_lexical_cast&)
 {
  return false;
 }
}
int main()
{
 assert(num_valid<double>("3.14"));
 assert(!num_valid<int>("3.14"));
 assert(num_valid<int>("65535"));
 system("pause");
 return 0;
}

转换对象的要求:
 lexical_cast实际是一个模板函数,内部使用了标准库的流操作,因此,对于它的转换对象有如下要求:
 【1】转换起点对象是可流输出的,即定义了operator<<;
 【2】转换终点对象是可流输入的,即定义了operator>>;
 【3】转换终点对象必须是可缺省构造和可拷贝构造的;
 c++语言中的内建类型(int,double等)和std::string都满足以上的三个条件;

应用于自己的类:
 如果要将lexcical_cast应用于自定义的类,把类转换为可理解的字符串描述,只需要满足lexcical_cast的要求即可,准确地说,需要实现流输出操作符operator<<;
示范:
#include <iostream>
#include <boost/lexical_cast.hpp>
using namespace boost;
using namespace std;
class demo_class
{
 friend std::ostream& operator<<(std::ostream& os, const demo_class& x)
 {
  os<<"demo_class's Name";
  return os;
 }
};
int main()
{
 cout<<lexical_cast<string>(demo_class())<<endl;
 system("pause");
 return 0;
}
 这段代码值得提取一个模板类,可以仿造boost.operator库,定义一个模板类outable,以简化流输出操作符<<重载,注意这里没有使用基类链技术,不能用operator的基类串联;
示例:
#include <iostream>
#include <boost/lexical_cast.hpp>
using namespace boost;
using namespace std;
template<typename T>
struct outable
{
 friend std::ostream& operator<<(std::ostream& os, const T &x)
 {
  os<<typeid(T).name();
  return os;
 }

};
class demo_class: outable<demo_class>
{};
int main()
{
 cout<<lexical_cast<string>(demo_class())<<endl;
 system("pause");
 return 0;
}
 这样任何继承outable的类,都会自动获得流输出操作符<<或者lexcical_cast的支持
 依据同样的原理,也可以实现流输入操作符>>的重载.

format:
 boost.format可以把参数格式化到一个字符串,而且是完全类型安全的。
#include<boost/format.hpp>
using namespace boost;
简单例子:
#include <assert.h>
#include <iostream>
#include <boost/format.hpp>
using namespace boost;
using namespace std;
int main()
{
 cout<<format("%s:%d+%d=%d\n")%"sum"%1%2%(1+2);
 format fmt("(%1% + %2%) * %2% = %3%\n");
 fmt %2%5;
 fmt %((2+5)*5);
 cout<<fmt.str();
 system("pause");
 return 0;
}

输入操作符%:
为什么使用重载操作符:
 基于类型安全的考虑,format不能使用省略号来实现可变参数,如果使用函数的调用形式,那么就需要定义不同参数数量的模板函数,如:
template<class T1, class T2, .., class TN>
string format(string s, const T1 &x1, ..., const T1& xN);
 在c++没有实现可变数量模板参数之前,无论定义多少个这样的重载形式,都无法满足格式化“无限”个参数的需求,因此,必须使用操作符的方式来接受参数,而且IO流的operator<<已经应用了许多年,证明这种方式的确有效,

二元操作符operator%()声明如下:
format& operator%(T& x);
 它接受format对象和任意值作为参数,然后返回format对象的引用,因此可以再对返回的format对象实施%操作符,所以:
format("...")%x%y
被编译器解释为:
 operator%(format("..."), x) %y  =>
 operator%(operator%format("..."), x), y)
依次类推,从而能够接受无限个待格式化的参数。

类摘要:
 format并不是一个真正的类,而是一个typedef,真正的实现是basic_format
格式化语法:
 format基本继承了printf的格式化语法,仅对printf语法有少量的不兼容;
 
 每个printf格式化选项以%开始,后面是格式规则,规定了输出的对齐,宽度,字符类型:
 【1】%05d;输出宽度为5的整数,不足位用0填充
 【2】%-8.3f;输出左对齐,总宽度为8,小数位3位的浮点数
 【3】%10s;输出10位的字符串,不足位用空格填充
 【4】%05X;输出宽度为5的大写16进制整数,不足位用0填充。
在经典的printf式格式化外,format还增加了新的格式:
 【5】%|spec|:与printf格式选项功能相同,但两边增加了竖线分隔,可以更好地区分格式化选项与普通字符;
 【6】%N%;标记第N个参数,相当于占位符,不带任何其他的格式化选项。

高级用法:
 format提供了类似printf的功能,但它并不等同于printf函数,这就是面向对象的好处,在通常的格式化字符串之外,format类还拥有几个高级功能,可以再运行时修改格式化选项,绑定输入参数。
这些高级功能用到的函数如下:
 【1】basic_format&bind_arg(int argN, const T& val)
  把格式化字符串第argN位置的输入参数固定为val,即使调用clear()也保持不变,除非调用clear_bind()或clear_binds().
 【2】basic_format& clear_bind(int argN)
  取消格式化字符串第argN位置的参数绑定.
 【3】basic_format& clear_binds()
  取消格式化字符串所有位置的参数绑定,并调用clear().
 【4】basic_format& modify_item(int itemN, T manipulator)
  设置格式化字符串第itemN位置的格式化选项,manipulator是一个boost::io::group()返回的对象。
 【5】boost::io::group(T1 al, ..., Var const &var)
  它是一个模板函数,最大支持10个参数(10个重载形式),可以设置IO流操纵以指定格式或输入参数值,IO流操纵器位于头文件<iomanip>.
 
示例:
#include <iostream>
#include <boost/format.hpp>
#include <iomanip>
using namespace boost;
using boost::io::group;
using namespace std;
int main()
{
 //声明format对象,有三个输入参数,五个格式化选项
 format fmt("%1% %2% %3% %2% %1% \n");
 cout<<fmt %1 % 2 % 3;
 fmt.bind_arg(2, 20); //将第二个输入参数固定为数字20
 cout<<fmt %1 %3;  //输入其余两个参数
 fmt.clear();   //清空缓冲,但绑定的参数不变
 //在操作符中使用group(),指定IO流操纵符第一个参数显示为八进制
 cout<<fmt % group(showbase, oct, 111) % 333;
 fmt.clear_binds();  //清除所有绑定参数
 //设置第一个格式化项,十六进制,宽度为8,右对齐,不足位用*填充
 fmt.modify_item(1, group(hex, right, showbase, setw(8), setfill('*')));
 cout<<fmt % 49 % 20 %100;
 system("pause");
 return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值