Table of contents
Earlier we briefly introduced some commonly used member functions of string. Today we will selectively explain the string class. What is not commonly used does not mean that it is useless. We must know that the commonly used ones must be mastered.
string class iterator
iterate over the array
In addition to traversing the array with size(), here I briefly introduce the operation of using an iterator to access each element of the array, which also paves the way for our later learning.
string a("hello world");
string::iterator it = a.begin();
while (it != a.end())
{
cout << *it << " ";
++it;
}
cout << endl;
As an independent type, iterator needs to specify string:: to be parsed into an iterator inside string. The begin and end here are superficially understood as pointers, which probably look like the picture below.
In addition to using this method, we can also use range for, and the bottom layer is an iterator.
reverse traversal
Reverse traversal is implemented by means of reverse iterators, here we use rbegin and rend.
The traversal structure should look like this:
const iterator
As the name implies, const iterators are used to return const objects. When we traverse the array, we can add const because it does not involve changing the object .
void Func(const string& s)
{
string::const_iterator it = s.begin();//只能读不能写
while (it != s.end())
{
cout << *it << " ";
++it;
}
cout << endl;
}
At this time, the name has changed. Note that the const here has an underscore, which is a name and not a keyword. The object that is actually modified by const is not it (the return value of begin)
const forward iterator declaration:
const_iterator begin() const;//修饰this指针
We can also understand it like this:
const int* p;//指向的对象不能改变
The same goes for reverse iterators.
If you find it troublesome, you can use auto to automatically deduce the type:
The type deduced by auto here is the object return type, and here we define an object of const type.
In order to distinguish const from ordinary iterators, the string class adds such functions:
The usage is basically the same, and everyone can use it according to their own specifications.
[ ] Overload
Pay attention to the distinction between const and ordinary objects
The iterator does not seem to be convenient to use [ ] overload directly, but its appearance can solve some very complicated data structures in the future. I hope everyone has a clear understanding of this.
at
The difference from [] is the check for out-of-bounds, the former is assert, the latter is the way of throwing an exception, we can find the exception by catching it.
back&&front
back and front are the first and last elements of the returned string array (excluding \0)
insert
Let's simply write a few insert instances
c-string (3) string& insert (size_t pos, const char* s);
It means to insert a string at position pos (array subscript)
string& insert (size_t pos, size_t n, char c);
It means to insert n characters c at position pos
iterator insert (iterator p, char c);
Iterator insertion:
Under normal circumstances, we do not recommend using insert to insert data. Combined with the knowledge of data structure, we know that inserting needs to move space and increase the complexity. You can check the document when necessary.
erase
The opposite of insert is erase, which deletes elements.
Here we introduce the first two:
Iterator single parameter can delete an element at position pos. If the deletion length len is greater than the length of the array itself, all subsequent elements will be deleted. Likewise, erase is not recommended for frequent use.
replace
replace can replace characters or strings at specified positions, but there are two disadvantages of using replace. The first is that there is not enough space to expand the capacity, and the second is the need to move data. Let's take an example of filling the spaces in a string to see the common usage of replace.
Before that, we need to introduce find to find the position of the space:
size_t find (char c, size_t pos = 0) const;
To traverse string, we can use string::npos (static member) to loop:
It means that if the match fails, -1 (the maximum value of the integer) will be returned
The replace used:
string& replace (size_t pos, size_t len, const char* s);
It means to replace the last len characters at position pos with a string.
Here we use reserve to open up space in advance, avoiding the consumption of expansion, reallocation of space and copying content . Then we use a loop to traverse the string, because the filled content is no longer a space. In order to avoid useless searches, we skip the string directly , which improves the search efficiency.
string s2("i love you more than you will ever know");
size_t num = 0;
for (auto ch : s1)
{
if (ch == ' ')
{
num++;
}
}
//提前开空间,避免扩容
s2.reserve(s2.size() + 2 * num);
size_t i = s2.find(' ');
while (i != string::npos)
{
s2.replace(i, 1, "%20");
i = s2.find(' ',i+3);
}
Output result:
Although it has been carefully processed, the movement of data is still indispensable. Here we briefly introduce the method of exchanging space for time:
string New_s2;
New_s2.reserve(s2.size() + 2 * num);
for (auto ch : s2)
{
if (ch != ' ')
New_s2 += ch;
else
New_s2 += "%20";
}
s2 = New_s2;
cout << New_s2 << endl;
string::swap
Why write the string class field in front? That's because there is also a template-like swap function in std, but the usage is different, so what is the difference between them?
Efficiency comparison:
The swap exchange in string only needs to change the pointing of the pointer to realize the exchange of elements. The swap of class templates involves deep copying , and its implementation logic may be more complicated, which we will talk about later.
c_str
The appearance of this interface is mainly to be compatible with the string returned in C style. What does it mean? Let us illustrate with an example.
It can be seen that there is no difference in the first printing. The second time s3 encounters \0 and does not terminate and continue to output the following content, but c_str ends the printing. In c language, \0 is used as the end mark of char* type , and c_str inherits this feature, records the value of string in the form of constant pointer, and directly uses the string overloaded with cout to output its entire size The size does not need to control whether \0 exists or not.
When we use the c interface to open the string type file name, in order to distinguish the c++ interface, we need to use this c interface.
successfully read content
find
As you can see, find can find constant strings, string types and single characters.
Let's take finding the file suffix as an example to explain
Here we use the substr interface to save the suffix name
The usage is to keep the npos string after the pos position .
Here you can directly use the default npos of substr to directly fetch . and then end the file name.
Think about what to do if there are multiple suffixes and want to take its real suffix (the last suffix)?
In addition to the find interface, string also provides the rfind interface, which means reverse lookup .
rfind
Using the function of npos to look forward from the last one , we can modify the code like this:
string file("test.cpp.zip");
size_t pos = file.rfind('.');
if (pos != string::npos)
{
string sf = file.substr(pos);
cout << sf << endl;
}
Here is a code to find the URL, you can understand it by yourself
string url("http://www.cplusplus.com/reference/string/string/find/");
cout << url << endl;
size_t start = url.find("://");
if (start == string::npos)
{
cout << "invalid url" << endl;
}
else
{
start += 3;
size_t end = url.find('/', start);
string address = url.substr(start,end-start);
cout << address << endl;
}
find_fisrt_of
Note that first here is easily misunderstood as looking for the first string, but actually it will look for any characters or strings that appear . As long as any one of these characters is found , it will return.
The first value of found = is the number of matching strings, where the initial value of found is 3.
find_last_of
Contrary to find_first_of, find_last_of looks backwards. You can look at the official library to understand
In addition, there are the following two interfaces that have the opposite effect on them, let's find out.
operator overloading
In the section on operator overloading, we have simulated and implemented the operators of the date class. I believe everyone is familiar with it. It should be noted that the string class does not have - operator overloading, and there is + overloading , but use it as little as possible (involving copying).
I hope that everyone will have a deeper understanding of string through today's study, and I will write this part of the exercises as a blog and upload them. If you like it, don't forget to click and triple!