STL learning road

Posted by imtaqi on Thu, 06 Feb 2020 14:18:03 +0100

Article directory

STL basic concepts

In order to establish a set of standards for data structure and algorithm, and reduce the coupling relationship between them, so as to improve their independence, flexibility and interoperability, STL was born.
STL can be broadly divided into: the container algorithm iterator, and the container and algorithm are seamlessly connected through the iterator. Almost all STL code uses template classes or template functions, which provides a better opportunity for code reuse than the traditional library composed of functions and classes. STL(Standard Template Library) standard template library, which is subordinate to STL in our c + + standard library, accounts for more than 80%.

Introduction to STL components

STL provides six components, which can be combined and applied to each other. These six components are: container, algorithm, iterator, functor, adapter (adapter), space configurator.
Container: various data structures, such as vector, list, deque, set, map, etc., are used to store data. From the perspective of implementation, STL container is a class template.
Algorithm: various commonly used algorithms, such as sort, find, copy, for each. From the point of view of implementation, STL algorithm is a function template
Iterator: it acts as the glue between container and algorithm. There are five types in total. From the perspective of implementation, iterator is a class template that overloads pointer related operations such as operator *, operator - >, operator + +, operator -. All STL containers are provided with their own exclusive iterators, and only the container designer knows how to traverse their own elements. Native pointer is also an iterator.
Imitative function: it behaves like a function and can be used as a strategy of the algorithm. From the implementation point of view, a generic function is a class or class template that overloads operator()
Adapter: something used to decorate a container or a function or iterator interface.
Space configurator: responsible for space configuration and management. From the implementation point of view, configurator is a class tempalt which realizes dynamic space configuration, space management and space release
The six components of STL interact with each other. The container obtains the data storage space through the space configurator. The algorithm stores the contents of the container through the iterator. The generic function can help the algorithm to complete the changes of different strategies. The adapter can modify the generic function.

STL advantages

1.STL is part of C + +, so it's built into your compiler without any extra installation.
2. An important feature of STL is to separate data and operation. Data is managed by container categories, and operations are defined by customizable algorithms. The iterator acts as a "glue" between the two so that the algorithm can interact with the container
3. Programmers do not need to think about the specific implementation process of STL, as long as they can skillfully use STL. So they can focus on other aspects of program development.
STL has the advantages of high reusability, high performance, high portability and cross platform.
4. High reusability: almost all the code in STL is implemented by template class and template function, which provides a better opportunity for code reuse than the traditional library composed of functions and classes. Knowledge about templates
Yes, I have introduced it to you.
5. High performance: for example, map can efficiently find out the specified records from 100000 records, because map is implemented with the variant of red black tree.
6. High portability: for example, modules written in STL on project A can be directly ported to project B.

Three components of STL

Common data structures: array, list, tree, stack, queue, set, map. According to the arrangement characteristics of data in the container, these data can be divided into sequential container and associated container.

1. The sequential container emphasizes the sorting of values. Each element in the sequential container has a fixed position, unless the position is changed by the operation of deletion or insertion. Vector container, Deque container, List container, etc.
2. The relational container is a non-linear tree structure, more accurately, a binary tree structure. There is no strict physical order relationship between the elements, that is, the logical order of the elements when they are put into the container is not saved in the container. Another remarkable feature of associative container is that it selects a value as the key key in the value, which plays an index role in the value and is easy to find. Set/multiset containermap / Multimap container

iterator

The iterator pattern is defined as follows: a method is provided to enable the iterator to search the elements contained in a container in order without exposing the internal representation of the container.
The design thinking of iterators - the key of STL, the central idea of STL is to separate containers and algorithms, design independently of each other, and finally match them with adhesive. From the technical point of view, it is not difficult to generalize the container and algorithm. The class template and function template of c + + can achieve the goal respectively. If a good adhesive between the two is designed, it is a big problem.

Preliminary understanding of three components

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include <string>
using namespace std;

//Container vector
#include <vector>

//Header file using system algorithm
#include <algorithm>



// Iterator traversal function understood by pointer
//Ordinary pointer is also an iterator
void test01()
{
	int array[5] = { 1, 3, 5, 6, 8 };

	int * p = array; //Pointer to array first address & array [0]

	for (int i = 0; i < 5;i ++)
	{
		//cout << array[i] << endl;
		cout << *(p++) << endl;
	}
}


void myPrint(int v)
{
	cout << v << endl;
}

