[C++快速开发] 查询
2014-12-05 16:47
162 查看
本文介绍C++语言中进行查询操作的高效模板。
提起查询,最先想到的应该就是find函数,find函数的定义如下:
template<class InputIterator, class T> InputIterator find(InputIterator first, InputIterator last, const T& val);
简单的说,就是确定查询的起始点和终止点及查询的内容,返回第一次找到的位置。
还是给一个例子:
查找数组中数字5第一次出现的位置。
对于数组,find的返回值是一个指针。上面的例子中,返回的指针index的值就是a数组中数字5出现位置的地址。下一行输出的是该位置的下标,结果为2。
如果查不到,返回的是指向数组后一个位置的指针。如在例子中,将查询值改为11,则输出值为5。
如果是对于string的操作,查找'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的例子。查找偶数。
在上面的例子中,find_if的第三个参数是一个lambda表达式,有关lambda的相关介绍请参考本人的另一篇文章:在C++中使用lambda (http://blog.csdn.net/xiahn1a/article/details/41665339)
建议大家都能掌握lambda,这个对于快速开发很有帮助。如果不使用lambda,则需要单独声明一个布尔返回值的函数:
调用find_if时直接使用函数名即可。
上面介绍的find / find_if函数可以用来做什么?指定元素定位,判断是否存在指定元素,这些都是可以的。
但经常还可以看到有很多人把它用来提取满足条件的元素,或者对满足条件的元素进行计数,而且有很多论坛的帖子也是这么教的。不可否认这可以做,但效率不一定比for循环高,而且代码不一定比直接for循环简单。可以用一些更优化的函数模板来做这些问题。
对满足条件的元素计数,可以使用count / count_if函数。其中count_if是count的泛型。
count函数的函数参数与find函数是相同的,只是返回值是满足条件的元素个数,例子就不给了。
count_if函数的参数与find_if函数相同,只是返回值是满足条件元素个数,给一个和上面相似的例子。求偶数的个数。
对于提取所有满足条件的元素,可以使用copy_if函数。
还是上面的例子,提取所有偶数。
在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。
从上面这么多的例子可以看出,对于查询所要做的各种操作,我们不一定全部要依赖于一个find函数来实现,这样无论是实现的开销还是代码量都是大的。C++语言已经为我们提供了这些好用的函数,我们为什么不用呢?
本文所涉及代码均在Visual Studio 2015中通过。部分代码如lambda表达式,需要支持C++ 11标准的编译器,如最新版G++及VS2012及以上版本等。
提起查询,最先想到的应该就是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及以上版本等。
相关文章推荐
- [框架那点事儿-快速开发季]编写自己的数据持久层(4)分页查询
- C++开发人员快速学习C#
- RDIFramework.NET ━ .NET快速信息化系统开发框架 V3.0 版新增查询引擎管理
- CRL快速开发框架系列教程二(基于Lambda表达式查询)
- Winform开发框架之通用高级查询模块--SNF快速开发平台3.3-Spring.Net.Framework
- c++的意义。。(个人感觉使用c++可以接触到软件的本质,虽然不能直接开发快速但你可以有自由的感觉,尤其是指针,和直接贴近内存的本质)
- SNF快速开发平台MVC-高级查询组件
- 快速测试dao层查询代码是否正确的开发技巧
- kphp企业站快速开发之关联字段查询方法:mysql的find_in_set()函数
- 用C++Qt 与libfcgi快速开发后台 WebService
- 适易快速开发、查询分析、工作流、内容管理及项目管理试用版下载
- C++程序员学习android开发快速入门指引
- MongoDB 查询 (转) 仅限于C++开发
- RDIFramework.NET ━ .NET快速信息化系统开发框架 V3.0 版新增查询引擎管理
- 开发指南专题七:JEECG微云快速开发平台查询HQL过滤器
- C++开发人员快速学习C#
- 快速构建C++项目工具Scons,结合Editplus搭建开发环境
- 如何快速开发树形列表和分页查询整合的WInform程序界面
- 天纵智能软件快速开发平台状态图查询分析插件
- 企慧Q5快速开发平台系列之二:数据查询设计