Introduction to C + + - Programmer Training Manual Chapter 8 - string class

1. Why learn string class?

1.1 string in C language

In C language, a string is a collection of characters ending with '\ 0'. For ease of operation, the C standard library provides some str series library functions, but these library functions are separated from the string, which is not in line with the idea of OOP, and the underlying space needs to be managed by the user. If you are not careful, you may access beyond the boundary.

2. string in standard library

2.1 string class

1. String is a class representing character sequence
2. The standard string class provides support for such objects. Its interface is similar to that of the standard character container, but it adds a design feature specially used to operate single byte character strings.
3. The string class uses char (that is, as its character type, it uses its default char_traits and allocator type) (for more information about templates, see basic_string).
4. The string class is basic_ An instance of the string template class, which uses char to instantiate basic_ String template class with char_traits and allocator as basic_ The default parameter of string (based on more template information, please refer to basic_string).
5. Note that this class processes bytes independently of the encoding used: if it is used to process sequences of multi byte or variable length characters (such as UTF-8), all members of this class (such as length or size) and its iterators will still operate according to bytes (rather than actually encoded characters).

Summary:

1. string is a string class representing a string
2. The interface of this class is basically the same as that of the conventional container, and some conventional operations specially used to operate string are added.

3. The string at the bottom is actually: basic_ Alias of string template class, typedef basic_string<char, char_ traits, allocator>string;
4. The sequence of multi byte or variable length characters cannot be operated.

When using string class, it must include #include header file and using namespace std;

2.2 description of common interfaces of string class (note that I will only explain the most common interfaces below)

1. Common constructions of string class objects

(constructor) function name function description
string(): construct an empty string class object, that is, an empty string
string(const char* s): use C-string to construct string class objects
string(size_t n, char c) the string class object contains n characters C
String (const string & S): (key) copy constructor

#include<iostream>
#include<string>
using namespace std;
int main()
{
	string s1;					//Construct an empty class object,
	string s2("hello world");   //Construct string class object s2 with C format string
	string s3(s2);				//Default copy structure
	string s4(10, 'x');         // Generate n identical characters
	cout << s1 << endl;
	cout << s2 << endl;
	cout << s3 << endl;
	cout << s4 << endl;
	return 0;
}

 2. Capacity operation of string class object

Function name} function description
size returns the effective character length of the string
Length returns the valid character length of a string
capacity returns the total size of the space
Empty (emphasis) if the detected string is released as an empty string, it returns true, otherwise it returns false
Clear clear valid characters
reserve reserves space for strings**
resize converts the number of valid characters into n, and the extra space is filled with character c

void Teststring()
{
	string s6("hello world");
	cout << s6.size() << endl;
	cout << s6.length()<< endl;
	cout << s6.capacity() << endl;
	cout << s6 << endl;
	// Clear the string in s. note that when clearing, only clear the size to 0 without changing the size of the underlying space
	s6.clear(); 
	cout << s6.size() << endl;
	cout << s6.capacity() << endl;
	// Increase the number of valid characters in s to 10, fill the extra positions with 'a', append and control the number of characters.
	s6.resize(10, 'a');
	cout << s6 << endl;
	cout << s6.size() << endl;
	cout << s6.capacity() << endl;
	// Increase the number of valid characters in s to 15, and fill the extra positions with the default value '\ 0'
	// "aaaaaaaaaa\0\0\0\0\0"
	// Note that the number of valid characters in s has increased to 15
	s6.resize(15);
	cout << s6.size() << endl;
	cout << s6.capacity() << endl;
	cout << s6 << endl;
	// Reduce the number of valid characters in s to 5
	s6.resize(5);
	cout << s6.size() << endl;
	cout << s6.capacity() << endl;
	cout << s6 << endl;
}

be careful:

