💓博主CSDN主页:Am心若依旧💓
⏩专栏分类c++从入门到精通⏪
🚚代码仓库:青酒余成🚚🌹关注我🫵带你学习更多c++
🔝🔝
1.前言
本章重点
本章着重讲解string中一些重要的接口函数:构造函数,析构函数,拷贝构造函数,赋值重载函数,插入,删除,扩容,resize,append等接口。
2. 构造函数和拷贝构造函数
重要接口:
//构造函数
string(); //构造一个空字符串
string(const char* s); //复制s所指的字符序列
string(const char* s, size_t n); //复制s所指字符序列的前n个字符
string(size_t n, char c); //生成n个c字符的字符串
//拷贝构造函数
string(const string& str); //生成str的复制品
string(const string& str, size_t pos, size_t len = npos); //复制str中从字符位置pos开始并跨越len个字符的部分
示例:
void Teststring()
{
string s1; //构造空字符串
string s2("hello string"); //复制"hello string"
string s3("hello string", 3); //复制"hello string"的前3个字符
string s4(10, 's'); //生成10个's'字符的字符串
string s5(s2); //用C格式字符串构造string类对象s5
string s6(s2, 0, 4); //复制s2中从字符位置0开始并跨越4个字符的部分
}
3.string类对象的容量操作
1、使用size函数或length函数获取当前有效字符的个数
size_t size() const;
size_t length() const;
示例:
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s("i am CSDN");
cout << s.size() << endl; //9
cout << s.length() << endl; //9
return 0;
}
2、使用max_size函数获取string对象对多可包含的字符数
size_t max_size() const;
示例:
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s("CSDN");
cout << s.max_size() << endl; //4294967294
return 0;
}
3、使用capacity函数获取当前对象所分配的存储空间的大小
size_t capacity() const;(重点)
示例:
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s("CSDN");
cout << s.capacity() << endl; //15
return 0;
}
注意:这里的capacity是指开辟的空间的大小,例如你有20块钱,但是你只用了5块钱。这里20就可以表示为开辟的空间大小,5表示为你已经用掉的空间大小
4、使用resize改变当前对象的有效字符的个数
void resize (size_t n);
void resize (size_t n, char c);
对上述进行解释:将字符串的长度调整为 n 个字符。
1.如果 n 小于当前字符串长度(已经使用的长度),则当前值将缩短为前 n 个字符,并删除第 n 个字符以外的字符。
2.如果 n 大于当前字符串长度,则通过在末尾插入尽可能多的字符来扩展当前内容,以达到 n 的大小。如果指定了 c,则新元素将初始化为 c ,否则,它们是值初始化字符(空字符)
示例:
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s1("CSDN");
//resize(n)n大于对象当前的size时,将size扩大到n,扩大的字符默认为'\0'
s1.resize(20);
cout << s1 << endl; //CSDN
cout << s1.size() << endl; //20
cout << s1.capacity() << endl; //31
string s2("CSDN");
//resize(n, char)n大于对象当前的size时,将size扩大到n,扩大的字符为char
s2.resize(20, 'x');
cout << s2 << endl; //CSDNxxxxxxxxxxxxxxxx
cout << s2.size() << endl; //20
cout << s2.capacity() << endl; //31
string s3("CSDN");
//resize(n)n小于对象当前的size时,将size缩小到n
s3.resize(2);
cout << s3 << endl; //CS
cout << s3.size() << endl; //2
cout << s3.capacity() << endl; //15
return 0;
}
这里不需要担心是否会超出容量的大小,在resize里面内置了扩容的函数,一旦超过了当前容量会先扩容,然后再进行初始化
5、使用reserve改变当前对象的容量大小
void reserve (size_t n = 0);
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s("CSDN");
cout << s << endl; //CSDN
cout << s.size() << endl; //4
cout << s.capacity() << endl; //15
//reverse(n)当n大于对象当前的capacity时,将当前对象的capacity扩大为n或大于n
s.reserve(20);
cout << s << endl; //CDSN
cout << s.size() << endl; //4
cout << s.capacity() << endl; //31
//reverse(n)当n小于对象当前的capacity时,什么也不做
s.reserve(2);
cout << s << endl; //CDSN
cout << s.size() << endl; //4
cout << s.capacity() << endl; //31
return 0;
}
注意:capacity的含义是不管容量怎么扩大,他都不会影响实际有效的元素个数。 而上面所说的resize是,他会实际影响有效的元素个数。并且如果resize在减少有效元素的个数时,空间的大小即capacity的大小不会发生改变。
6、使用clear删除对象的内容,删除后对象变为空字符串
void clear();
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s("i am a CSDN");
//clear()删除对象的内容,该对象将变为空字符串
s.clear();
cout << s << endl; //空字符串
return 0;
}
ps:clear()只是将string中有效字符清空,不改变底层空间大小。
7、使用empty判断对象是否为空
bool empty() const;
这里只需要比较容量和size的大小即可,有效元素的个数为0时,那就是空。
4. string类对象的访问及遍历操作
1、[ ]+下标来访问元素
char& operator[] (size_t pos); const char& operator[] (size_t pos) const;
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s("string a");
//[]+下标访问对象元素
for (size_t i = 0; i < s.size(); i++)
{
cout << s[i];
}
cout << endl;
return 0;
}
打印出来的是:string a
2、使用范围for访问对象中的元素
需要特别注意的是:若是需要通过范围for修改对象的元素,则用于接收元素的变量e的类型必须是引用类型,否则e只是对象元素的拷贝,对e的修改不会影响到对象的元素。
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s("abcd");
//使用范围for访问对象元素
for (auto e : s)
{
cout << e;
}
cout << endl; //abcd
//使用范围for访问对象元素,并对其进行修改
for (auto& e : s) //需要修改对象的元素,e必须是引用类型
{
e = 'x';
}
cout << s << endl; //xxxx
return 0;
}
3、使用迭代器访问对象中的元素
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s("CSDN");
//使用迭代器访问对象元素
string::iterator it1 = s.begin();
while (it1 != s.end())
{
cout << *it1;
it1++;
}
cout << endl; //CSDN
//使用迭代器访问对象元素,并对其进行修改
string::iterator it2 = s.begin();
while (it2 != s.end())
{
*it2 += 1;
it2++;
}
cout << s << endl; //DTEO
return 0;
}
5.string中与迭代器相关的函数
还不知道什么是迭代器的小伙伴推荐先阅读下面文章:
C++迭代器(STL迭代器)iterator详解-CSDN博客
C++ 迭代器 iterator 详解_c++ iterator-CSDN博客
1、与正向迭代器相关的函数
begin函数:返回一个指向字符串第一个字符的迭代器。
end函数:返回一个指向字符串结束字符的迭代器,即’\0’。
iterator begin();
const_iterator begin() const;
iterator end();
const_iterator end() const;
使用示例:
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s("hello string");
//正向迭代器
string::iterator it = s.begin();
while (it != s.end())
{
cout << *it;
it++;
}
cout << endl; //hello string
return 0;
}
2、与反向迭代器相关的函数
rbegin函数:返回指向字符串最后一个字符的反向迭代器。
rend函数:返回指向字符串第一个字符前面的理论元素的反向迭代器。
reverse_iterator rbegin();
const_reverse_iterator rbegin() const;
reverse_iterator rend();
const_reverse_iterator rend() const;
使用示例:
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s("hello string");
//反向迭代器
string::reverse_iterator rit = s.rbegin();
while (rit != s.rend())
{
cout << *rit;
rit++;
}
cout << endl; //gnirts olleh
return 0;
}
6.string中的getline函数
我们知道,使用>>进行输入操作时,当>>读取到空格便会停止读取,基于此,我们将不能用>>将一串含有空格的字符串读入到string对象中。
例:
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s;
cin >> s; //输入:hello CSDN
cout << s << endl; //输出:hello
return 0;
}
所以为了解决上述问题,引出了getline这个函数接口
接口一:
istream& getline (istream& is, string& str);
getline函数将从is中提取到的字符存储到str中,直到读取到换行符’\n’为止。
示例:
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s;
getline(cin, s); //输入:hello CSDN
cout << s << endl; //输出:hello CSDN
return 0;
}
接口二:
istream& getline (istream& is, string& str, char delim);
getline函数将从is中提取到的字符存储到str中,直到读取到分隔符delim或换行符’\n’为止。
示例:
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s;
getline(cin, s, 'D'); //输入:hello CSDN
cout << s << endl; //输出:hello CS
return 0;
}
7.string中的插入、删除、追加等相关函数
1.push_back进行尾插
void push_back (char c);
2.使用insert进行插入
string& insert (size_t pos, const string& str);string& insert (size_t pos, size_t n, char c) iterator insert (iterator p, char c);
解释:在pos位置插入一个字符串str;在pos位置插入一个n个字符c;在迭代器位置插入字符c
示例:
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s("C"); //C
//insert(pos, str)在pos位置插入字符串str
s.insert(1, "S"); //CS
//insert(pos,n,c)在pos位置插入n个c字符
char c='S';
s.insert(2,3 ,t); //CSSSS
//insert(pos, char)在pos位置插入字符char
s.insert(s.end(), 'N'); //CSDN
cout << s << endl; //CSDN
return 0;
}
3.append相关接口
string& append (const string& str);
string& append (const char* s);
string& append (size_t n, char c);
解释:有一个对象s1后,把str追加到s1后面;把s追加到s1后面;在s1后面追加n个字符c
示例:
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s1("I");
string s2(" like");
//append(string)完成两个string对象的拼接
s1.append(s2); //I like
//append(str)完成string对象和字符串str的拼接
s1.append(" C++"); //I like C++
//append(n, char)将n个字符char拼接到string对象后面
s1.append(3, '!'); //I like C++!!!
cout << s1 << endl; //I like C++!!!
return 0;
}
4.pop_back接口进行尾删
void pop_back();
5.使用erase来进行删除
string& erase (size_t pos = 0, size_t len = npos);
iterator erase (iterator p);
iterator erase (iterator first, iterator last);
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s("I like C++!!!");
//这里面的npos可以把他当成无穷值,不显示给定,就表示从pos开始后面的全部删除
//erase(pos, n)删除pos位置开始的n个字符
s.erase(8, 5); //I like C
//erase(pos)删除pos位置的字符
s.erase(s.end()-1); //I like
//erase(pos1, pos2)删除[pos1pos2)上所有字符
s.erase(s.begin() + 1, s.end()); //I
cout << s << endl; //I
return 0;
}
8.总结
string这个类非常的重要,基本可以说string可以贯穿程序员的始终,你无时无刻不在处理字符串,你也无时无刻不在使用字符串。因此一定要好好的掌握string中的重要接口。
string中的重要接口除了上述常用的以外,还有许多需要特别关注的,各位看官老爷可以自己去看看。链接:string - C++ Reference
find函数接口
operator+=函数接口
c_str函数接口
operator<<和operator>>输入输出运算符重载函数接口
下期预告:string类的模拟实现