void test02()
{
	//Declaring container
	vector<int> v; //Declare a container in which the int type data object name v is stored
	//Add data to container

	v.push_back(10);
	v.push_back(20);
	v.push_back(30);
	v.push_back(40);

	//Traverse data in container
	//Using iterators

	vector<int>::iterator itBegin = v.begin(); // itBegin points to the starting position in the v container

	vector<int>::iterator itEnd = v.end(); //itEnd points to the next address of the last location in the v container

	//while (itBegin != itEnd)
	//{
	//	cout << *itBegin << endl;

	//	itBegin++;
	//}


	//The second way to traverse
	//for (int i = 0; i < 10;i++)
	//for (vector<int>::iterator it = v.begin(); it != v.end();it++)
	//{
	//	cout << *it << endl;
	//}

	//The third way to use the algorithm
	for_each(v.begin(), v.end(), myPrint);


}
//Action custom data type
class Person
{
public:
	Person(string name, int age)
	{
		this->m_Name = name;
		this->m_Age = age;
	}

	string m_Name;
	int m_Age;
};

void test03()
{
	vector<Person> v;
	Person p1("Big head son", 10);
	Person p2("Little daddy", 32);
	Person p3("Uncle Wang next door", 30);
	Person p4("Apron mom", 28);

	v.push_back(p1);
	v.push_back(p2);
	v.push_back(p3);
	v.push_back(p4);

	//ergodic
	for (vector<Person>::iterator it = v.begin(); it != v.end();it++)
	{
		cout << "Full name: " << (*it).m_Name << " Age:" << it->m_Age << endl;
	}
}

//Pointer to hold custom data type
void test04()
{
	vector<Person *> v;
	Person p1("Big head son", 10);
	Person p2("Little daddy", 32);
	Person p3("Uncle Wang next door", 30);
	Person p4("Apron mom", 28);

	v.push_back(&p1);
	v.push_back(&p2);
	v.push_back(&p3);
	v.push_back(&p4);

	for (vector<Person*>::iterator it = v.begin(); it != v.end();it++)
	{
		cout << "Full name:: " << (*it)->m_Name << " Age: " << (*it)->m_Age << endl;
	}

}

//Container nested container
void test05()
{
	vector<vector<int>> v;

	vector<int>v1;
	vector<int>v2;
	vector<int>v3;


	for (int i = 0; i < 5;i++)
	{
		v1.push_back(i);
		v2.push_back(i + 10);
		v3.push_back(i + 100);
	}
	//Put the small container into the large one
	v.push_back(v1);
	v.push_back(v2);
	v.push_back(v3);

	//Traverse all data
	for (vector<vector<int>>::iterator it = v.begin(); it != v.end();it++)
	{
		for (vector<int>::iterator vit = (*it).begin(); vit != (*it).end();vit++)
		{
			cout << *vit << " ";
		}
		cout << endl;
		 
	}

}


int main(){

	//test01();

	//test02();
	//test03();
	//test04();
	test05();
	system("pause");
	return EXIT_SUCCESS;
}

Basic use of three components

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include <string>
using namespace std;

//Container vector
#include <vector>

//Header file using system algorithm
#include <algorithm>



// Iterator traversal function understood by pointer
//Ordinary pointer is also an iterator
void test01()
{
	int array[5] = { 1, 3, 5, 6, 8 };

	int * p = array; //Pointer to array first address & array [0]

	for (int i = 0; i < 5;i ++)
	{
		//cout << array[i] << endl;
		cout << *(p++) << endl;
	}
}


void myPrint(int v)
{
	cout << v << endl;
}

void test02()
{
	//Declaring container
	vector<int> v; //Declare a container in which the int type data object name v is stored
	//Add data to container

	v.push_back(10);
	v.push_back(20);
	v.push_back(30);
	v.push_back(40);

	//Traverse data in container
	//Using iterators

	vector<int>::iterator itBegin = v.begin(); // itBegin points to the starting position in the v container

	vector<int>::iterator itEnd = v.end(); //itEnd points to the next address of the last location in the v container

	//while (itBegin != itEnd)
	//{
	//	cout << *itBegin << endl;

	//	itBegin++;
	//}


	//The second way to traverse
	//for (int i = 0; i < 10;i++)
	//for (vector<int>::iterator it = v.begin(); it != v.end();it++)
	//{
	//	cout << *it << endl;
	//}

	//The third way to use the algorithm
	for_each(v.begin(), v.end(), myPrint);


}
//Action custom data type
class Person
{
public:
	Person(string name, int age)
	{
		this->m_Name = name;
		this->m_Age = age;
	}

	string m_Name;
	int m_Age;
};

