前言:各位老铁好,今天分享的知识是STL中的string类,相信每一位学c++的小伙伴都懂得stl的重要性,所以我也就不多说废话了,直接上干货;这篇文章会先分享string类的一些常用接口的使用(如果小伙伴对其他接口使用有兴趣),可以自己查一下文档,在下文我会分享文档链接),懂得的 如何使用string类,那么接下来我又会分享string底层是如何实现的,从而加深我们对string类的理解。
c++文档链接
string容器的定义:string是表示字符串的字符串类,string里面不仅存放字符串也存放着\0(c++11)
string容器接口:
1.首先我们来看看文档中string常用的构造函数。
笔者认为着里面有四个我们比较常用,所以笔者只分享这四个构造函数如何使用。
(1)string() (无参的构造函数,构造空的string对象,即是空的字符串)
string s1();
(2)string(const char* s) (使用字符串来构造string对象)
string s2("hello");
(3)string(size_t n,char c) (使用n个字符来构造string对象)
//表示拷贝10字符a
string s3(10, 'a');
(4)string(const string& str) (使用string对象进行拷贝构造string对象)
string s4("hello");
string s5(s4);
2.我们再来看看string对容量进行操作的接口:
老规矩我们直接看文档。
string表示容量有这么多的接口,笔者会在里面挑出笔者认为比较常用的进行分享如何使用。
(1).size()
我们看文档可以清楚的知道,size返回的是字符串的长度,表示的是字符串实际的大小,不一定和存储容量相等。
文档中也给出例子了,笔者结合文档给出的例子演示一下,看看是否能求出字符串的长度。
(2)length()
length()和size()功能一样,都是求字符串的实际大小,size()和length()都可以使用,笔者推荐使用size(),因为要和其他容器的接口保持一致。
(3)capacity()
我们可以看到,它返回的是已经分配的存储空间的大小,它和实际字符串的大小不一定相等,当它的容量耗尽时,它会自动进行扩容。
它的返回值是为字符串分配的存储空间的大小,是一个无符号整数。
我们再看看它是如何使用的。
// comparing size,capacity
#include <iostream>
#include <string>
int main ()
{
std::string str ("Test string");
std::cout << "length: " << str.size() << "\n";
std::cout << "capacity: " << str.capacity() << "\n";
return 0;
}
(4)empty()
empty()表示判断字符串是否为空,如果字符串长度为0则返回true,否则就会返回false
(5)clear()
clear()表示清空有效字符,无返回值。
(6)reserve()
reserve()表示改变容量的大小,无返回值,当reserve()要开辟空间的大小<string实际的空间,reserve不会改变容量的大小
#include <iostream>
#include <string>
using namespace std;
int main ()
{
//表示增容到指定的大小
//只改变空间的大小,不会改变数据
string s;
cout << s.capacity() << endl;
s.reserve(100);//要开整数倍的空间(会在你要开的空间大小基础上多开一个空间存放\0)
cout << s.capacity() << endl;
return 0;
}
(7)resize()
resize()表示改变字符串的实际大小,如果需要改变的大小n<字符串的实际长度,那么改变后,字符串的实际大小变成了n,多出来的全部删除,如果n>字符串的实际长度,就从>n的位置开始插入字符串,从而达到n的大小,如果指定了需要插入什么字符就会插入什么字符,否则会自动插入\0
#include <iostream>
#include <string>
using namespace std;
int main ()
{
string s;
cout << s.size() << endl;
s.resize(100);
cout << s.size() << endl;
return 0;
}
3.string类型的遍历(三种)
(1).for循环遍历,如果使用for循环遍历,就需要可以任意访问string对象中的任意一个元素,正好stl中提供了operator[ ]重载。
operator[ ]表示pos为下标的位置的字符,如果operator[ ]返回值不是const ,那么表示还可以修改。
string s1("hello");
for (size_t i = 0; i < s1.size(); i++)
{
//写
s1[i] += 1;
s1[i]-=1;
//读
cout << s1[i];
}
cout << endl;
(2).非const迭代器遍历:使用迭代器遍历,我们首先需要知道字符串的首位置和末尾。
begin()表示返回字符串的起始位置
end()表示返回字符串最后一个字符的下一个位置。
string s1("hello");
//9.string迭代器进行遍历(读)
string::iterator it2 = s1.begin();
while (it2 != s1.end())
{
cout << *it2 << " ";
++it2;
}
cout << endl;
//8.string迭代器进行遍历(写)
string s1("hello");
string::iterator it1 = s1.begin();
while (it1 != s1.end())//end表示最后一个字符的下一个位置
{
*it1 -= 1;
cout<<*it1;
++it1;
}
cout << endl;
(2).const迭代器遍历:
const string s1("hello");
//由于s1是const类型的,所以迭代器的返回值也得是const类型
//const迭代器不能修改
string::const_iterator it = s1.begin();
while(it!=s1.end())
{
*it -= 1;//直接就报错了
cout<<*it;
++it;
}
cout<<endl;
const string s1("hello");
//由于s1是const类型的,所以迭代器的返回值也得是const类型
//const迭代器不能修改
string::const_iterator it = s1.begin();
while(it!=s1.end())
{
cout<<*it1;
++it1;
}
cout<<endl;
(3).迭代器的反向遍历:
rbegin()表示以最后一个字符为开头,从而达到反向的效果。
rend()表示以第一个字符为末尾,从而达到反向的效果
string s1("hello world");
//倒着遍历(反向迭代器)
string::reverse_iterator rit = s1.rbegin();
while (rit != s1.rend())
{
cout << *rit << " ";
++rit;
}
cout << endl;
(2).范围for遍历(基于迭代器实现的):
//10.范围for(c++11才支持)
string s1("hello");
for (auto ch : s1)//把s1里面的每个字符依次取出来扔给auto,然后自动++
{
cout << ch << " ";
}
cout << endl;
4.string类对象的修改操作
(1)插入字符
push_back()表示把字符插入到字符串的末尾,从而使字符串的长度+1
string s;
//表示插入一个字符
s.push_back('x');
for (auto ch : s)//把s1里面的每个字符依次取出来扔给auto,然后自动++
{
cout << ch << " ";
}
cout << endl;
cout<<s.size()<<endl;
(2)插入字符串
append()表示在末尾插入字符串(有很多接口就不一 一演示了)。
string s;
s.append("11111");
for (auto ch : s)//把s1里面的每个字符依次取出来扔给auto,然后自动++
{
cout << ch << " ";
}
cout << endl;
cout<<s.size()<<endl;
(3)在任意位置插入字符串
insert()表示在下标为pos位置(pos可以是任意位置)插入字符/字符串。
//头插一个字符
string s;
s.insert(s.begin(), '0');
s.insert(1,"1111");
cout << s << endl;
(4)在字符串末尾追加字符串/字符(比较简单,推荐使用)
operator+=表示在字符串末尾插入字符/字符串,或者是把两个string对象含有的字符串连接起来。
string s;
string s1("hello");
s += 'x';
s += "aaa";
s+=s1;
cout<<s<<endl;
(5)获取和c语言格式一样的字符串的首地址
c_str表示获取指向字符数组首元素的地址,返回指向首地址的指针
//获取字符数组首地址,用C字符串的形式遍历
string s1("hello");
const char* str = s1.c_str();
while (*str)
{
cout << *str << " ";
++str;
}
cout << endl;
(6)在字符串中查找字符
find()表示从pos位置开始查找从pos位置开始到字符串末尾的字符串/字符,找到返回匹配项中的第一个字符的位置,找不到返回npos(npos表示所能保有的最大正值)
npos返回类型是size_t类型,刚好npos值是-1所以对应的是所能保有的最大正值。
(7)生成子字符串
substr()表示从pos位置开始,跨越len字符生成该范围内的子字符串。
string s("hello");
string s1=s.substr(1,2);//表示从下标为1的位置开始,跨越两个字符,从而生成该范围内的子字符串el
cout<<s1;
(7)删除字符串一部分
erase()表示删除字符串的一部分,表示从pos位置开始,跨越len个字符,删除该范围内的字符,无参数时默认删除全部字符,返回该string对象。