C++ 标准库:string 类、vector/List 容器与文件操作深度剖析
引言
C++ 标准库犹如一座编程的宝库,其中的 string
类、vector
和 List
容器以及文件操作(fstream
)为开发者提供了强大而便捷的工具,能极大地提升编程效率。接下来,我们将全方位深入探索这些重要组件。
一、string 类
1. 概述
string
类位于 <string>
头文件中,它是 C++ 为处理字符串量身打造的利器。相较于传统的 C 风格字符串(以 '\0'
结尾的字符数组),string
类拥有自动内存管理功能,提供了丰富的成员函数,使用起来更加方便、安全。
2. 详细使用方法
2.1 定义与初始化
#include <iostream>
#include <string>
int main() {
// 默认构造函数,创建一个空字符串
std::string str1;
// 使用 C 风格字符串初始化
std::string str2("Hello, C++!");
// 使用另一个 string 对象初始化
std::string str3(str2);
// 使用重复字符初始化
std::string str4(5, 'X');
// 从指定位置开始截取初始化
std::string str5(str2, 7, 3);
std::cout << "str1: " << str1 << std::endl;
std::cout << "str2: " << str2 << std::endl;
std::cout << "str3: " << str3 << std::endl;
std::cout << "str4: " << str4 << std::endl;
std::cout << "str5: " << str5 << std::endl;
return 0;
}
2.2 字符串拼接
#include <iostream>
#include <string>
int main() {
std::string str1 = "Hello";
std::string str2 = " World";
std::string str3 = "!";
// 使用 + 运算符拼接
std::string result1 = str1 + str2 + str3;
// 使用 append 方法拼接
std::string result2 = str1;
result2.append(str2);
result2.append(str3);
std::cout << "result1: " << result1 << std::endl;
std::cout << "result2: " << result2 << std::endl;
return 0;
}
2.3 字符串查找与替换
#include <iostream>
#include <string>
int main() {
std::string str = "Hello, World! World is wonderful.";
// 查找子字符串第一次出现的位置
size_t pos1 = str.find("World");
if (pos1 != std::string::npos) {
std::cout << "第一次出现的位置: " << pos1 << std::endl;
}
// 从指定位置开始查找子字符串
size_t pos2 = str.find("World", pos1 + 1);
if (pos2 != std::string::npos) {
std::cout << "第二次出现的位置: " << pos2 << std::endl;
}
// 替换子字符串
str.replace(pos1, 5, "C++");
std::cout << "替换后的字符串: " << str << std::endl;
return 0;
}
2.4 字符串比较
#include <iostream>
#include <string>
int main() {
std::string str1 = "apple";
std::string str2 = "banana";
std::string str3 = "apple";
// 使用 compare 方法比较
if (str1.compare(str2) < 0) {
std::cout << "str1 在字典序上小于 str2" << std::endl;
}
if (str1.compare(str3) == 0) {
std::cout << "str1 等于 str3" << std::endl;
}
return 0;
}
3. 高级特性
- 容量管理:
string
类会自动管理内存,但也提供了一些方法来控制容量,如reserve
可以预先分配一定的内存空间,减少内存重新分配的次数。 - 迭代器:支持使用迭代器遍历字符串,如
begin()
和end()
分别返回指向字符串首字符和尾后字符的迭代器。
二、vector/List 容器
1. vector 容器
1.1 概述
vector
是一种动态数组,位于 <vector>
头文件中。它的元素在内存中连续存储,支持随机访问,并且能够自动调整大小。
1.2 详细使用方法
1.2.1 定义与初始化
#include <iostream>
#include <vector>
int main() {
// 默认构造函数,创建一个空的 vector
std::vector<int> vec1;
// 初始化指定大小的 vector
std::vector<int> vec2(5);
// 初始化指定大小并赋予初始值
std::vector<int> vec3(5, 10);
// 使用另一个 vector 初始化
std::vector<int> vec4(vec3);
std::cout << "vec1 大小: " << vec1.size() << std::endl;
std::cout << "vec2 大小: " << vec2.size() << std::endl;
std::cout << "vec3 大小: " << vec3.size() << std::endl;
std::cout << "vec4 大小: " << vec4.size() << std::endl;
return 0;
}
1.2.2 元素操作
#include <iostream>
#include <vector>
int main() {
std::vector<int> vec;
// 添加元素
vec.push_back(1);
vec.push_back(2);
vec.push_back(3);
// 访问元素
std::cout << "第一个元素: " << vec[0] << std::endl;
std::cout << "第二个元素: " << vec.at(1) << std::endl;
// 修改元素
vec[1] = 5;
// 删除最后一个元素
vec.pop_back();
// 遍历元素
for (int num : vec) {
std::cout << num << " ";
}
std::cout << std::endl;
return 0;
}
1.2.3 插入和删除元素
#include <iostream>
#include <vector>
int main() {
std::vector<int> vec = {1, 2, 3, 4, 5};
// 在指定位置插入元素
auto it = vec.begin() + 2;
vec.insert(it, 10);
// 删除指定位置的元素
vec.erase(vec.begin() + 3);
for (int num : vec) {
std::cout << num << " ";
}
std::cout << std::endl;
return 0;
}
1.3 优势与适用场景
- 随机访问:可以通过下标直接访问元素,时间复杂度为 O(1),适合需要频繁随机访问元素的场景。
- 动态扩展:当元素数量超过容器容量时,会自动重新分配内存并扩展容量,使用方便。但在插入和删除元素时,尤其是在中间位置,效率较低。
2. List 容器
2.1 概述
list
是一种双向链表,位于 <list>
头文件中。它的元素在内存中不连续存储,每个元素包含指向前一个元素和后一个元素的指针,支持高效的插入和删除操作,但不支持随机访问。
2.2 详细使用方法
2.2.1 定义与初始化
#include <iostream>
#include <list>
int main() {
// 默认构造函数,创建一个空的 list
std::list<int> list1;
// 初始化指定大小的 list
std::list<int> list2(5);
// 初始化指定大小并赋予初始值
std::list<int> list3(5, 10);
// 使用另一个 list 初始化
std::list<int> list4(list3);
std::cout << "list1 大小: " << list1.size() << std::endl;
std::cout << "list2 大小: " << list2.size() << std::endl;
std::cout << "list3 大小: " << list3.size() << std::endl;
std::cout << "list4 大小: " << list4.size() << std::endl;
return 0;
}
2.2.2 元素操作
#include <iostream>
#include <list>
int main() {
std::list<int> myList;
// 添加元素
myList.push_back(1);
myList.push_front(0);
// 访问第一个和最后一个元素
std::cout << "第一个元素: " << myList.front() << std::endl;
std::cout << "最后一个元素: " << myList.back() << std::endl;
// 删除第一个和最后一个元素
myList.pop_front();
myList.pop_back();
return 0;
}
2.2.3 插入和删除元素
#include <iostream>
#include <list>
int main() {
std::list<int> myList = {1, 2, 3, 4, 5};
// 在指定位置插入元素
auto it = std::next(myList.begin(), 2);
myList.insert(it, 10);
// 删除指定位置的元素
it = std::next(myList.begin(), 3);
myList.erase(it);
for (int num : myList) {
std::cout << num << " ";
}
std::cout << std::endl;
return 0;
}
2.3 优势与适用场景
- 高效的插入和删除:在任意位置插入和删除元素的时间复杂度为 O(1),适合需要频繁进行插入和删除操作的场景。
- 不支持随机访问:由于元素在内存中不连续存储,不能通过下标直接访问元素,需要通过迭代器遍历,访问效率较低。
3. 选择建议
- 如果需要随机访问元素,并且插入和删除操作主要在尾部进行,建议使用
vector
。 - 如果需要频繁在任意位置进行插入和删除操作,建议使用
list
。
三、文件操作(fstream)
1. 概述
C++ 标准库提供了 <fstream>
头文件,用于进行文件操作。主要有三个类:ifstream
(用于读取文件)、ofstream
(用于写入文件)和 fstream
(用于读写文件)。
2. 详细使用方法
2.1 文件读取
#include <iostream>
#include <fstream>
#include <string>
int main() {
std::ifstream inFile("example.txt");
if (inFile.is_open()) {
std::string line;
// 逐行读取文件
while (std::getline(inFile, line)) {
std::cout << line << std::endl;
}
inFile.close();
} else {
std::cerr << "无法打开文件" << std::endl;
}
return 0;
}
2.2 文件写入
#include <iostream>
#include <fstream>
#include <string>
int main() {
// 以覆盖模式打开文件
std::ofstream outFile("output.txt");
if (outFile.is_open()) {
outFile << "Hello, File!" << std::endl;
outFile << "This is a test." << std::endl;
outFile.close();
} else {
std::cerr << "无法打开文件" << std::endl;
}
// 以追加模式打开文件
std::ofstream appendFile("output.txt", std::ios::app);
if (appendFile.is_open()) {
appendFile << "Appended content." << std::endl;
appendFile.close();
} else {
std::cerr << "无法打开文件" << std::endl;
}
return 0;
}
2.3 文件读写
#include <iostream>
#include <fstream>
#include <string>
int main() {
std::fstream file("data.txt", std::ios::in | std::ios::out | std::ios::trunc);
if (file.is_open()) {
// 写入数据
file << "10 20 30" << std::endl;
// 将文件指针移动到文件开头
file.seekg(0, std::ios::beg);
int num1, num2, num3;
// 读取数据
file >> num1 >> num2 >> num3;
std::cout << "读取的数据: " << num1 << " " << num2 << " " << num3 << std::endl;
file.close();
} else {
std::cerr << "无法打开文件" << std::endl;
}
return 0;
}
3. 注意事项
- 在进行文件操作时,要确保文件能够正常打开,否则会导致程序出错。可以使用
is_open()
方法检查文件是否打开成功。 - 使用完文件后,要及时关闭文件,以释放系统资源。可以使用
close()
方法关闭文件。 - 在文件读写过程中,要注意文件指针的位置,可以使用
seekg()
和seekp()
方法移动文件指针。
四、总结
C++ 标准库中的 string
类、vector
和 List
容器以及文件操作(fstream
)为我们提供了强大而便捷的工具。string
类让字符串处理更加简单安全,vector
和 list
容器可以根据不同的需求选择使用,而文件操作则方便我们进行数据的持久化存储。熟练掌握这些标准库的使用,能够显著提高 C++ 编程的效率和质量。同时,我们还应该深入理解它们的底层原理和适用场景,以便在实际开发中做出更合适的选择。