一、string 的定义
string有多个构造函数的重载:
cpp
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个字符
cpp
string s1;
string s2("hello world");
string s3("hello world", 3);
string s4(5, 'c');
string s5(s4);
string s6(s2, 0, 4);
二、string插入
1、push_back
void push_back (char c);
cpp
int main() {
string s;
const char* str = "hello world";
for (int i = 0; i < strlen(str); i++) {
s.push_back(str[i]);
}
cout << s << endl; //hello world
return 0;
}
2、insert
string& insert (size_t pos, const string& str);
string& insert (size_t pos, const char* s);
iterator insert (iterator p, char c);
cpp
int main() {
string s;
const char* str = "hello world";
for (int i = 0; i < strlen(str); i++) {
s.insert(s.end(), str[i]);
}
s.insert(0, "A");
s.insert(0, str);
cout << s << endl; //hello worldAhello world
return 0;
}
三、string拼接
append
string& append (const string& str);
string& append (const char* s);
string& append (size_t n, char c);
cpp
int main() {
string s1("hello");
string s2("world");
s1.append(s2);
s1.append(" xyz");
s1.append(3, '!');
cout << s1 << endl; //helloworld xyz!!!
return 0;
}
四、string删除
1、pop_back
void pop_back();
cpp
int main() {
string s;
const char* str = "hello world";
for (int i = 0; i < strlen(str); i++) {
s.push_back(str[i]);
}
cout << s << endl; //hello world
s.pop_back();
cout << s << endl; //hello worl
return 0;
}
2、erase
string& erase (size_t pos = 0, size_t len = npos);
iterator erase (iterator p);
iterator erase (iterator first, iterator last);
cpp
int main() {
string s;
const char* str = "hello world";
for (int i = 0; i < strlen(str); i++) {
s.push_back(str[i]);
}
s.erase(6, 1);
cout << s << endl;//hello orld
s.erase(s.end()-1);
cout << s << endl;//hello orl
s.erase(s.begin(), s.end());
cout << s << endl;//
return 0;
}
五、string查找
1、find
size_t find (const string& str, size_t pos = 0) const;
size_t find (const char* s, size_t pos = 0) const;
size_t find (char c, size_t pos = 0) const;
cpp
int main()
{
string s1("https://blog.csdn.net/m0_72651735?type=blog");
//搜索与对象所匹配的第一个位置
string s2("blog");
size_t pos1 = s1.find(s2);
cout << pos1 << endl; //8
//搜索与字符串所匹配的第一个位置
char str[] = "csdn";
size_t pos2 = s1.find(str);
cout << pos2 << endl; //13
//搜索与字符所匹配的第一个位置
size_t pos3 = s1.find('/');
cout << pos3 << endl; //6
return 0;
}
2、rfind
size_t rfind (const string& str, size_t pos = npos) const;
size_t rfind (const char* s, size_t pos = npos) const;
size_t rfind (char c, size_t pos = npos) const;
cpp
int main()
{
string s1("https://blog.csdn.net/m0_72651735?type=blog");
//搜索与对象所匹配的反向第一个位置
string s2("blog");
size_t pos1 = s1.rfind(s2);
cout << pos1 << endl; //39
//搜索与字符串所匹配的反向第一个位置
char str[] = "csdn";
size_t pos2 = s1.rfind(str);
cout << pos2 << endl; //13
//搜索与字符所匹配的反向第一个位置
size_t pos3 = s1.rfind('/');
cout << pos3 << endl; //21
return 0;
}
六、string比较
int compare (const string& str) const;
int compare (size_t pos, size_t len, const string& str) const;
int compare (size_t pos, size_t len, const string& str, size_t subpos, size_t sublen) const;
1、两个字符串中谁的第一个不匹配的字符值较小,或者所有比较字符都匹配,但比较字符串较短,则返回小于0的值。2、两个字符串中谁的第一个不匹配的字符值较大,或者所有比较字符都匹配,但比较字符串较长,则返回大于0的值。
3、两个字符串相等,则返回0。
cpp
int main()
{
string s1("hello world");
string s2("swean");
cout << s1.compare(s2) << endl; //1
cout << s1.compare(6, 3, s2) << endl; //1
cout << s1.compare(0, 4, s2, 0, 4) << endl; //-1
return 0;
}
七、string替换
replace
string& replace (size_t pos, size_t len, const char* s);
string& replace (size_t pos, size_t len, size_t n, char c);
cpp
int main()
{
string s("hello world");
//replace(pos, len, str)将pos位置开始的len个字符替换为字符串str
s.replace(6, 4, "swean"); //hello sweand
//replace(pos, len, n, char)将pos位置开始的len个字符替换为n个字符char
s.replace(10, 1, 2, '-'); //hello swea--d
cout << s << endl;
return 0;
}
八、string交换
swap
void swap (string& x, string& y);
void swap (string& str);
cpp
int main()
{
string s1("hello world");
string s2("swean");
//类的成员函数swap交换s1和s2
s1.swap(s2);
cout << s1 << endl; //swean
cout << s2 << endl; //hello world
//非成员函数swap交换s1和s2
swap(s1, s2);
cout << s1 << endl; //hello world
cout << s2 << endl; //swean
return 0;
}
九、string大小和容量
1、size / length
size_t size() const;
size_t length() const;
cpp
int main()
{
string s("swean");
cout << s.size() << endl; //5
cout << s.length() << endl; //5
return 0;
}
2、max_size
size_t max_size() const;
cpp
int main()
{
string s;
cout << s.max_size() << endl; //4294967294
return 0;
}
3、capacity
size_t capacity() const;
cpp
int main()
{
string s("swean");
cout << s.capacity() << endl; //15
return 0;
}
4、resize
1、当n大于当前的size时,将size扩大到n,扩大的字符为c,c默认为'\0'。
2、当n小于当前的size时,将size缩小到n。
void resize (size_t n);
void resize (size_t n, char c);
cpp
int main()
{
string s1("swean");
//resize(n)当n大于当前的size时,将size扩大到n,扩大的字符为c,c默认为'\0'。
s1.resize(20);
cout << s1 << endl; //swean
cout << s1.size() << endl; //20
cout << s1.capacity() << endl; //31
string s2("swean");
//resize(n, char)n大于对象当前的size时,将size扩大到n,扩大的字符为char
s2.resize(20, 'x');
cout << s2 << endl; //sweanxxxxxxxxxxxxxxxx
cout << s2.size() << endl; //20
cout << s2.capacity() << endl; //31
string s3("swean");
//resize(n)n小于对象当前的size时,将size缩小到n
s3.resize(2);
cout << s3 << endl; //sw
cout << s3.size() << endl; //2
cout << s3.capacity() << endl; //15
return 0;
}
5、reserve
1、当n大于对象当前的capacity时,将capacity扩大到n或大于n。
2、当n小于对象当前的capacity时,什么也不做。
void reserve (size_t n = 0);
cpp
int main()
{
string s("swean");
cout << s << endl; //swean
cout << s.size() << endl; //5
cout << s.capacity() << endl; //15
//reverse(n)当n大于对象当前的capacity时,将当前对象的capacity扩大为n或大于n
s.reserve(20);
cout << s << endl; //swean
cout << s.size() << endl; //5
cout << s.capacity() << endl; //31
//reverse(n)当n小于对象当前的capacity时,什么也不做
s.reserve(2);
cout << s << endl; //swean
cout << s.size() << endl; //5
cout << s.capacity() << endl; //31
return 0;
}
这里我们可以测试一下在vs2022环境下,capacity的扩容机制是什么样的
cpp
int main() {
string s;
int cp = s.capacity();
cout << "初始capacity:" << cp << endl;
for (int i = 0; i < 200; i++) {
if (s.capacity() != cp) {
cp = s.capacity();
cout << "扩容capacity:" << cp << endl;
}
s.push_back('a');
}
return 0;
}
可以看出差不多是1.5倍,而且还有对齐

