欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Boost库基础-字符串与文本处理(string_algo)

程序员文章站 2024-03-14 11:11:04
...

string_algo

string_algo被设计用于处理字符串,然而处理对象并不一定是string或basic_string<T>,可以是任何符合boost.range要求的容器。容器内的元素也不一定是char或wchar_t,任何可拷贝和赋值的类型均可,但如果类型的拷贝赋值代价很高,那么string_algo的性能会下降。

string_algo库位于名字空间boost::algorithm,但被using语句引入到了名字空间boost,为了使用它,需要包含头文件

#include <boost/algorithm/string.hpp>
using namespace boost;

string_algo库提供的算法共分五大类:

  • 大小写转换;
  • 判断式与分类;
  • 修剪;
  • 查找与替换;
  • 分割与合并;

string_algo库中的算法命名遵循了标准库的惯例,算法名均为小写形式,并使用不同的词缀来区分不同的版本,命名规则:

  • 前缀 i:大小写不敏感(忽略大小写);
  • 后缀_copy:不变动输入,返回处理结果的拷贝,否则原地处理,输入即输出;
  • 后缀_if:需要一个作为判断式的函数对象,否则使用默认的判断准则;

大小写转换

#include <iostream>
#include <string>
#include <boost/algorithm/string.hpp>

using namespace boost;
using namespace std;

int main()
{
	string str("I Don't Know.\n");

	//转换为大写
	cout << to_upper_copy(str) << endl;

	//原字符串不变
	cout << str << endl;

	//转换我小写
	to_lower(str);

	//原字符串被改变
	cout << str << endl;

	getchar();
	return 0;
}

 运行结果:

Boost库基础-字符串与文本处理(string_algo)

判断式(算法)

主要检测两个字符串之间的关系,包含以下几种:

  • lexicographical_compare:根据字典顺序检测一个字符串是否小于另一个;
  • starts_with:检测一个字符串是否以另一个为前缀;
  • ends_with:检测一个字符串是否以另一个为后缀;
  • contains:检测一个字符串是否包含另一个;
  • equals:是否相等;
  • all:检测一个字符串中的所有元素是否满足指定的判断式;

除了all,这些算法都有 i 前缀的版本。由于它们不变动字符串,因此没有_copy版本。

用法:

#include <iostream>
#include <string>
#include <boost/algorithm/string.hpp>

using namespace boost;
using namespace std;

int main()
{
	string str("Power Bomb");

	//大小写无关检测
	assert(iends_with(str, "bomb"));

	//大小写敏感检测后缀
	assert(!ends_with(str, "bomb"));

	//检测前缀
	assert(starts_with(str, "Pow"));

	//检测包含关系
	assert(contains(str, "er"));

	//转换小写
	string str2 = to_lower_copy(str);

	//大小写转换无关判断
	assert(iequals(str, str2));

	string str3("power suit");

	//大小写无关比较
	assert(ilexicographical_compare(str, str3));

	//检测字符串均小写
	assert(all(str2.substr(0, 5), is_lower()));

	getchar();
	return 0;
}

判断式(函数对象) 

允许对不同类型的参数进行比较,并提供大小写无关的形式。

  • is_equal:比较两个对象是否相等
  • is_less:比较两个对象是否小于关系
  • is_not_greater:比较两个对象是否不大于关系

用法:

#include <iostream>
#include <string>
#include <boost/algorithm/string.hpp>

using namespace boost;
using namespace std;

int main()
{
	string str1("Samus");
	string str2("samus");

	assert(!is_equal()(str1, str2));

	assert(is_less()(str1, str2));

	getchar();
	return 0;
}

注意:调用的两个括号,第一个括号调用了函数对象的构造函数,产生一个对象,第二个才是函数调用。

分类

用于检测一个字符是否符合某种特性。

Boost库基础-字符串与文本处理(string_algo)

修剪

