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.
原文地址:https://www.cnblogs.com/rogerroddick/p/2846716.html