void test03()
{
	vector<Person> v;
	Person p1("Big head son", 10);
	Person p2("Little daddy", 32);
	Person p3("Uncle Wang next door", 30);
	Person p4("Apron mom", 28);

	v.push_back(p1);
	v.push_back(p2);
	v.push_back(p3);
	v.push_back(p4);

	//ergodic
	for (vector<Person>::iterator it = v.begin(); it != v.end();it++)
	{
		cout << "Full name: " << (*it).m_Name << " Age:" << it->m_Age << endl;
	}
}

//Pointer to hold custom data type
void test04()
{
	vector<Person *> v;
	Person p1("Big head son", 10);
	Person p2("Little daddy", 32);
	Person p3("Uncle Wang next door", 30);
	Person p4("Apron mom", 28);

	v.push_back(&p1);
	v.push_back(&p2);
	v.push_back(&p3);
	v.push_back(&p4);

	for (vector<Person*>::iterator it = v.begin(); it != v.end();it++)
	{
		cout << "Full name:: " << (*it)->m_Name << " Age: " << (*it)->m_Age << endl;
	}

}

//Container nested container
void test05()
{
	vector<vector<int>> v;

	vector<int>v1;
	vector<int>v2;
	vector<int>v3;


	for (int i = 0; i < 5;i++)
	{
		v1.push_back(i);
		v2.push_back(i + 10);
		v3.push_back(i + 100);
	}
	//Put the small container into the large one
	v.push_back(v1);
	v.push_back(v2);
	v.push_back(v3);

	//Traverse all data
	for (vector<vector<int>>::iterator it = v.begin(); it != v.end();it++)
	{
		for (vector<int>::iterator vit = (*it).begin(); vit != (*it).end();vit++)
		{
			cout << *vit << " ";
		}
		cout << endl;
		 
	}

}


int main(){

	//test01();

	//test02();
	//test03();
	//test04();
	test05();
	system("pause");
	return EXIT_SUCCESS;
}

Common containers

string container
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
#include <string>
#include <stdexcept>
/*
string Constructor
string();//Create an empty string, for example: string str;
string(const string& str);//Initializing another string object with one string object
string(const char* s);//Initialize with string s
string(int n, char c);//Initialize with n characters c

3.1.2.2 string Basic assignment operation
string& operator=(const char* s);//char*Type string assigned to current string
string& operator=(const string &s);//Assign string s to the current string
string& operator=(char c);//Character assignment to current string
string& assign(const char *s);//Assign string s to the current string
string& assign(const char *s, int n);//Assign the first n characters of string s to the current string
string& assign(const string &s);//Assign string s to the current string
string& assign(int n, char c);//Assign n characters c to the current string
string& assign(const string &s, int start, int n);//Assign s n characters from start to string

*/

void test01()
{
	string str; //Default structure
	string str2(str); //copy construction
	string str3 = str;

	string str4 = "abcd";
	string str5(10, 'a');

	cout << str4 << endl;
	cout << str5 << endl;

	//Basic assignment
	str = "hello";
	str2 = str4;

	//String & assign (const char * s, int n); / / assign the first n characters of string s to the current string
	str3.assign("abcdef", 4);
	cout << str3 << endl;


	//String & assign (const string & S, int start, int n); / / assign n characters of s from start to string
	string str6;
	str6.assign(str, 1, 3); //Ell? Hel index from 0

	cout << str6 << endl;
}


/*
string Access character operation
char& operator[](int n);//Character fetching by []
char& at(int n);//Get character by at method

*/
void test02()
{
	string s = "hello world";

	for (int i = 0; i < s.size();i++)
	{
		//cout << s[i] << endl;
		cout << s.at(i) << endl;
	}
	//What's the difference between [] and at? [] an exception will be thrown if you directly hang up the at when you cross the boundary

	try
	{
		//cout << s[100] << endl;
		cout << s.at(100) << endl;
	}
	catch (out_of_range & e)
	{
		cout << e.what() << endl;
	}
	catch (...)
	{
		cout << "Cross boundary anomaly" << endl;
	}
}