string_algo提供了三个修剪算法:trim_left、trim_right和trim。

修剪算法可以删除字符串开头或结尾部分的空格,它有_if 和_copy 两种后缀,因此每个算法有四个版本。_if版本接受一个判断式IsSpace,将所有被判定为空格(IsSpace(c) == true)的字符删除。

用法:

#include <iostream>
#include <string>
#include <boost/format.hpp>
#include <boost/algorithm/string.hpp>

using namespace boost;
using namespace std;

int main()
{
	format fmt("|%s|\n");

	string str = "  samus aran  ";

	//删除两端的空格
	cout << fmt % trim_copy(str) << endl;

	//删除左端空格
	cout << fmt % trim_left_copy(str) << endl;

	//原地删除右端空格
	trim_right(str);

	cout << fmt % str << endl;

	string str2 = "2020 Happy new Year!!!";

	//删除左端的数字
	cout << fmt % trim_left_copy_if(str2, is_digit());

	//删除右端的标点
	cout << fmt % trim_right_copy_if(str2, is_punct());

	//删除两端的标点、数字和空格
	cout << fmt % trim_copy_if(str2, is_punct() || is_digit() || is_space());

	getchar();
	return 0;
}

运行结果:

Boost库基础-字符串与文本处理(string_algo)

查找

string_algo算法它不返回一个迭代器(查找到的位置),而使用了boost.range库的iterator_range返回查找到的整个区间,获得了更多的信息,便于算法串联和其他处理。

iterator_range 概念上类似  std::pair<iterator,iterator>,包装了两个迭代器,可以用begin()和end()访问。相当于定义了一个容器的子区间。

Boost库基础-字符串与文本处理(string_algo)

这些算法都不变动字符串,因此没有_copy后缀版本,但其中前三个算法有 i 前缀的版本。

使用:

#include <iostream>
#include <string>
#include <boost/format.hpp>
#include <boost/algorithm/string.hpp>

using namespace boost;
using namespace std;

int main()
{
	format fmt("|%s| . pos = %d\n");

	string str = "Long long ago , there was a king.";

	//迭代器区间
	iterator_range<string::iterator> rge;

	//查找第一次出现
	rge = find_first(str, "long");
	cout << fmt % rge % (rge.begin() - str.begin()) << endl;

	//大小写无关找第一次出现
	rge = ifind_first(str, "long");
	cout<< fmt % rge % (rge.begin() - str.begin()) << endl;

	//找第三次出现
	rge = find_nth(str, "ng", 2);
	cout << fmt % rge % (rge.begin() - str.begin()) << endl;
	
	//取前4个字符
	rge = find_head(str, 4);
	cout << fmt % rge % (rge.begin() - str.begin()) << endl;

	//取末尾5个字符
	rge = find_tail(str, 5);
	cout << fmt % rge % (rge.begin() - str.begin()) << endl;
	
	//找不到
	rge = find_first(str, "samus");
	assert(rge.empty() && !rge);

	getchar();
	return 0;
}

替换与删除

替换、删除操作与查找算法非常接近,是在查找到结果后再对字符串进行处理。

Boost库基础-字符串与文本处理(string_algo)

前八个算法每个都有前缀 i 、后缀_copy 和组合,有4个版本,后四个则只有后缀_copy两个版本。

用法:

#include <iostream>
#include <string>
#include <boost/format.hpp>
#include <boost/algorithm/string.hpp>

using namespace boost;
using namespace std;

int main()
{
	string str = "Samus beat the monster.\n";

	//替换第一次出现的地方
	cout << replace_first_copy(str, "Samus", "samus") << endl;

	//替换在最后一次出现的地方
	replace_last(str, "beat", "kill");
	cout << str << endl;

	//替换末尾9个字符
	replace_tail(str, 9, "ridley.\n");
	cout << str << endl;
	
	//不分大小写删除出现的所有位置
	cout << ierase_all_copy(str, "samus") << endl;

	//找到r字符出现第1次 将 r 替换为 L
	cout << replace_nth_copy(str, "r", 0, "L");

	//删除尾部8个字符
	cout << erase_tail_copy(str, 8);

	getchar();
	return 0;
}

