| « | August 2026 | » | | 日 | 一 | 二 | 三 | 四 | 五 | 六 | | | | | | | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | | | | | | |
| 公告 |
| 暂无公告... |
| Blog信息 |
|
blog名称: 日志总数:11 评论数量:53 留言数量:0 访问次数:153420 建立时间:2006年4月11日 |

| |
|
[编程语言]C++字符串处理: 使用Boost Libraries(一) 原创空间, 软件技术
wdx04 发表于 2007/7/1 13:18:43 |
|
C++字符串处理: 使用Boost Libraries(一)
大多数C++应用程序都在一定程度上需要处理字符串。C++标准库通过basic_string、basic_stringstream类模版及在algorithm头文件中定义的一系列算法提供了对基本字符串操作的支持。但是,还有一些常用的字符串算法例如大小写转换、子串替换、分割、除去首尾空格、与数值类型转换和格式化,C++标准库并没有提供直接的实现。因此,作为C++标准库后备的Boost Libraries提供了很多字符串和文本处理库,不仅实现了前面提到的字符串算法,而且含有高级的正则表达式和语法分析库。
Boost Libraries包括以下几个通用字符串库:lexical_cast 最简单的一个库,用于处理字符串与其它数据类型的转换regex 最早的C++正则表达式库,经过多年发展已经很成熟tokenizer(1.25.0加入) 把字符串分割为一组记号(token)format(1.29.0加入) 提供类似C标准库函数printf的数据格式化操作spirit(1.30.0加入) 强大的语法分析器产生器,用C++语言直接表达EBNF语法string_algo(1.32.0加入) 包含大量的常用字符串算法xpressive(1.34.0加入) 和regex一样是正则表达式库,速度更快,挤进Boost全靠实力
Boost Libraries的用法很简单:从Boost官方网站(http://www.boost.org)把整个发行版本下载到本地并解压缩到任意本地目录(建议解压缩到硬盘某个分区的根目录下),并且将该目录加入到C++编译器的Include目录列表中即可。Boost中大多数库完全由头文件组成(扩展名为hpp),不需要编译就可以使用。少数库如regex需要用Boost的项目管理工具bjam预先编译才能使用。
500)this.width=500'>
(图:在VC6中设置Boost包含目录)
下面逐一解释这些库的用法。
Boost. Conversion/lexical_cast
很多时候我们需要把数值表示为字符串的形式,或者反过来,把以字符串表示的数字转换为通常的数值类型。标准C库和标准C++库提供了一些方法来做这个操作,但是要么就不够灵活和安全(itoa/atoi函数族),要么就显得比较繁琐(stringstream)。Boost. Conversion/lexical_cast就是为简化这个操作而设计的,它的公共接口声明为:namespace boost{ class bad_lexical_cast; template<typename Target, typename Source> Target lexical_cast(Source arg);}这里包含1个异常类bad_lexical_cast和1个模版函数lexical_cast。lexical_cast函数借助C++的stringstream,把类型为Source的字符串或数值转换为Target类型的数值或字符串。其中模版参数Source可以省略(因为编译器会根据arg的类型自动推知Source类型)。当arg不能正确转换为Target类型时,lexical_cast会抛出bad_lexical_cast异常。例子: string valid_int = "1234"; string valid_float = "23.786"; string invalid_float = "7c.82w"; int rint = 1234; double rdouble = 86253.45; // string to int int i = boost::lexical_cast<int, string>(valid_int); cout << "valid_int = " << i << endl; // string to float float f = boost::lexical_cast<float>(valid_float); cout << "valid_float = " << f <<endl; // invalid string to float try { f = boost::lexical_cast<float>(invalid_float); } catch(boost::bad_lexical_cast& ex) { cout << ex.what() << endl; } // int to string string s = boost::lexical_cast<string>(rint); cout << "rint = " << s << endl; // double to stirng s = boost::lexical_cast<string>(rdouble); cout <<"rdouble = " << s << endl;运行结果:valid_int = 1234valid_float = 23.786bad lexical cast: source type value could not be interpreted as targetrint = 1234rdouble = 86253.4完整例子参见示例工程的lexical_cast项目。值得一提的是,由于Visual C++ 6.0编译器的bug,不能通过using <命名空间>::<符号名>的方式引用命名空间中的单个符号。所以只能通过 using namespace boost;声明使用boost命名空间中所有的符号,或者像上例那样直接用带命名空间的完整名称。
Boost.Tokenizer
Boost.Tokenizer库提供了一种灵活易用的方式把字符序列分解为一系列记号。例如,下面的程序可以把一个英语句子分解为一系列单词:// simple_example_1.cpp#include<iostream>#include<boost/tokenizer.hpp>#include<string>
int main(){ using namespace std; using namespace boost; string s = "This is, a test"; tokenizer<> tok(s); for(tokenizer<>::iterator beg=tok.begin(); beg!=tok.end();++beg){ cout << *beg << "\n"; }}可以看出,这个库的核心就是tokenizer模版类,在构造tokenizer时传递一个源字符串作为参数,然后就可以通过迭代器取得分解出来的每一个记号,这个过程和遍历任何一个STL容器一样简单。通过设置tokenizer的模版参数可以指定分解字符串的规则: template < class TokenizerFunc = char_delimiters_separator<char>, class Iterator = std::string::const_iterator, class Type = std::string > class tokenizer;第一个参数TokenizerFunc是一个观念(concept)类型,指定如何区分记号的边界。第二个参数Iterator是字符串迭代器的类型,与被分隔的字符串类型有关。第三个参数Type是结果类型,也就是产生的每一个记号的类型,一般用std::string就可以了。Boost.Tokenizer库包含3种TokenizerFunc模型,分别适用于不同的情况。char_separator是默认的分隔器,以一组特定的字符来分隔记号,它的构造函数为:explicit char_separator(const Char* dropped_delims, const Char* kept_delims = "", empty_token_policy empty_tokens = drop_empty_tokens)dropped_delims和kept_delims是两个以0结尾的字符数组,这两个数组中的每个字符都是一个记号的终结符。不同的是,dropped_delims中的终结符本身被丢弃,而kept_delims中的字符本身作为一个单独的记号被保留下来。empty_tokens指示是否保留长度为0的记号。它有两个可选值boost::keep_empty_tokens表示要保留空记号,而默认的boost::drop_empty_tokens表示丢弃空记号。例子: std::string str = ";;Hello|world||-foo--bar;yow;baz|"; typedef boost::tokenizer<boost::char_separator<char> > tokenizer; boost::char_separator<char> sep("-;", "|", boost::keep_empty_tokens); tokenizer tokens(str, sep); for (tokenizer::iterator tok_iter = tokens.begin(); tok_iter != tokens.end(); ++tok_iter) std::cout << "<" << *tok_iter << "> ";结果为 <> <> <Hello> <|> <world> <|> <> <|> <> <foo> <> <bar> <yow> <baz> <|> <>offset_separator主要用于解析长度和格式都固定的字符串,像电话号码或时间日期等。它的构造函数为:template<typename Iter>offset_separator(Iter begin,Iter end,bool bwrapoffsets = true, bool breturnpartiallast = true)参数意义:begin, end: 指向一个整数容器offsets开始和末尾的迭代器。其中每个元素表示一个字段的字符数。bwrapoffsets: 如果字符串长度大于offsets容器中所有字段长度的和,是重复否用offsets继续解析字符串。breturnpartiallast: 当字符串解析到末尾时剩余的部分长度小于字段长度,是保留还是丢弃这个部分。例子: typedef offset_separator separator_type; typedef tokenizer<separator_type> tokenizer_type; int offsets[] = { 3, 3, 4 }; separator_type sep(offsets, offsets + 3); string s = "1234443627"; tokenizer_type tok(s, sep);遍历iterator将得到”123”(长度3),”444”(长度3)和”3627”(长度4)三个字符串escaped_list_separator解析包含转义符、分隔符和引号的字符串,可以看作CSV的强化版本。explicit escaped_list_separator(Char e = '\\', Char c = ',',Char q = '\"')explicit escaped_list_separator(string_type e, string_type c, string_type q)e为单个转义字符或包含多个转已字符的串。转义符后跟引号表示银号,转义符后跟n表示换行,连续两个转义符表示作为普通字符的转义符本身。c为记号分隔符。q为引号,两个引号中间出现的分隔符作为普通字符处理。例子: typedef escaped_list_separator<char> separator_type; typedef tokenizer<separator_type> tokenizer_type; string s = "field 1,\"field 2\",\"field,\\\"3\""; separator_type sep('\\', ',', '"'); tokenizer_type tok(s, sep);遍历iterator将得到<field 1> <field 2> <field,”3>三个字符串(不包括<>)完整例子参见示例工程的tokenizer项目,在该项目中 #include <boost/tokenizer.hpp> 包含指令没有写在stdafx.h中被预编译,而是直接写在.cpp源代码中,因为Visual C++ 6.0编译器对预编译头的处理有严重bug,很容易就出现致命的1001内部编译器错误。所以,如果要在实际项目中应用Boost Libraries,一定不要用Visual C++ 6.0自带的编译器,要么挂Intel C++ Compiler 6.0以上版本,要么就用Visual C++ 7.1(2003)以上版本。
例子工程文件:
500)this.width=500'>boost_test.rar
|
|
|
Player Exclusive Rewind: Antwan Jamison’s adidas Professor Mid 原创空间, 软件技术
Tiffany Necklaces New(游客)发表评论于2010/4/1 16:49:06 |
|
With its raised sidewalls, patent rand, and unfettered colorblocking, the adidas Professor proved to be a highly sought after commodity after the mid released in 2007. As a member of the Team USA Men’s Basketball Trial squad, Wizards forward Antwan Jamison was blessed with this white/blue/red version of the shoe. “USA” is inscribed along the upper ridge of the collar. If you can fit his size 16’s, or just appreciate Antwan Jamison or United States-themed apparel, head here to purchase them.Tiffany Necklaces New --> |
|
|
回复:C++字符串处理: 使用Boost Libraries(一) 原创空间, 软件技术
wdx04发表评论于2008/6/2 18:32:23 |
| escaped_list_separator构造函数中的e就是转义符,转义的规则和C/C++的字符常量类似。e也可以是一个字符串,此时e中包含的每一个字符都是转义字符。具体情况可以参考token_functions.hpp。 |
|
|
回复:C++字符串处理: 使用Boost Libraries(一) 原创空间, 软件技术
星星远好(游客)发表评论于2008/3/29 22:48:46 |
| 当char e='\\'时,是不是表明,以后\标志着转义呢?还是表示字符串中遇到\\为转义符呢?,实在不明白,望详解. |
|
|
回复:C++字符串处理: 使用Boost Libraries(一) 原创空间, 软件技术
星星远好(游客)发表评论于2008/3/29 22:46:40 |
| 楼主,您好,我刚刚学习boost库,看到您的blog不错也。
我向您请教一个问题:
tokenizer中escaped_list_separator中char e或string_type e有什么作用。它表明什么意思呢?
我没看懂,其它我看懂了。
如果您方便,回复一下发送到yijunjun@163.com
好不?
非常感谢。 |
|
» 1 »
|