• c++ stl 算法使用


    traverse elements in contianer

    associated container: set

    Compare between sets

    if you want to find the different elements in one set to another set, you could use the std::set_difference method

    	int i = 0;
    	set<int> s1 = boost::assign::list_of(++i).repeat_fun(10, [&i]()->int{return ++i;} ); // 1..to.. 11
    	i = 5;
    	set<int> s2 = boost::assign::list_of(++i).repeat_fun(10, [&i]()->int{return ++i;} ); // 6..to.. 16
    	set<int> dif;
    	std::set_difference(s1.begin(), s1.end(), s2.begin(), s2.end(), std::inserter(dif, dif.end()));
    	cout<<"dif:"<<endl;
    	std::for_each(dif.cbegin(), dif.cend(), [](const int& item){
    		cout<<item<<" "; // 1 2 3 4 5
    	});
    	cout<<endl;
    	dif.clear();
    	std::set_intersection(s1.begin(), s1.end(), s2.begin(), s2.end(), std::inserter(dif, dif.end()));
    	cout<<"dif:"<<endl;
    	std::for_each(dif.cbegin(), dif.cend(), [](const int& item){
    		cout<<item<<" "; // 6 7 8 9 10 11 
    	});
    	cout<<endl;
    	dif.clear();
    	std::set_symmetric_difference(s1.begin(), s1.end(), s2.begin(), s2.end(), std::inserter(dif, dif.end()));
    	cout<<"dif:"<<endl;
    	std::for_each(dif.cbegin(), dif.cend(), [](const int& item){
    		cout<<item<<" "; // 1 2 3 4 5 12 13 14 15 16
    	});
    	cout<<endl;

    If you ignore the std::insertor, you will get a compiler error said that: "you cannot assign to a variable that is const". Because elements in set container is immuable and the code inside the set_difference is "*Dest++ = *Iter1", so you can not assign a value to a variable that is const. the a variable is the element of set.

    You should know about the inserter in STL. For example, std::copy this algorithm is used to copy the elements in the range[first,last) into a range beginning atresult.

    	int i = 0;
    	vector<int> v1 = boost::assign::list_of(++i).repeat_fun(10, [&i]()->int{return ++i;} );
    	vector<int> v2;
    	std::copy(v1.begin(), v1.end(), v2.begin());
    	cout<<"v2:"<<endl;
    	std::for_each(v2.cbegin(), v2.cend(), [](const int& item){
    		cout<<item<<" ";
    	});
    	cout<<endl;
    The above code snippet will cause a exception as the v2 doesn't be allocated to enough space to copy. You can useresizemethod of vector to allocate specifed size before using std::copy. Note, reserve method just to change the capacity not to construct the element for vector.

    v2.resize(v1.size());
    Or you could use the inserter defined in STL for different posistion inserting (back inserters,front inserters, andgeneral inserters.). The definition of inserter iterator is:

    By using insert iterators, algorithms can insert rather than overwrite. All insert iterators are in the output-iterator category. Thus, they provide only the ability to assignnew values.Output iterators can only step forward with write access. Thus, you can assign new values only element-by-element. You can’t use an output iterator to iterate twice over the same range.

    back inserter will call the member function of the container: push_back, vailable only forvectors,deques,lists, andstrings.

    front inserter will call the member function of the container: push_front, vailable only for deques andlists.

    general inserter will call the member fucntion of the container: insert, vailable only for all standard containers exceptarraysandforward lists.

    using general inserter for associative containers, the position argument just acts as a hint to help to improve the performance for insert. But if the container is reserved order. the hint will be bad for the performance as each insert will start at a wrong postion.

    Back to the point, you can use back_inserter in copy algorithm like this code snippet.

    std::copy(v1.begin(), v1.end(), std::back_inserter(v2));

    Append/Join another set to one set

    There are two ways to append/join another set to one set.

    1. use the insert method of set.

    	int i = 0;
    	set<int> s1 = boost::assign::list_of(++i).repeat_fun(10, [&i]()->int{return ++i;} ); // 1..to.. 11
    	i = 5;
    	set<int> s2 = boost::assign::list_of(++i).repeat_fun(10, [&i]()->int{return ++i;} ); // 6..to.. 16
            s2.insert(s1.begin(), s1.end());
    s2 contains s1's elements.

    2. use the inserter and std::set_union algorithm

    set<int> all;
    std::set_union(s1.begin(), s1.end(), s2.begin(), s2.end(), std::inserter(all, all.end()));

    Retrieve Map's key collection

    There are three way to retrieve map's key collection.

    1. using lambda and std::transform to traverse the map to get keys.

    std::transform(mymap.cbegin(), mymap.cend(), std::inserter(myset, exist.end()), [](const mymap::value_type& item)-> mykey{
    			return item.first;
    		});

    2. using boost::bind

    std::transform(m1.begin(), m1.end(), std::inserter(sm, sm.end()), boost::bind(&std::pair<const int, int>::first, _1));

    3. using sgi::select1st

    std::transform(M.begin(), M.end(), ostream_iterator<int>(cout, " "),
                select1st<map<int, int>::value_type>());

    Compare float/double variable

    When comparing two double or float data type, you should not use "==" directly, you should choose to use the code snippet listed below.

    #include <cmath>
    #include <limits>
    
    template<typename T>
    bool IsEqual(T lhs, T rhs)
    {
    	return std::fabs(lhs - rhs) < std::numeric_limits<T>::epsilon();
    }

    Using "typedef" defines array/function

    typedef char NAME[32];


    Override ostream operator

    As the operator<< needs two operands, the ostream and the target object. So the override function should be defined as global function, not the member function(with this pointer as the first argument.). Can also be defined as friend keyword to access the private member variables.

    ostream& operator<<(ostream& ous,const DefinedType& p1)

    If you meet compiler error for LNK2005 and LNK1169, please declare the function declaration on header file and the implement in source file.

    Override the compare function for map or set

    1. in the class or struct, implement the operator <.

    struct Real
    {
    	int value;
    	int format;
    	bool operator < (const Real& rhs) const
    	{
    		return value < rhs.value;
    	}
    };
    typedef map<Real, int> MR;
    2. implement the binary_function

    struct RealLess : public std::binary_function<const Real&, const Real&, bool>
    {
    	bool operator()(const Real& lhs, const Real& rhs) const
    	{
    		return lhs.value < rhs.value;
    	}
    };
    typedef std::map<Real, int, RealLess> MR1;

    Convert hex string to unsigned int

    using std::hex

    #include <sstream>
    stringstream ss;
    unsigned int val;
    ss << "ff";
    ss >> std::hex >> val;
    cout<<val <<endl;
    If you need to parse in loop, please calling the clear function in the loop of stringstream variable.
  • 相关阅读:
    ArcObjects SDK(AE)10.1在vs2012安装的方法(亲测,并未成功,尝试需谨慎)
    PTA 求链式表的表长
    PTA 输出数组元素
    PTA 找出不是两个数组共有的元素
    PTA 将数组中的数逆序存放
    PTA 利用指针找最大值
    PTA 有序数组的插入
    PTA 冒泡排序
    PTA 报数
    PTA 数组循环右移
  • 原文地址:https://www.cnblogs.com/rogerroddick/p/2846716.html
Copyright © 2020-2023  润新知