分割

  • find_all:类似普通的查找算法,它搜索所有匹配的字符串,加入到容器中,有一个狐狸卡大小写的前缀 i 版本。
  • spit:使用判断式Pred来确定分割的依据,如果字符 ch 满足判断式 Pred(Pred(ch) == true),那么它就是一个分隔符,spit中第4个参数可以取值为 token_compress_on或token_compress_off,如果为第一个,那么当两个分隔符连续出现时被视为一个,如果后第二个,两个连续的分隔符标记了一个空字符串。默认取值为token_compress_off。

用法:

#include <iostream>
#include <string>
#include <boost/format.hpp>
#include <boost/algorithm/string.hpp>

using namespace boost;
using namespace std;

int main()
{
	string str = "A,B.C::Dd-Ee+DD";

	deque<string> d;

	//大小写无关分割字符串
	ifind_all(d, str, "Dd");

	//遍历deque里字符串
	for (auto x : d)
	{
		cout << "[" << x << "]";
	}
	cout << endl;

	//存储range对象
	list < iterator_range<string::iterator>> l;

	//使用标点分割
	split(l, str, is_any_of(",.:-+"));

	//遍历
	for (auto x : l)
	{
		cout << "[" << x << "]";
	}
	cout << endl;

	l.clear();

	split(l, str, is_any_of(".:-"), token_compress_on);

	for (auto x : l)
	{
		cout << "[" << x << "]";
	}
	cout << endl;

	getchar();
	return 0;
}

运行截图:

Boost库基础-字符串与文本处理(string_algo)

合并 

join算法是分割算法的逆运算,它把存储在容器中的字符串连接成一个新的字符串,并且可以指定连续的分隔符。

join有一个后缀 _if 的版本。

用法:

#include <iostream>
#include <string>
#include <vector>
#include <boost/assign.hpp>
#include <boost/utility/string_ref.hpp>
#include <boost/algorithm/string.hpp>

using namespace boost;
using namespace std;
using namespace boost::assign;

int main()
{
	//向vetor添加了4个字符
	vector<string> v = list_of("Samus")("Link")("Zelda")("Mario");

	//用+合并它们
	cout << join(v, "+") << endl;

	//lambda表达式,判断包含a的 才合并
	cout << join_if(v, "**", [](string_ref s)
	{
		return contains(s, "a");
	});

	getchar();
	return 0;
}

运行结果:

Boost库基础-字符串与文本处理(string_algo)

查找(分割)迭代器

find_iterator 和 split_iterator

使用:

#include <iostream>
#include <string>
#include <vector>
#include <boost/assign.hpp>
#include <boost/utility/string_ref.hpp>
#include <boost/algorithm/string.hpp>

using namespace boost;
using namespace std;

int main()
{
	string str("Samus | | samus | | mario | |  | | Link");

	//查找迭代器定义
	typedef find_iterator<string::iterator> string_find_iterator;

	//声明变量
	string_find_iterator pos, end;

	//遍历
	for (pos = make_find_iterator(str, first_finder("samus", is_iequal())); pos != end; ++pos)
	{
		cout << "[" << *pos << "]";
	}
	cout << endl;

	//分割迭代器类型定义
	typedef split_iterator<string::iterator> string_split_iterator;

	//声明变量
	string_split_iterator p, endp;
	for (p = make_split_iterator(str, first_finder(" | | ", is_equal())); p != endp; ++p)
	{
		cout << "[" << *p << "]";
	}
	cout << endl;

	getchar();
	return 0;
}

运行结果:

Boost库基础-字符串与文本处理(string_algo)

 

相关标签: Boost