6、clear
void clear();
cpp
int main()
{
string s("swean");
s.clear();
cout << s << endl; //空字符串,但是capacity不会改变
return 0;
}
7、empty
bool empty() const;
cpp
int main()
{
string s("swean");
cout << s.empty() << endl; //0
s.clear();
cout << s.empty() << endl; //1
return 0;
}
十、string访问元素
1、 +下标
因为string类对 运算符进行了重载,所以我们可以直接使用 +下标访问对象中的元素。并且该重载使用的是引用返回,所以我们可以通过 +下标修改对应位置的元素。
char& operator\[\] (size_t pos);
const char& operator\[\] (size_t pos) const;
cpp
int main()
{
string s("hello world");
//[]+下标访问对象元素
for (int i = 0; i < s.size(); i++)
{
cout << s[i];
}
cout << endl; //hello world
//[]+下标修改对象元素内容
for (int i = 0; i < s.size(); i++)
{
s[i] += 1;
}
cout << s << endl; //ifmmp!xpsme
return 0;
}
2、at
char& at (size_t pos);
const char& at (size_t pos) const;
cpp
int main()
{
string s("hello world");
//[]+下标访问对象元素
for (int i = 0; i < s.size(); i++)
{
cout << s.at(i);
}
cout << endl; //hello world
//[]+下标修改对象元素内容
for (int i = 0; i < s.size(); i++)
{
s.at(i) = 'x';
}
cout << s << endl; //xxxxxxxxxxx
return 0;
}
3、范围for
cpp
int main()
{
string s("hello world");
//使用范围for访问对象元素
for (auto e : s)
{
cout << e;
}
cout << endl; //hello world
//使用范围for访问对象元素,并对其进行修改
for (auto& e : s) //需要修改对象的元素,e必须是引用类型
{
e += 1;
}
cout << s << endl; //ifmmp!xpsme
return 0;
}
4、iterator
cpp
int main()
{
string s("hello world");
//使用迭代器访问对象元素
string::iterator it1 = s.begin();
while (it1 != s.end())
{
cout << *it1;
it1++;
}
cout << endl;
//使用迭代器访问对象元素,并对其进行修改
string::iterator it2 = s.begin();
while (it2 != s.end())
{
*it2 += 1;
it2++;
}
cout << s << endl;
return 0;
}
十一、string运算符
1、operator=
string类中对=运算符进行了重载,重载后的=运算符支持string类的赋值、字符串的赋值以及字符的赋值。
cpp
int main()
{
string s1;
string s2("hello world");
s1 = s2;
cout << s1 << endl;
s1 = "hello";
cout << s1 << endl; //hello
s1 = 'x';
cout << s1 << endl; //x
return 0;
}
2、operator+=
string类中对+=运算符进行了重载,重载后的+=运算符支持string类的复合赋值、字符串的复合赋值以及字符复合的赋值。
cpp
int main()
{
string s1;
string s2("hello");
s1 += s2;
cout << s1 << endl; //hello
s1 += " world";
cout << s1 << endl; //hello world
s1 += '!';
cout << s1 << endl; //hello world!
return 0;
}
3、operator+
string类中对+运算符进行了重载,重载后的+运算符支持以下几种类型的操作:
string类 + string类、string类 + 字符串、字符串 + string类、string类 + 字符、字符 + string类
它们相加均返回一个string类对象。
cpp
int main()
{
string s;
string s1("swean");
string s2("hello");
char str[] = "world";
char ch = '!';
//string类 + string类
s = s1 + s2;
cout << s << endl; //sweanhello
//string类 + 字符串
s = s1 + str;
cout << s << endl; //sweanworld
//字符串 + string类
s = str + s1;
cout << s << endl; //worldswean
//string类 + 字符
s = s1 + ch;
cout << s << endl; //swean!
//字符 + string类
s = ch + s1;
cout << s << endl; //!swean
return 0;
}
4、operator>> 和 operator<<
istream& operator>> (istream& is, string& str);
ostream& operator<< (ostream& os, const string& str);
cpp
int main()
{
string s;
cin >> s; //输入
cout << s << endl; //输出
return 0;
}
5、关系运算符
string类中还对一系列关系运算符进行了重载,==、!=、<、<=、>、>=。
cpp
int main()
{
string s1("abcd");
string s2("abde");
cout << (s1 > s2) << endl; //0
cout << (s1 < s2) << endl; //1
cout << (s1 == s2) << endl; //0
return 0;
}
十二、string迭代器
1、正向迭代器
begin / end
iterator begin();
const_iterator begin() const;
iterator end();
const_iterator end() const;
cpp
int main()
{
string s("hello world");
//正向迭代器
string::iterator it = s.begin();
while (it != s.end())
{
cout << *it;
it++;
}
cout << endl;
return 0;
}
2、反向迭代器
rbegin / rend
reverse_iterator rbegin();
const_reverse_iterator rbegin() const;
reverse_iterator rend();
const_reverse_iterator rend() const;
cpp
int main()
{
string s("hello world");
//反向迭代器
string::reverse_iterator rit = s.rbegin();
while (rit != s.rend())
{
cout << *rit;
rit++;
}
cout << endl;
return 0;
}
十三、string转换字符串
字符串 ==> string
cpp
int main()
{
string s1("hello world");
char str[] = "hello world";
string s2(str);
cout << s1 << endl; //hello world
cout << s2 << endl; //hello world
return 0;
}
2、c_str / data
const char* c_str() const;
const char* data() const;
- 在C++98中,c_str()返回 const char* 类型,返回的字符串会以空字符结尾。
- 在C++98中,data()返回 const char* 类型,返回的字符串不以空字符结尾。
- C++11版本中,c_str()与data()用法相同。
cpp
int main()
{
string s("hello world");
const char* str1 = s.data();
const char* str2 = s.c_str();
cout << str1 << endl;
cout << str2 << endl;
return 0;
}
十四、string子串提取
substr
string substr (size_t pos = 0, size_t len = npos) const;
cpp
int main()
{
string s1("hello world");
string s2;
//substr(pos, n)提取pos位置开始的n个字符
s2 = s1.substr(2, 4);
cout << s2 << endl;
return 0;
}
这里我们可以实现一个网址分割
cpp
int main() {
string s1("https://blog.csdn.net/m0_72651735?type=blog");
string sub1, sub2, sub3;
int i1 = s1.find(':');
if (i1 != string::npos) {
sub1 = s1.substr(0, i1);
}
else {
cout << "未找到" << endl;
}
int i2 = s1.find('/', i1 + 3);
if (i2 != string::npos) {
sub2 = s1.substr(i1+3, i2-(i1+3));
}
else {
cout << "未找到" << endl;
}
sub3 = s1.substr(i2);
cout << sub1 << endl;
cout << sub2 << endl;
cout << sub3 << endl;
}
copy
size_t copy (char* s, size_t len, size_t pos = 0) const;
cpp
int main()
{
string s("hello world");
char str[20];
//复制pos位置开始的n个字符
size_t length = s.copy(str, 4, 2);
//copy函数不会在复制内容的末尾附加'\0',需要手动加
str[length] = '\0';
cout << str << endl;
return 0;
}
十五、string的getline函数
使用>>时,当>>读取到空格便会停止读取,所以我们不能用>>将一串含有空格的字符串读入到string对象中。
cpp
int main()
{
string s;
cin >> s; //hello world
cout << s << endl; //hello
return 0;
}
这时,getline函数就派上用场了
istream& getline (istream& is, string& str);
istream& getline (istream& is, string& str, char delim);
1.getline函数从is中提取到的字符存储到str中,直到读取到换行符'\n'为止。
cpp
int main()
{
string s;
getline(cin, s); //hello world
cout << s << endl; //hello world
return 0;
}
2.getline函数从is中提取到的字符存储到str中,直到读取到分隔符delim为止。
cpp
int main()
{
string s;
//hello
//world
//swean!
getline(cin, s, '!');
cout << s << endl;
//hello
//world
//swean
return 0;
}