我正在编写一个代码,我需要验证填充了多个std::vector
对象的std::string
。逻辑是我需要检查所有对象是否有效。如果是,则显示一条消息,指出输入向量有效,否则出错。这是我到目前为止所拥有的。
#include<iostream>
#include<vector>
#include<numeric>
#include<boost/foreach.hpp>
short multiply(short s1,short s2)
{
return s1*s2;
}
bool validate(const std::vector<std::string> &in)
{
std::vector<short>check(in.size(),0);
auto checkitr = check.begin();
BOOST_FOREACH(std::string str,in)
{
for(auto itr = str.begin(); itr != str.end(); ++itr)
{
if(*itr == 'c')
{
*checkitr = 1;
break;
}
}
++checkitr;
}
short product = std::accumulate(check.begin(),check.end(),1,multiply);
return ( (product) ? true : false );
}
int main()
{
std::string s1("abcd");
std::string s2("lncd");
std::vector<std::string>iVec;
iVec.push_back(s1);
iVec.push_back(s2);
bool isValid = validate(iVec);
if(isValid){
std::cout<<"This Vector is valid "<<std::endl;
}
else
{
std::cout<<"This is an invalid vector "<<std::endl;
}
iVec.push_back(std::string("ghkd"));
isValid = validate(iVec);
if(isValid){
std::cout<<"This Vector is valid "<<std::endl;
}
else
{
std::cout<<"This is an invalid vector "<<std::endl;
}
return 0;
}
这很好,给了我需要的结果。我的问题是, 我可以使用标准算法或升级库中的其他更好/性能更高的方法而不是我当前的方法吗?
答案 0 :(得分:4)
包含验证算法应该验证的内容的描述会很好,但我认为源是自我记录的。要确定字符串向量是否仅包含包含c
的字符串,请使用
#include <algorithm> // for std::none_of
#include <iterator> // for std::begin, std::end
bool validate(const std::vector<std::string> &in)
{
return std::none_of(std::begin(in),
std::end (in),
[](std::string const &s) {
return s.find('c') == std::string::npos;
});
}
std::none_of
检查范围中的元素是否满足条件,[](std::string const &s) { ... }
是描述条件std::none_of
应该使用的lambda表达式。放在一起,检查是否有一个字符串在向量中不包含c
,如果没有,则返回true
,如果有,则返回false
。
与此代码相比,主要的运行时优势在于,只要找到不包含c
的字符串,就会停止检查;除此之外,它大多缩短(除非std::string::find
的实现包含聪明的优化,这是不可能的)。
旁注:由于argument-dependent name lookup,可能会遗漏该代码中的许多std::
。我在原始代码中留下了一些但是把它们放回去了
在@BoBTFish评论之后,以避免混淆;我倾向于将它们留给begin
和end
,因为我曾经这样做过。这是因为在模板的上下文中有一些(有些)有用的技巧,它与上述函数没有实际关系,但是在这里(如果你感兴趣的话):
如果您希望此验证例程不仅适用于矢量,您可以编写
template<typename Container>
bool validate(Container &&in)
{
using std::begin;
using std::end;
return std::none_of(begin(std::forward<Container>(in)),
end (std::forward<Container>(in)),
[](std::string const &s) {
return s.find('c') == std::string::npos;
});
}
这改编自Scott Meyers在Effective C ++中描述的std::swap
的类似技术;有用的是,如果begin(...)
和end(...)
在Container
和std::begin
的拟合实现中定义了std::end
引用的类型,则它们优先于std::begin
和std::end
- 这很好,因为如果它们存在,那么假设它们提供了更好的契合是明智的。
(当然.begin()
和.end()
使用begin
和end
成员函数的默认行为会使std::none_of
和std::find_if
大部分都是不必要的,但我在现实生活中的代码中看到了一些奇怪的东西。)
std::find_if
;原始解决方案使用std::none_of
。当然,{{1}}也有效,但{{1}}显然更适合。