1. The underlying implementation principles of size() and length() methods are exactly the same. The reason why size() is introduced is to keep the same interface with other containers
Generally, size() is used.
2. clear() just clears the valid characters in the string without changing the size of the underlying space.
3. Both resize (size_t n) and resize(size_t n, char c) change the number of valid characters in the string to N. the difference is that when the number of characters increases: resize(n) fills the extra element space with 0, and resize(size_t n, char c) fills the extra element space with C. Note: when resizing the number of elements, increasing the number of elements may change the size of the underlying capacity
Small. If the number of elements is reduced, the total size of the underlying space remains unchanged.
4. reserve(size_t res_arg=0): reserve space for string without changing the number of valid elements. When the parameter of reserve is less than
When the total size of the underlying space of string is, the reserver will not change the capacity.

3. Access and traversal of string objects

Function name function description
operator []: key: return the character of pos position, and call const string class object
begin+ end: begin gets the iterator of one character + end gets the iterator of the next position of the last character

rbegin + rend: begin gets the iterator of one character + end gets the iterator of the next position of the last character
Scope for: C++11 supports a more concise new traversal method of scope for

void Test2()
{
	string s1("hello Etta");//It can be modified during traversal
	const string s2("hello Jingyun");//It cannot be modified during traversal
	//cout << s1 << endl;
	//cout << s2 << endl;
	for (size_t i = 0; i < s1.size(); i++) //operator [] subscript traversal
	{
		cout << s1[i] <<" ";
	}
	cout << endl;
	//Iterator traverses iterator (forward iterator)
	string::iterator it = s1.begin();//Apply for it, which is equivalent to a pointer pointing to the beginning of the array
	while (it != s1.end())
	{
		cout << *it << " ";
		it++;
	}
	cout << endl;
	//Iterator traverses reverse_ Iterator (reverse iterator)
	string::reverse_iterator rit = s1.rbegin();
	while (rit != s1.rend())
	{
		cout << *rit << " ";//Reverse output
		rit++;
	}
	cout << endl;
	//Range for traversal
	for (auto e : s1)
	{
		cout << e <<" ";
	}
	cout << endl;
}

4. Modification of string object

Function name} function description
push_back insert the character c after the string
append appends a string after the string
operator + = (emphasis) append the string str after the string
c_ Str (emphasis) returns a C format string
Find + NPOs (key): find the character c from the pos position of the string and return the position of the character in the string
rfind: find the character c from the pos position of the string and return the position of the character in the string
substr # in str, start from pos position, intercept n characters, and then return them

void Test3()//Modification of class object
{
		string s1("hello Etta");
		const string s2("hello Jingyun");
		s1.push_back(' ');
		s1.push_back('l');				//Append character
		s1.push_back('o');
		s1.push_back('v');
		s1.push_back('e');
		s1.append(" you");				//Append a string after the string
		s1 += " jingyun" ;				//Append string after string
		cout << s1.c_str() << endl;		//Return C format string
		//1.c_str is a temporary pointer whose content is a string pointing to a character array; 
		//2.c_str returns a constant pointer that is readable and cannot be changed
		//Note: be sure to use strcpy() function to operate method C_ Pointer returned by str() 
		cout << s1 << endl;
		//s1 when calling str(), a temporary string object will be returned. And because it's a temporary object,
		//So it will be destructed after the end of the whole expression.
		//If you need to further operate the string object, assign its value to a string variable before operation
		
		// Get the suffix of file
		string files("string.cpp");
		size_t pos = files.find('.');
		cout << pos << endl;
		string suff(files.substr(pos, files.size() - pos));
		//substr takes the pos position to the end, constructs suff, and assigns the intercepted suffix to suff
		cout << suff << endl;

		size_t epos = files.rfind('.');
		string esuff(files.substr(epos, files.size() - epos));
		cout << esuff << endl;
		// npos is a static member variable in string
		// static const size_t npos = -1;
		
		// Remove the domain name from the url
		  string url("http://www.cplusplus.com/reference/string/string/find/");
		size_t start = url.find("://");
		if (start == string::npos)
		{
			cout << "invalid url" << endl;
			return;
		}
		start += 3;
		size_t end = url.find('/', start);
		string address = url.substr(start, end-start);
		cout << address << endl;
	
		// Remove the protocol prefix of the url
		  size_t pos = url.find("://");
		  url.erase(0, pos + 3);
		  cout << url << endl;

}

