std :: vector中的字符串验证

时间:2015-02-21 09:34:19

标签: c++ c++11 boost

我正在编写一个代码,我需要验证填充了多个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;
}

这很好,给了我需要的结果。我的问题是, 我可以使用标准算法或升级库中的其他更好/性能更高的方法而不是我当前的方法吗?

1 个答案:

答案 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评论之后,以避免混淆;我倾向于将它们留给beginend,因为我曾经这样做过。这是因为在模板的上下文中有一些(有些)有用的技巧,它与上述函数没有实际关系,但是在这里(如果你感兴趣的话):

如果您希望此验证例程不仅适用于矢量,您可以编写

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(...)Containerstd::begin的拟合实现中定义了std::end引用的类型,则它们优先于std::beginstd::end - 这很好,因为如果它们存在,那么假设它们提供了更好的契合是明智的。

(当然.begin().end()使用beginend成员函数的默认行为会使std::none_ofstd::find_if大部分都是不必要的,但我在现实生活中的代码中看到了一些奇怪的东西。)

编辑:我没有立刻想到std::find_if;原始解决方案使用std::none_of。当然,{{1}}也有效,但{{1}}显然更适合。