/*
string Stitching operation
string& operator+=(const string& str);//Overload + = operator
string& operator+=(const char* str);//Overload + = operator
string& operator+=(const char c);//Overload + = operator
string& append(const char *s);//Connect string s to the end of the current string
string& append(const char *s, int n);//Connect the first n characters of string s to the end of the current string
string& append(const string &s);//Same as operator + = ()
string& append(const string &s, int pos, int n);//Connect n characters from pos in string s to the end of the current string
string& append(int n, char c);//Add n characters c at the end of the current string

3.1.2.5 string Find and replace
int find(const string& str, int pos = 0) const; //Find the first occurrence of str, starting from pos
int find(const char* s, int pos = 0) const;  //Find the location where s first appears, starting from pos
int find(const char* s, int pos, int n) const;  //Find the first n characters of s from pos position for the first time
int find(const char c, int pos = 0) const;  //Find the first occurrence of character c
int rfind(const string& str, int pos = npos) const;//Find the last location of str, starting from pos
int rfind(const char* s, int pos = npos) const;//Find the last occurrence of s, starting from pos
int rfind(const char* s, int pos, int n) const;//Find the last position of the first n characters of s from pos
int rfind(const char c, int pos = 0) const; //Find the last occurrence of character c
string& replace(int pos, int n, const string& str); //Replace n characters from pos to str
string& replace(int pos, int n, const char* s); //Replace n characters starting from pos with string s

*/

void test03()
{
	//Splicing
	string s1 = "I";
	string s2 = "Love Beijing";
	s1 += s2;
	cout << s1 << endl;
	s1.append("Tiananmen");

	cout << s1 << endl;

	//find lookup

	string s = "abcdefg";
	int pos = s.find("bcf"); //Cannot find return is - 1
	cout << "pos = " << pos << endl;
	
	int pos2 = s.rfind("bc"); //rfind and find results are the same, and the internal search order is the opposite
	cout << "pos2 = " << pos2 << endl; // 4 2 


	//replace
	string s3 = "hello"; //Replace n characters from pos to str
	s3.replace(1, 3, "1111");
	cout << s3 << endl; // h1111o


}

/*
string Comparison operation
/*
compare The function returns 1 when > and - 1 when < and 0 when = = respectively.
The comparison is case sensitive. When comparing, refer to the dictionary order. The smaller the top is.
A in uppercase is smaller than a in lowercase.

int compare(const string &s) const;//Compare with string s
int compare(const char *s) const;//Compare with string s
*/

void test04()
{
	string s1 = "abc";
	string s2 = "abcd";

	if (s1.compare(s2) == 0)
	{
		cout << "s1 Be equal to s2" << endl;
	}
	else if (s1.compare(s2) == 1)
	{
		cout << "s1 greater than s2" << endl;
	}
	else
	{
		cout << "s1 less than s2" << endl;
	}

}


/*
string Substring
string substr(int pos = 0, int n = npos) const;//Returns a string of n characters starting with pos

*/

void test05()
{
	string s1 = "abcde";

	string s2 = s1.substr(1, 3);
	cout << "s2 = " << s2 << endl;

	//Need to find a right-click user name
	string email = "zhangtao@sina.com";

	int pos = email.find("@");//8 
	cout << "pos " << pos << endl;

	string usrName = email.substr(0, pos);
	cout << "The user name is:" << usrName << endl;
}


/*
string Insert and delete operations
string& insert(int pos, const char* s); //Insert string
string& insert(int pos, const string& str); //Insert string
string& insert(int pos, int n, char c);//Insert n characters c in the specified position
string& erase(int pos, int n = npos);//Delete n characters from Pos

*/

void test06()
{
	string s1 = "hello";
	s1.insert(1, "111");
	cout << s1 << endl; //h111ello

	//Delete 111
	s1.erase(1, 3);
	cout << s1 << endl;

}


/*
string And c-style string conversion
*/

void func(string s)
{
	cout << s << endl;
}

void func2(const char * s)
{
	cout << s << endl;
}

void test07()
{
	string s = "abc";
	//string -> const char *

	const char * p = s.c_str();

	func(p); //const char * implicitly cast to string

	//const char * -> string 

	string s2(p);
	//func2(s2); //string cannot be implicitly converted to char* 
}

void test08()
{
	string s = "abcdefg";
	char& a = s[2];
	char& b = s[3];

	a = '1';
	b = '2';

	cout << s << endl;
	cout << (int*)s.c_str() << endl;

	s = "pppppppppppppp";

	//a = '1';
	//b = '2';

	cout << s << endl;
	cout << (int*)s.c_str() << endl;

}

/*
Write a function that internally changes all lowercase letters in the string to uppercase letters.
*/

void test09()
{
	string s = "abCdEfg";

	for (int i = 0; i < s.size();i++)
	{
		//s[i] = toupper(s[i]);

		//Full variable lowercase
		s[i] = tolower(s[i]);
	}

	cout << s << endl;
}

int main(){

//	test01();

	//test02();

	//test03();

	//test04();

	//test05();

	//test06();

//	test07();

	//test08();

	test09();

	system("pause");
	return EXIT_SUCCESS;
}
Published 45 original articles, won praise 3, visited 991
Private letter follow

Topics: P4 less