[C++快速开发] 查询

本文介绍C++语言中进行查询操作的高效模板。


提起查询,最先想到的应该就是find函数,find函数的定义如下:

template<class InputIterator, class T> InputIterator find(InputIterator first, InputIterator last, const T& val);

简单的说,就是确定查询的起始点和终止点及查询的内容,返回第一次找到的位置。

还是给一个例子:

查找数组中数字5第一次出现的位置。

int a[] = { 1, 3, 5, 7, 9 };
int* index = find(a, a + 5, 5);
cout << (int)(index - a) << endl;

对于数组,find的返回值是一个指针。上面的例子中,返回的指针index的值就是a数组中数字5出现位置的地址。下一行输出的是该位置的下标,结果为2。

如果查不到,返回的是指向数组后一个位置的指针。如在例子中,将查询值改为11,则输出值为5。

如果是对于string的操作,查找'a'第一次出现的位置。

string s = "Hello";
int index = s.find('a');

结果index直接就是第一次出现的位置下标。

如果是对于vector或者list等结构,调用find函数方法与数组类似,但所有的参数由数组中的指针变为相应的迭代器。

其他的如find_first_of, find_last_of, find_first_not_of 用法都与find类似,只是意义稍有不同。


对于上面的find函数,只能以一个等于特定的值作为查找条件,而不能以一个范围作为限定条件。

下面介绍find_if函数,可以理解为find函数的泛型,其定义如下:

template<class InputIterator, class Predicate> InputIterator find_if(InputIterator first, InputIterator last, Predicate pred);

这个函数也是有三个参数,前两个参数也是表示find的起始和终止位置,第三个参数一般为一个布尔类型的函数,用于给出筛选条件,满足条件的返回true。该函数的返回值的情形与find是相同的。

find函数给过数组和string的例子,这里就给一个vector的例子。查找偶数。

vector<int> a = { 1, 2, 3, 4 };
auto res = find_if(a.begin(), a.end(), [](int x) -> bool { if (x % 2 == 0) return true; else return false; });
结果res是引用第一个满足条件的元素的迭代器。如果查找不到则返回last的迭代器。与find函数相同。
在上面的例子中,find_if的第三个参数是一个lambda表达式,有关lambda的相关介绍请参考本人的另一篇文章:在C++中使用lambda ( http://blog.csdn.net/xiahn1a/article/details/41665339)

建议大家都能掌握lambda,这个对于快速开发很有帮助。如果不使用lambda,则需要单独声明一个布尔返回值的函数:

bool ret(int x)
{
	if (x % 2 == 0) 
		return true; 
	else 
		return false;
}

调用find_if时直接使用函数名即可。

auto res = find_if(a.begin(), a.end(), ret });


上面介绍的find / find_if函数可以用来做什么?指定元素定位,判断是否存在指定元素,这些都是可以的。

但经常还可以看到有很多人把它用来提取满足条件的元素,或者对满足条件的元素进行计数,而且有很多论坛的帖子也是这么教的。不可否认这可以做,但效率不一定比for循环高,而且代码不一定比直接for循环简单。可以用一些更优化的函数模板来做这些问题。


对满足条件的元素计数,可以使用count / count_if函数。其中count_if是count的泛型。

count函数的函数参数与find函数是相同的,只是返回值是满足条件的元素个数,例子就不给了。

count_if函数的参数与find_if函数相同,只是返回值是满足条件元素个数,给一个和上面相似的例子。求偶数的个数。

vector<int> a = { 1, 2, 3, 4 };
auto res = count_if(a.begin(), a.end(), [](int x) -> bool { if (x % 2 == 0) return true; else return false; });

对于提取所有满足条件的元素,可以使用copy_if函数。

还是上面的例子,提取所有偶数。

vector<int> a = { 1, 2, 3, 4 };
vector<int> b(a.size());
auto res = copy_if(a.begin(), a.end(), b.begin(), [](int x) -> bool { if (x % 2 == 0) return true; else return false; });
b.resize(distance(b.begin(), res));
for (int x : b)
	cout << ' ' << x;
可以看到相比于前面的find_if和count_if。copy_if函数多了第三个参数,表示copy到的位置。其余参数意义仍相同。

在copy的时候做了处理,先预设b的大小为a,然后resize改变b的大小。resize中使用了函数distance,即计算两个迭代器之间的元素个数差。res表示copy到的数组(例子中为b)的拷贝结束点的后一位的迭代器,即copy_if函数的返回值。
还有函数remove_copy_if,是拷贝不满足条件的元素。即原集合与copy_if拷贝后的集合的差集。remove_copy_if与copy_if函数的参数及返回值意义相同。


如果要求是查找所有满足条件的结果并做替换。此时就要用到replace / replace_if函数。replace_if是replace的泛型。

用法都是相似的,只给一个replace_if函数的例子。

还是上面的例子,将所有偶数替换为1。

vector<int> a = { 1, 2, 3, 4 };
replace_if(a.begin(), a.end(), [](int x) -> bool { if (x % 2 == 0) return true; else return false; }, 1);
可以看出copy_if函数前两个参数也是指示位置,第三个参数是判断条件,第四个参数是替换后的值。这个函数返回值为void。

从上面这么多的例子可以看出,对于查询所要做的各种操作,我们不一定全部要依赖于一个find函数来实现,这样无论是实现的开销还是代码量都是大的。C++语言已经为我们提供了这些好用的函数,我们为什么不用呢?


本文所涉及代码均在Visual Studio 2015中通过。部分代码如lambda表达式,需要支持C++ 11标准的编译器,如最新版G++及VS2012及以上版本等。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值