string
string简单点理解就是C++在库中帮我们定义好的类,我们只需要学会用就好了。
string在C++ 标准库中用于处理字符串。相对于 C 语言中的 C 风格字符串(以
'\0'
结尾的字符数组),std::string
提供了更多的功能,并且更安全、易用。一个对于string类和类中操作函数的介绍的网站:cplusplus.com/reference/string/string/
里面对string操作函数都有详细的介绍
1.string的特点
- 自动管理内存:
std::string
自动处理字符串的内存分配和释放,避免了手动管理内存时可能出现的错误,如缓冲区溢出或内存泄漏。(不用担心扩容问题,底层会自动扩容不需要在C语言中一样用realloc()扩容) - 面向对象的设计:作为一个类,
std::string
提供了丰富的成员函数,支持常见的字符串操作,如连接、查找、替换等。 - 支持迭代器:可以使用迭代器遍历字符串的每个字符,就像遍历容器一样。下面会逐渐介绍。
- 与 C 风格字符串兼容:
std::string
可以很容易地与 C 风格字符串相互转换。
2.创建和初始化
使用string类,首先就是要把string类创建出来,也就是实例化出来才能继续玩。
实例化string对象需要先看看sting提供的构造函数:
看上图,库中string的构造函数提供了很多种重载,也就是说支持多种方式来实例化string对象,下面看代码看看具体的常用用法:(非常简单且好用)
#include <string> // 包含 std::string 类
//因为没有using namespace std;所以函数种都用std::string
void main()
{
// 1. 默认构造 (default)
std::string str1;
std::cout << "1. str1 (default): \"" << str1 << "\"" << std::endl;
// 2. 拷贝构造 (copy)
std::string str2("Hello, World!"); // 用于后续的拷贝构造
std::string str3(str2);
std::cout << "2. str3 (copy of str2): \"" << str3 << "\"" << std::endl;
// 3. 子字符串构造 (substring)
std::string str4(str2, 7, 5); // 从 str2 的第 7 个字符开始,取 5 个字符
std::cout << "3. str4 (substring of str2): \"" << str4 << "\"" << std::endl;
// 4. 从 C 字符串构造 (from c-string)
const char* c_str = "Hello, C-string!";
std::string str5(c_str);
std::cout << "4. str5 (from C-string): \"" << str5 << "\"" << std::endl;
// 5. 从 C 字符串的前 n 个字符构造 (from sequence)
std::string str6(c_str, 5); // 只取 C 字符串的前 5 个字符
std::cout << "5. str6 (first 5 characters of C-string): \"" << str6 << "\"" << std::endl;
// 6. 重复字符构造 (fill)
std::string str7(10, 'x'); // 构造一个包含 10 个 'x' 的字符串
std::cout << "6. str7 (10 'x' characters): \"" << str7 << "\"" << std::endl;
// 7. 范围构造 (range)(使用迭代器)
std::vector<char> vec = {'R', 'a', 'n', 'g', 'e'};
std::string str8(vec.begin(), vec.end());
std::cout << "7. str8 (from range): \"" << str8 << "\"" << std::endl;
}
运行程序后,你将看到如下输出:
1. str1 (default): ""
2. str3 (copy of str2): "Hello, World!"
3. str4 (substring of str2): "World"
4. str5 (from C-string): "Hello, C-string!"
5. str6 (first 5 characters of C-string): "Hello"
6. str7 (10 'x' characters): "xxxxxxxxxx"
7. str8 (from range): "Range"
其中比较常用的还是 默认构造,拷贝构造,直接用字符串构造(代码中:4),迭代器暂时看不懂没关系下面会继续介绍。
3.常规操作
对象实例化出来之后就可以玩了,下面介绍一下string中的操作函数,先看看最最最常用的,也最好用的:
std::string在库中重载了 = 、+ 、[ ] 、+= 、>> 、<< 几种运算符
因为string底层是用顺序表实现的,可以把str[0]的用法看成数组,可以用下标去访问/修改 对象(数组)中元素。
下面看看他们的用法 :
// 文件名:string_operators_example.cpp
#include <iostream> // 标准输入输出流
#include <string> // std::string 类
int main() {
// 1. = 赋值运算符
std::string str1 = "Hello";
std::string str2;
str2 = "World" // str2 赋值成 "world"(展示=用法 此行代码无意义)
str2 = str1; // str2 现在也是 "Hello"
std::cout << "1. str2 (after assignment): " << str2 << std::endl;//打印str2
// 2. + 字符串连接运算符
std::string str3 = str1 + ", World!"; // str3是 "Hello, World!"
std::cout << "2. str3 (after concatenation): " << str3 << std::endl;
// 3. [] 下标运算符
char ch = str3[7]; // str3是 "Hello, World!" 读取下标为7字符'W'
std::cout << "3. Character at index 7 in str3: " << ch << std::endl;
str3[7] = 'w'; // 修改字符大写'W'改小小'w'
std::cout << " str3 (after modification): " << str3 << std::endl;
// 4. += 追加运算符
std::string str4 = "C++";
str4 += " is"; //str4现在是"C++ is"
str4 += " fun!"; //str4现在是"C++ is fun!"
std::cout << "4. str4 (after += operation): " << str4 << std::endl;
//流插入和流提取都是支持可以把string实例化出来的对象当作是内置类型变量来打印或读取
//用法也简单,和平时打印char类型的用法一样
// 5. >> 输入流运算符
std::string inputStr;
std::cout << "5. Enter a word: ";
std::cin >> inputStr;
std::cout << " You entered: " << inputStr << std::endl;
// 6. << 输出流运算符
std::string str5 = "Goodbye!";
std::cout << "6. str5: " << str5 << std::endl;
return 0;
}
代码输出:
1. str2 (after assignment): Hello
2. str3 (after concatenation): Hello, World!
3. Character at index 7 in str3: W
str3 (after modification): Hello, world!
4. str4 (after += operation): C++ is fun!
5. Enter a word: example
You entered: example
6. str5: Goodbye!
4. string进阶使用
这里仅演示比较常用的string函数,并不是所有string的成员函数!!如果需要了解更多函数的详细用法可以在此篇章开始位置去网站中查看
string常用成员函数:
find
: 查找子串首次出现的位置。substr
: 提取子字符串。replace
: 替换字符串中的某些部分。insert
: 在指定位置插入字符串。erase
: 删除字符串中的某些部分。size
/length
: 获取字符串长度。compare
: 比较两个字符串。append/push_back
: 在字符串末尾追加内容。
#include <iostream>
#include <string> // std::string 类
int main() {
std::string str = "Hello, C++ World!";
// 1. 查找子串首次出现的位置
size_t pos = str.find("C++");
if (pos != std::string::npos) //如果找到就打印 ,==npos就是找不到下面会说明
{
std::cout << "1. 'C++' found at position: " << pos << std::endl;
}
else {
std::cout << "1. 'C++' not found." << std::endl;
}
// 2. 提取子字符串
std::string sub = str.substr(pos, 3); // 从位置 pos 开始,提取 3 个字符
std::cout << "2. Substring extracted: " << sub << std::endl;
// 3. 替换字符串中的某些部分
str.replace(pos, 3, "Java"); // 用 "Java" 替换 "C++"
std::cout << "3. String after replace: " << str << std::endl;
// 4. 在指定位置插入字符串
str.insert(7, "beautiful "); // 在位置 7 插入 "beautiful "
std::cout << "4. String after insert: " << str << std::endl;
// 5. 删除字符串中的某些部分
str.erase(7, 10); // 从位置 7 开始,删除 10 个字符
std::cout << "5. String after erase: " << str << std::endl;
// 6. 获取字符串长度
std::cout << "6. String length: " << str.size() << std::endl;
// 7. 比较两个字符串
std::string str2 = "Hello, World!";
int result = str.compare(str2); //此函数的功能和C语言的strcmp()一样,但用法有差异
if (result == 0) {
std::cout << "7. str is equal to str2" << std::endl;
}
else if (result < 0)
{
std::cout << "7. str is less than str2" << std::endl;
}
else
{
std::cout << "7. str is greater than str2" << std::endl;
}
// 8. 在字符串末尾追加内容
str.append(" Welcome!"); //此函数实现得有些冗余,其实+=和这个函数实现的效果完全一样(个人更喜欢用+= 简单)
std::cout << "8. String after append: " << str << std::endl;
return 0;
}
运行结果:
1. 'C++' found at position: 7
2. Substring extracted: C++
3. String after replace: Hello, Java World!
4. String after insert: Hello, beautiful Java World!
5. String after erase: Hello, Java World!
6. String length: 17
7. str is greater than str2
8. String after append: Hello, Java World! Welcome!
npos说明:
npos是std::string类中定义的一个静态常量,其类型为
size_t,
表示为一个非常大的无符号整数(通常是size_t
的最大值,即-1
)。在32位系统中,size_t
是unsigned int,-1
会在二进制中表示为全1
,即0xFFFFFFFF,
对应的十进制值就是4294967295。
在代码中如果返回了npos,那就是找不到
代码说明:
find
: 查找子串"C++"
首次出现的位置。如果找到,返回下标;如果没找到,返回std::string::npos
。substr
: 从字符串中截取子串,指定开始位置和长度。replace
: 替换字符串中的某一部分。这里是将"C++"
替换为"Java"
。insert
: 在指定位置插入字符串。例子中在位置7
插入"beautiful "
。erase
: 从指定位置开始删除一定长度的字符。这里从位置7
开始删除10
个字符。size
/length
: 获取字符串的长度。(用size比较多,因为往后学习的容器都用size())compare
: 比较两个字符串,返回值为0
表示相等,小于0
表示小于,大于0
表示大于。append/push_back
: 在字符串末尾追加内容。append()是追加字符串,push_back()是追加单字符(都可用 += 替代)
5.string的迭代器
迭代器:在 C++ 中,迭代器是一种类似于指针的对象,用于遍历容器中的元素。
迭代器的功能:
- 遍历:可以从字符串的开头到结尾依次访问每个字符。
- 修改:通过迭代器可以直接修改字符串中的字符。
- 比较:迭代器可以比较是否指向同一个元素,通过
==
和!=
运算符进行比较。 - 算术运算:可以对迭代器使用递增(
++
)和递减(--
)操作,以移动到下一个或前一个字符。
(string的迭代器在底层就是指针,就当string是字符串数组,迭代器是指向数组中元素的指针)
具体用法: (在代码中怎么写 用迭代器)
#include <iostream>
#include <string>
Using namespace std::string;
int main()
{
string str = "Hello, C++ World!";
// 使用普通迭代器遍历字符串
string::iterator it = str.begin()//it的类型是string::iterator ,
//str.begin()函数拿到str数组首元素地址
for (; it != str.end(); ++it) //str.end()函数拿到str数组最末元素地址
{
cout << *it; // 解引用迭代器,获取字符
}
cout << endl;
// 修改字符串中的字符
for (string::iterator it = str.begin(); it != str.end(); ++it) {
if (*it == 'C') {
*it = 'D'; // 修改 'C' 为 'D'
}
}
cout << str << endl;
return 0;
}
运行结果:
Hello, C++ World!
Hello, D++ World!
在这里,只做普通正向迭代器的使用做介绍,并无对 常量迭代器、反向迭代器、常量反向迭代器,做介绍,平时也是在一些特定场景才用,大家如果想了解他们的用法可去网站了解详细用法,此章节只作入门介绍。