be careful:

1. When appending characters at the end of string, s.push_ Back (c) / s.append (1, c) / S + ='c 'are implemented in the same way. Generally, the + = operation of string class has more functions. The + = operation can connect not only a single character, but also a string.
2. When operating on a string, if you can roughly estimate how many characters to put, you can reserve the space through reserve first.

5. string class non member function

Function description
operator + should be used as little as possible, because the return of value transfer leads to low efficiency of deep copy
Operator > > (emphasis) input operator overload
Operator < < (key) output operator overload
getline (emphasis) gets a line of string
Size comparison of relational operators

3. Simulation implementation of string class

Realize the construction, copy construction, overload of assignment operator and destructor of string class

namespace jy
{
class string 
	{
	public:
		string(const char *str = "")//Constructor
		{
			// When constructing a string class object, if the nullptr pointer is passed, it is considered that the program is illegal. Assert here
			if (nullptr == str)
			{
				assert(false);
				return;
			}
			_str = new char[strlen(str) + 1];
			strcpy(_str, str);
		}
		~string()//Destructor
		{
			if (_str)
			{
				delete[] _str;
				_str = nullptr;
			}
		}
	private:
		char* _str;	
	};
};

int main()
{
	jy::string s1("hello Etta");
	jy::string s2(s1);//When we copy the structure, we will find that this program cannot be compiled
    //The actual reason is that after the construction is completed, the destructor releases the same space continuously, which is not allowed by the system
	return 0;
}

Note: the above string class does not explicitly define its copy constructor and assignment operator overload. At this time, the compiler will synthesize the default. When constructing s2 with s1, the compiler will call the default copy constructor. The final problem is that s1 and s2 share the same memory space. When released, the same space is released many times, resulting in program crash. This copy method is called shallow copy.

3.2 shallow copy

Shallow copy: also known as bit copy, the compiler just copies the values in the object. If a resource is managed in an object, it will eventually lead to multiple objects sharing the same resource. When an object is destroyed, the resource will be released. At this time, other objects do not know that the resource has been released and think it is still valid. Therefore, when the resource input operation continues, an access violation will occur. To solve the problem of shallow copy, deep copy is introduced into C + +.

If a class involves resource management, its copy constructor, assignment operator overload and destructor must be explicitly given. Generally, it is provided in the form of deep copy.

public:
    string()
    :_str(new char[1])
        {
        *_str = '\0';
        }

string(const char* str = "\0") Error demonstration
string(const char* str = nullptr) Error demonstration
}

This is a shallow copy, which copies values and has no operation on the space pointed to.

3.3, deep copy

The deep copy is as follows. You need to open the space to assign the value, and release the space after the program runs. Calling the destructor will not release the same space multiple times.

namespace jy
{
class string 
	{
	public:
		string(const char *str = "")//Constructor
		{
			// When constructing a string class object, if the nullptr pointer is passed, it is considered that the program is illegal. Assert here
			if (nullptr == str)
			{
				assert(false);
				return;
			}
			_str = new char[strlen(str) + 1];
			strcpy(_str, str);
			cout << "Constructor" << endl;
		}

		string(const string& s)//copy construction 
			: _str(new char[strlen(s._str) + 1])
		{
			strcpy(_str, s._str);
			cout << "copy construction " << endl;
		}
		//Operator overloading=
		string& operator=(const string& s)
		{
			if (this != &s)
			{
				char* pstr = new char[strlen(s._str) + 1];
				strcpy(pstr, s._str);
				delete[] _str;
				_str = pstr;
			}
			cout << "Assignment operation" << endl;
			return *this;
		}
		~string()//Destructor
		{
			if (_str)
			{
				delete[] _str;
				_str = nullptr;
			}
		}
	private:
		char* _str;	
	};
};

int main()
{
	jy::string s1("hello Etta");
	jy::string s2(s1);
	jy::string s3;
	s3 = s1;
	return 0;
}

Tags: C++

Posted by -Mike- on Mon, 18 Apr 2022 22:45:59 +0930