// 欢迎来到 aramae 的博客,愿 Bug 远离,好运常伴! //
时代不会辜负长期主义者,愿每一个努力的人都能达到理想的彼岸。
引言: 我们都知道STL是C++的重要部分,STL(Standard Template Library)与 C++ 的string类密切相关,它们共同构成了 C++ 标准库的核心部分,因此学习string类时会将两者紧密联系起来学习。下面学习string时会和参考 C++ 标准文档(如cppreference.com)和 SGI STL 源码。(下篇讲string的模拟实现)
注意:学习STL不要想着掌握所有函数,只要掌握最常见的就可以了(大概二十几个),剩下的不常用的,有个印象,需要时查文档就行。学习这块最好的方式是阅读文档加自己动手实现一遍。
https://cppreference.com --> C++官网 (较繁琐,查找不便,感兴趣可以看看)
string - C++ Reference -->(盗版网站,查找方便,建议阅读)
注:初步学习STL,不建议阅读 stl源码剖析,等进阶时阅读效果更好
下面就 文档 + 代码 做简单学习理解,最后做一些练习题目
1. 什么是string类?
std::string
是 C++ 标准库提供的字符串类(位于 <string>
头文件),用于安全、高效地处理可变长度的字符序列。
string类的文档介绍:
- 字符串是表示字符序列的类
- 标准的字符串类提供了对此类对象的支持,其接口类似于标准字符容器的接口,但添加了专门用于操作单字节字符字符串的设计特性。
- string类是使用char(即作为它的字符类型,使用它的默认char_traits和分配器类型(关于模板的更多信息,请参阅basic_string)。
- string类是basic_string模板类的一个实例,它使用char来实例化basic_string模板类,并用char_traits 和allocator作为basic_string的默认参数(根于更多的模板信息请参考basic_string)。
- 注意,这个类独立于所使用的编码来处理字节:如果用来处理多字节或变长字符(如UTF-8)的序列,这个类的所有成员(如长度或大小)以及它的迭代器,将仍然按照字节(而不是实际编码的字符)来操作。
- 1. string是表示字符串的字符串类
- 2. 该类的接口与常规容器的接口基本相同,再添加了一些专门用来操作string的常规操作。3. string在底层实际是:basic_string模板类的别名,typedef basic_string<char, char_traits, allocator> string;
- 4. 不能操作多字节或者变长字符的序列。
2. string类的常用接口说明
2.1 string类对象的成员函数
2.11 常见构造函数
构造字符串对象构造一个字符串对象,根据使用的构造函数版本初始化其值:
(1) std :: string();
空字符串构造函数(默认构造函数)构造一个长度为零个字符的空字符串。
(2)std::string (const string& str);
复制构造函数 构造 str 的副本。
(3)std::string (const string& str, size_t pos, size_t len = npos);(了解)
子字符串构造函数 复制从字符位置 pos 开始并跨越 len 字符的 str 部分(或者直到 str 的末尾,如果 str 太短或 len 为 string::npos)。
(4)std::string (const char* s);
从 C 字符串复制由 s 指向的以 null 结尾的字符序列(C 字符串)。
(5)std::string (const char* s, size_t n);(了解)
来自缓冲区 从 s 指向的字符数组中复制前 n 个字符。
(6)std::string (size_t n, char c);
填充构造函数 用字符 c 的 n 个连续副本填充字符串。
示例:
#include <iostream>
#include <string>
#include <vector>
int main() {
// (1) 默认构造函数
std::string s1;
std::cout << "s1: " << s1 << std::endl; // 输出: s1:
// (2) 复制构造函数
std::string s2("hello");
std::string s3(s2);
std::cout << "s3: " << s3 << std::endl; // 输出: s3: hello
// (3) 子字符串构造函数
std::string s4(s2, 1, 3); // 从位置1开始的3个字符
std::cout << "s4: " << s4 << std::endl; // 输出: s4: ell
// (4) 从C字符串构造
const char* cstr = "world";
std::string s5(cstr);
std::cout << "s5: " << s5 << std::endl; // 输出: s5: world
// (5) 从字符序列构造(前n个字符)
std::string s6(cstr, 3); // 取前3个字符
std::cout << "s6: " << s6 << std::endl; // 输出: s6: wor
// (6) 填充构造函数
std::string s7(5, '!'); // 5个连续的'!'
std::cout << "s7: " << s7 << std::endl; // 输出: s7: !!!!!
// (7) 范围构造函数(从迭代器范围)
std::vector<char> chars = {'H', 'e', 'l', 'l', 'o'};
std::string s8(chars.begin(), chars.end());
std::cout << "s8: " << s8 << std::endl; // 输出: s8: Hello
return 0;
}
#include<iostream>
using namespace std;
int main()
{
string s1();//构造空的string对象
string s2("zhang san");//用C格式字符串构造string类对象s2
string s3(s2); // 拷贝构造s3
}
2.12 析构函数(了解)
2.13 std::string::operator=(了解)
2.2 string类的迭代器 (iterator) (补充)
- 迭代器是 C++ 为简化容器访问而设计的抽象工具,提供安全、统一的遍历接口。
- 指针是 C++ 从 C 继承的底层机制,提供直接操作内存的能力,但需手动管理内存安全。
2.21. 迭代器类型
string
类有以下几种迭代器类型:
正向迭代器 (
可读写,用于正向遍历容器(从前往后)。iterator
)常量正向迭代器 (
只读,用于遍历常量容器或禁止修改元素的场景。const_iterator
)反向迭代器 (
可读写,用于反向遍历容器(从后往前)。reverse_iterator
)常量反向迭代器 (
只读,用于反向遍历常量容器const_reverse_iterator
)string::iterator // 用于正向遍历的可变迭代器 string::const_iterator // 用于正向遍历的常量迭代器 string::reverse_iterator // 用于反向遍历的可变迭代器 string::const_reverse_iterator // 用于反向遍历的常量迭代器
2.22. 迭代器的初始化
迭代器可借助
begin()
、end()
、rbegin()
和rend()
函数来初始化:#include <string> #include <iostream> int main() { std::string str = "Hello"; // 正向迭代器 std::string::iterator it = str.begin(); // 指向第一个字符'H' std::string::iterator end = str.end(); // 指向最后一个字符的下一个位置 // 反向迭代器 std::string::reverse_iterator rit = str.rbegin(); // 指向最后一个字符'o' std::string::reverse_iterator rend = str.rend(); // 指向第一个字符的前一个位置 return 0; }
2.23. 利用迭代器遍历字符串
正向遍历
std::string str = "World"; for (std::string::iterator it = str.begin(); it != str.end(); ++it) { std::cout << *it; // 输出: W o r l d }
也能使用常量迭代器来遍历常量字符串
const std::string cstr = "Hello"; for (std::string::const_iterator cit = cstr.begin(); cit != cstr.end(); ++cit) { std::cout << *cit; }
反向遍历
std::string str = "Hello"; for (std::string::reverse_iterator rit = str.rbegin(); rit != str.rend(); ++rit) { std::cout << *rit; // 输出: o l l e H }
2.24. 借助迭代器修改字符串
可变迭代器能够修改字符串中的字符:
std::string str = "hello"; for (std::string::iterator it = str.begin(); it != str.end(); ++it) { *it = std::toupper(*it); // 将字符转换为大写 } std::cout << str; // 输出: HELLO
2.25. C++11 范围 for 循环
C++11 引入的范围 for 循环让代码更为简洁。在底层,它也是通过迭代器来实现的:
std::string str = "Hello"; for (char c : str) { // 对于只读操作,使用const char&更佳 std::cout << c; } // 修改字符 for (char& c : str) { // 必须使用引用才能修改原字符串 c = std::tolower(c); }
2.26. 迭代器的运算
string
类的迭代器支持多种运算符std::string str = "0123456789"; std::string::iterator it = str.begin(); // 访问第5个字符 it += 4; // 移动4步,指向索引4的字符 std::cout << *it; // 输出: 4 // 比较迭代器 if (it < str.end()) { std::cout << "在有效范围内"; }
2.27. 迭代器失效问题
对字符串进行插入或删除操作可能会使迭代器失效,这意味着不能再使用失效的迭代器:
std::string str = "abc"; std::string::iterator it = str.begin(); str.insert(it, 'x'); // 在开头插入'x' // 此时原迭代器it已失效,不能再使用 it = str.begin(); // 重新获取有效迭代器
例:
#include <iostream> #include <vector> int main() { std::vector<int> vec = {1, 2, 3, 4, 5}; // 1. 正向遍历(可修改) std::cout << "正向遍历:"; for (auto it = vec.begin(); it != vec.end(); ++it) { *it *= 2; // 可修改元素 std::cout << *it << " "; // 输出: 2 4 6 8 10 } std::cout << std::endl; // 2. 反向遍历(可修改) std::cout << "反向遍历:"; for (auto rit = vec.rbegin(); rit != vec.rend(); ++rit) { *rit += 1; // 可修改元素 std::cout << *rit << " "; // 输出: 11 9 7 5 3 } std::cout << std::endl; // 3. 常量正向遍历(不可修改) const std::vector<int> cvec = {10, 20, 30}; std::cout << "常量正向遍历:"; for (auto cit = cvec.cbegin(); cit != cvec.cend(); ++cit) { // *cit = 100; // 错误:不能修改常量迭代器指向的元素 std::cout << *cit << " "; // 输出: 10 20 30 } std::cout << std::endl; // 4. 常量反向遍历(不可修改) std::cout << "常量反向遍历:"; for (auto crit = cvec.crbegin(); crit != cvec.crend(); ++crit) { std::cout << *crit << " "; // 输出: 30 20 10 } std::cout << std::endl; return 0; }
2.3 string类对象的访问及遍历操作
在 C++ 中,遍历字符串或容器除了使用迭代器,还有其他多种写法,具体取决于你的需求和代码风格。以下是几种常见的替代方法:
2.31. 基于范围的 for 循环(Range-based for loop)
最简洁的写法,适用于 C++11 及以后的版本:
#include <iostream>
#include <string>
int main() {
std::string s1 = "Hello";
// 自动遍历每个字符,c是字符的拷贝
for (char c : s1) {
std::cout << c << std::endl;
}
// 如果需要修改字符,使用引用(&)
for (char& c : s1) {
c = std::toupper(c); // 将字符转为大写
}
return 0;
}
2.32. 传统的下标遍历
通过索引访问字符,适用于所有 C++ 版本:
#include <iostream>
#include <string>
int main() {
std::string s1 = "Hello";
// 使用size_t避免整数溢出,i < s1.size()确保不会越界
for (size_t i = 0; i < s1.size(); ++i) {
std::cout << s1[i] << std::endl;
}
return 0;
}
2.33. 反向迭代器(Reverse Iterator)
从后向前遍历,使用
rbegin()
和rend()
:
#include <iostream>
#include <string>
int main() {
std::string s1 = "Hello";
// 反向迭代器,输出 "olleH"
for (auto it = s1.rbegin(); it != s1.rend(); ++it) {
std::cout << *it << std::endl;
}
return 0;
}
2.34. 常量迭代器(Const Iterator)
用于只读访问,防止修改字符串内容:
#include <iostream>
#include <string>
int main() {
const std::string s1 = "Hello";
// 使用const_iterator,禁止修改字符
for (std::string::const_iterator it = s1.begin(); it != s1.end(); ++it) {
std::cout << *it << std::endl;
// *it = 'X'; // 错误:不能修改常量迭代器指向的内容
}
// 或者使用auto自动推导类型
for (auto it = s1.cbegin(); it != s1.cend(); ++it) {
std::cout << *it << std::endl;
}
return 0;
}
2.35. 使用 STL 算法(如
std::for_each
)结合 lambda 表达式,适用于更复杂的操作:
#include <iostream>
#include <string>
#include <algorithm>
int main() {
std::string s1 = "Hello";
// 对每个字符执行lambda函数
std::for_each(s1.begin(), s1.end(), [](char c) {
std::cout << c << std::endl;
});
return 0;
}
2.36. 手动管理迭代器(不推荐,易出错)
直接操作迭代器指针,需要手动控制迭代过程:
#include <iostream>
#include <string>
int main() {
std::string s1 = "Hello";
auto it = s1.begin();
while (it != s1.end()) {
std::cout << *it << std::endl;
it += 2; // 跳步遍历(输出'H', 'l', 'o')
}
return 0;
}
选择建议:
- 优先使用基于范围的 for 循环:代码最简洁,不易出错。
- 需要索引时使用下标遍历:例如需要同时访问相邻元素。
- 反向遍历时使用反向迭代器:避免手动计算索引。
- 只读访问使用常量迭代器:提高代码安全性。
- 复杂操作使用 STL 算法:例如查找、转换等。
汇总:
#include<iostream>
#include<string>
#include <algorithm>
using namespace std;
int main()
{
string s1("hello aramae");
//正向迭代器
//方法一:
string::iterator it = s1.begin();
while (it != s1.end())
{
cout << *it << " ";
++it;
}
cout << endl;
//方法二:
for (auto i = s1.begin(); i < s1.end(); ++i)
{
cout << *i << " ";
}
cout << endl;
/*反向迭代器(Reverse Iterator)
从后向前遍历,使用rbegin()和rend():*/
//方法一:
string::reverse_iterator rit = s1.rbegin();
while (rit != s1.rend())
{
cout << *rit << " ";
++rit;
}
cout << endl;
//方法二:
for (auto rit = s1.rbegin(); rit < s1.rend(); ++rit)
{
cout << *rit << " ";
}
cout << endl;
return 0;
//基于范围的 for 循环(Range-based for loop)
//最简洁的写法,适用于 C++11 及以后的版本:
/*for (auto&a1 : s1)
{
cout << a1+1 << " ";
}
cout << endl*/;
for (char a1 : s1)
{
cout << a1 << " ";
}
cout << endl;
//如果需要改变s1
for (char& a2 : s1)
{
cout << a2 + 1 << " ";
}
cout << endl;
/*传统的下标遍历
通过索引访问字符,适用于所有 C++ 版本:*/
for (size_t i = 0; i < s1.size(); ++i)
{
cout << s1[i] << " ";
}
cout << endl;
//常量迭代器:
// 使用const_iterator,禁止修改字符
for (string::const_iterator it = s1.begin(); it != s1.end(); ++it) {
cout << *it << endl;
// *it = 'X'; // 错误:不能修改常量迭代器指向的内容
}
// 或者使用auto自动推导类型
for (auto it = s1.cbegin(); it != s1.cend(); ++it) {
std::cout << *it << std::endl;
}
/*使用 STL 算法(如std::for_each)
结合 lambda 表达式,适用于更复杂的操作*/
// 对每个字符执行lambda函数
std::for_each(s1.begin(), s1.end(), [](char c) {
std::cout << c << std::endl;
});
//最推荐:
for (auto& c : s1)
{
cout << c << " ";
}
}
2.4 string类对象的容量操作
(1)std::string::size
返回字符串的当前长度(即字符数量)
#include <iostream> #include <string> int main() { std::string s = "hello"; std::cout << "Size: " << s.size(); // 输出: 5 }
(2) std::string::length
与
size()
完全等价,返回字符串的当前长度
#include <iostream> #include <string> int main() { std::string s = "world"; std::cout << "Length: " << s.length(); // 输出: 5 }
(3)std::string::resize
整字符串长度,可能截断或填充新字符
#include <iostream> #include <string> int main() { std::string s = "hello"; // 截断字符串 s.resize(3); std::cout << s << "\n"; // 输出: hel // 扩展字符串,用 'x' 填充 s.resize(5, 'x'); std::cout << s << "\n"; // 输出: helxx // 扩展字符串,默认用 '\0' 填充 s.resize(7); std::cout << "Size: " << s.size(); // 输出: 7 std::cout << "Content: " << s; // 输出: helxx(后面的 '\0' 不可见) }
(4)std::string::capacity
返回当前分配的内存可容纳的字符数(不重新分配内存的情况下)
#include <iostream> #include <string> int main() { std::string s = "hello"; std::cout << "Size: " << s.size(); // 输出: 5 std::cout << "Capacity: " << s.capacity(); // 输出: 至少5(具体值取决于实现) // 添加字符可能触发内存重新分配 s += " world"; std::cout << "New Capacity: " << s.capacity(); // 输出: 通常大于11(动态扩展) }
(5)std::string::reserve
避免频繁重新分配
#include <iostream> #include <string> int main() { std::string s; s.reserve(100); // 预先分配100个字符的空间 std::cout << "Size: " << s.size(); // 输出: 0 std::cout << "Capacity: " << s.capacity(); // 输出: 至少100 s = "hello"; std::cout << "New Capacity: " << s.capacity(); // 输出: 至少100(保持不变) }
( 6)std::string::clear
清空字符串内容,但不释放内存(容量不变)
#include <iostream> #include <string> int main() { std::string s = "hello"; s.reserve(100); std::cout << "Before clear - Size: " << s.size(); // 输出: 5 std::cout << "Before clear - Capacity: " << s.capacity(); // 输出: 100 s.clear(); std::cout << "After clear - Size: " << s.size(); // 输出: 0 std::cout << "After clear - Capacity: " << s.capacity(); // 输出: 100(容量不变) }
(7)std::string::empty
检查字符串是否为空(即长度是否为 0)
#include <iostream> #include <string> int main() { std::string s1 = ""; std::string s2 = "hello"; std::cout << std::boolalpha; // 输出 true/false 而非 1/0 std::cout << "s1 empty: " << s1.empty(); // 输出: true std::cout << "s2 empty: " << s2.empty(); // 输出: false }
int main()
{
string s0("hello aramae!");
cout << "size:" << s0.size() << endl;
cout << "length:" << s0.length() << endl;
s0.resize(5);
cout << s0 << endl;
s0.resize(13, 'x');
cout << s0 << endl;
s0.resize(20);
cout << s0.size() << endl;
cout << s0 << endl;
cout << "size:" << s0.size() << endl;
cout << "capacity:" << s0.capacity() << endl;
string s1;
s1.reserve(100);
cout << "size:" << s1.size() << endl; //size: 0
cout << "capacity:" << s1.capacity() << endl;//capacity : 111
string s2="hello";
cout << "new capacity:" << s1.capacity() << endl;//new capacity: 111
s2.clear();
cout << "size:" << s1.size() << endl;
cout << "capzcity:" << s1.capacity() << endl; //capacity : 111
string s3 = "";
string s4 = "hello";
cout << std::boolalpha; // 输出 true/false 而非 1/0
cout << "s3 empty: " << s3.empty()<<endl; // 输出: true
cout << "s4 empty: " << s4.empty()<<endl; // 输出: false
return 0;
}
- 1. size()与length()方法底层实现原理完全相同,引入size()的原因是为了与其他容器的接口保持一 致,一般情况下基本都是用size()。
- 2. clear()只是将string中有效字符清空,不改变底层空间大小。
- 3. resize(size_t n) 与 resize(size_t n, char c)都是将字符串中有效字符个数改变到n个,不同的是当字 符个数增多时:resize(n)用0来填充多出的元素空间,resize(size_t n, char c)用字符c来填充多出的 元素空间。注意:resize在改变元素个数时,如果是将元素个数增多,可能会改变底层容量的大小,如果是将元素个数减少,底层空间总大小不变。
- 4. reserve(size_t res_arg=0):为string预留空间,不改变有效元素个数,当reserve的参数小于 string的底层空间总大小时,reserver不会改变容量大小。
2.5 string类对象的修改操作
(这里只讲部分常用的,剩下的需要时查文档即可)
(1)std::string::operator+=
这个函数用于在字符串末尾添加字符或者字符串。
#include <iostream> #include <string> int main() { std::string str = "Hello"; str += " World"; // 添加字符串 str += '!'; // 添加单个字符 std::cout << str; // 输出:Hello World! return 0; }
(2)std::string::append
该函数能够把字符串、字符串的子串或者字符数组添加到当前字符串的末尾
#include <iostream> #include <string> int main() { std::string str = "Hello"; str.append(" World"); // 添加字符串 str.append("!!!", 2); // 添加"!!!"的前2个字符 std::cout << str; // 输出:Hello World!! return 0; }
(3)std::string::push_back
此函数的作用是在字符串末尾添加一个字符,和
operator +=
添加单个字符的功能类似#include <iostream> #include <string> int main() { std::string str = "ABC"; str.push_back('D'); std::cout << str; // 输出:ABCD return 0; }
(4)std::string::c_str
该函数会返回一个指向以
\0
结尾的 C 风格字符串的指针,其内容和当前std::string
相同,主要用于和 C 语言的 API 进行交互#include <iostream> #include <string> #include <cstdio> int main() { std::string str = "Hello"; const char* cstr = str.c_str(); std::printf("C-style string: %s\n", cstr); return 0; }
(5)std::string::find
这个函数用于在字符串中查找子串或者字符首次出现的位置,如果找到了就返回其索引,没找到则返回
std::string::npos
#include <iostream> #include <string> int main() { std::string str = "Hello World"; size_t pos = str.find("World"); if (pos != std::string::npos) { std::cout << "Found at position: " << pos; // 输出:Found at position: 6 } return 0; }
(6)std::string::rfind
rfind
与find
类似,不过它是从字符串末尾开始向前查找子串或者字符首次出现的位置(也就是从后往前找第一个出现的位置)#include <iostream> #include <string> int main() { std::string str = "Hello World"; size_t pos = str.rfind("l"); if (pos != std::string::npos) { std::cout << "Last 'l' at position: " << pos; // 输出:Last 'l' at position: 9 } return 0; }
(7)std::string::substr
该函数用于从当前字符串中提取子串,它有两个参数,第一个参数是起始位置,第二个参数是子串的长度(如果省略第二个参数,则会提取从起始位置到字符串末尾的所有字符
#include <iostream> #include <string> int main() { std::string str = "Hello World"; std::string sub = str.substr(6, 5); // 从位置6开始,提取5个字符 std::cout << sub; // 输出:World return 0; }
使用这些函数时要留意边界条件,比如find和rfind在未找到目标时会返回std::string::npos,substr的起始位置不能超出字符串的长度等
汇总:
int main()
{
string str("hello ");
str += "aramae";
str += "!";
cout << str << endl;
string str1 = "hi";
str1.append(" aramae");
cout << str1 << endl;
str1.append("!!!!", 3);
cout << str1 << endl;
string str2("ABC");
str2.push_back('D');
cout << str2 << endl;
string str3("Hello world");
size_t pos = str.find("world");
if (pos != string::npos) {
std::cout << "Found at position: " << pos; // 输出:Found at position: 6
}
string sub = str3.substr(6, 5); // 从位置6开始,提取5个字符
cout << sub;
return 0;
}
2.6 string类非成员函数
(1)std::string::operator+
这个运算符的作用是连接两个字符串,或者把字符串和字符连接起来,连接完成后会返回一个新的字符串对象
#include <iostream> #include <string> int main() { std::string str1 = "Hello"; std::string str2 = " World"; std::string result = str1 + str2; // 连接两个字符串 result = result + '!'; // 连接字符串和字符 std::cout << result; // 输出:Hello World! return 0; }
(2)std::string::operator>>
该运算符是输入流运算符,它会从输入流(像std::cin)里读取内容,直到遇到空白字符(例如空格、制表符、换行符等)为止,然后把读取到的内容存储到字符串中
#include <iostream> #include <string> int main() { std::string name; std::cout << "Enter your name: "; std::cin >> name; // 输入"John Doe",只会读取"John" std::cout << "Hello, " << name; // 输出:Hello, John return 0; }
(3)std::string::operator<<
此运算符是输出流运算符,它的功能是把字符串的内容输出到输出流(例如
std::cout
)中#include <iostream> #include <string> int main() { std::string message = "Hello, C++!"; std::cout << message; // 输出:Hello, C++! return 0; }
(4)std::string::getline
这是一个独立的函数(并非std::string的成员函数),它能够从输入流中读取一整行内容,直到遇到换行符为止,并且会把读取到的内容存储到字符串中
#include <iostream> #include <string> int main() { std::string address; std::cout << "Enter your address: "; std::getline(std::cin, address); // 可以读取包含空格的整行内容 std::cout << "Your address: " << address; return 0; }
(5) std::string::relational operators
std::string
重载了一系列关系运算符,包括==
、!=
、<
、<=
、>
、>=
。这些运算符可以按照字典序对两个字符串进行比较#include <iostream> #include <string> int main() { std::string str1 = "apple"; std::string str2 = "banana"; if (str1 < str2) { std::cout << str1 << " comes before " << str2; // 输出:apple comes before banana } if (str1 != str2) { std::cout << "\nThey are not equal"; // 输出:They are not equal } return 0; }
汇总:
int main()
{
string str1 = "Hello";
string str2 = " World";
string result = str1 + str2; // 连接两个字符串
result = result + '!'; // 连接字符串和字符
cout << result<<endl;
string name;
cout << "Enter your name: ";
cin >> name; // 输入"Aramae Doe",只会读取"John"
cout << "Hello, " << name; // 输出:Hello, Aramae
string address;
cout << "Enter your address: ";
getline(std::cin, address); // 可以读取包含空格的整行内容
cout << "Your address: " << address;
string str1 = "apple";
string str2 = "banana";
if (str1 < str2) {
std::cout << str1 << " comes before " << str2; // 输出:apple comes before banana
}
if (str1 != str2) {
std::cout << "\nThey are not equal"; // 输出:They are not equal
}
return 0;
}
上面的几个接口大家了解一下,下面的OJ题目中会有一些体现他们的使用。string类中还有一些其他的 操作,这里不一一列举,大家在需要用到时不明白了查文档即可
2.7 . vs和g++下string结构的说明
2.71 vs下string的结构
- 当字符串长度小于16时,使用内部固定的字符数组来存放
- 当字符串长度大于等于16时,从堆上开辟空间
union _Bxty
{ // storage for small buffer or pointer to larger one
value_type _Buf[_BUF_SIZE];
pointer _Ptr;
char _Alias[_BUF_SIZE]; // to permit aliasing
} _Bx;

2.72 g++下string的结构
- 空间总大小
- 字符串有效长度
- 引用计数
struct _Rep_base
{
size_type _M_length;
size_type _M_capacity;
_Atomic_word _M_refcount;
};
- 指向堆空间的指针,用来存储字符串。
结语:感谢相遇
/// 高山仰止,景行行止。虽不能至,心向往之 ///