目录
一、string类型的基本概念
1.1. 定义与头文件
1.2. 本质与特点
1.3. 与 C 风格字符串的区别
二、string类型的构造函数
2.1. 默认构造函数
2.2. 使用C风格字符串初始化
2.3. 拷贝构造函数
2.4. 使用字符和重复次数初始化
2.5. 使用子串初始化
三、string类型的赋值操作
3.1 使用赋值运算符=
3.2 使用assign成员函数
四、string类型的容量操作
五、string类型的元素访问
5.1 使用下标运算符[]
5.2 使用at成员函数
六、string类型的迭代遍历
七、string类型的字符串操作
八、字符串输入输出处理
九、内存管理与性能优化
9.1 容量管理
9.2 避免不必要的拷贝
十、字符串与数值的转换
十一、C++11 及后续版本的新特性
十二、string 类型在实际应用中的示例
十三、 参考资料
在C++编程中,string
类型是一个非常重要的标准库类型,用于处理可变长度的字符序列。相比C语言中的字符数组(以\0
结尾的字符串),std::string
提供了更高效、更安全的字符串操作方法。
一、string类型的基本概念
1.1. 定义与头文件
std::string
是C++标准库中的一个类,定义在<string>
头文件中。要使用std::string
,需要在程序开头包含该头文件:
include <string>
为了简化代码,通常使用std
命名空间:
using namespace std;
1.2. 本质与特点
std::string
本质:std::string
本质上是一个模板类basic_string
的 typedef,即typedef basic_string<char> string;
内部封装了char*
指针,通过容器的方式管理字符串。- 动态增长和缩小:支持动态增长和缩小,无需关心字符串的长度或容量。
1.3. 与 C 风格字符串的区别
-
自动内存管理:
string
自动处理内存分配和释放,无需手动管理。 -
安全性:避免缓冲区溢出(如
strcpy
的潜在风险)。 -
功能丰富:支持拼接、查找、替换等操作,无需调用低级函数。
二、string类型的构造函数
std::string
提供了多种构造函数,用于初始化字符串对象。以下是一些常用的构造函数。
2.1. 默认构造函数
创建一个空的字符串对象:
string str1; // str1是一个空字符串
2.2. 使用C风格字符串初始化
使用C风格字符串(以\0
结尾的字符数组)初始化std::string
对象。
const char* cstr = "hello";
string str2(cstr); // str2是"hello"的副本
2.3. 拷贝构造函数
使用另一个std::string
对象初始化新的字符串对象。
string str3(str2); // str3是str2的副本
2.4. 使用字符和重复次数初始化
使用指定的字符和重复次数初始化字符串。
string str4(5, 'x'); // str4是"xxxxx"
2.5. 使用子串初始化
从已有的字符串中提取子串,用于初始化新的字符串对象。
string str5(str4, 1, 3); // str5是str4从索引1开始的3个字符,即"xxx"
三、string类型的赋值操作
std::string
支持多种赋值方式,可以将一个字符串的值赋给另一个字符串对象。
3.1 使用赋值运算符=
可以将C风格字符串、std::string
对象或单个字符赋值给std::string
对象:
string str1;
str1 = "hello"; // 将C风格字符串赋值给str1
string str2 = str1; // 将str1赋值给str2
string str3;
str3 = 'a'; // 将字符'a'赋值给str3,注意这里str3会变成"a"
3.2 使用assign
成员函数
assign
成员函数提供了更多的赋值方式,可以指定赋值的起始位置和长度:
使用assign成员函数
assign成员函数提供了更多的赋值方式,可以指定赋值的起始位置和长度:
四、string类型的容量操作
std::string
提供了多个成员函数,用于获取或修改字符串的容量。
①获取字符串的长度:使用size
或length
成员函数获取字符串中字符的个数(不包括结束符\0
)
string str = "hello";
size_t len = str.size(); // len是5
②判断字符串是否为空:使用empty
成员函数判断字符串是否为空。
if (str.empty()) {cout << "字符串为空" << endl;
} else {cout << "字符串不为空" << endl;
}
③修改字符串的容量
-
使用
reserve
成员函数为字符串预留空间,不改变当前内容:
str.reserve(100); // 为str预留至少100个字符的空间
- 使用
resize
成员函数改变字符串的大小,可以指定填充字符:
str.resize(10, '*'); // 将str的大小改为10,不足部分用'*'填充
- 使用
clear
成员函数清空字符串的内容,但不改变容量:
str.clear(); // str变为空字符串,但容量不变
五、string类型的元素访问
可以通过多种方式访问std::string
中的字符。
5.1 使用下标运算符[]
通过下标运算符访问字符串中的单个字符,下标从0开始:
string str = "hello";
char ch = str[1]; // ch是'e'
注意:使用下标运算符访问字符时,不会进行越界检查,需要确保下标在有效范围内。
5.2 使用at
成员函数
at
成员函数提供了安全的字符访问方式,会进行越界检查:
char ch = str.at(1); // ch是'e',如果索引超出范围,会抛出std::out_of_range异常
六、string类型的迭代遍历
可以使用迭代器或范围for
循环遍历std::string
中的字符。
①使用迭代器:std::string
提供了begin
和end
成员函数,返回指向字符串开头和结尾的迭代器
string str = "hello";
for (string::iterator it = str.begin(); it != str.end(); ++it) {cout << *it << " ";
}
// 输出:h e l l o
②使用范围for
循环:范围for
循环提供了一种更简洁的遍历方式
for (char ch : str) {cout << ch << " ";
}
// 输出:h e l l o
七、string类型的字符串操作
std::string
提供了丰富的成员函数,用于执行各种字符串操作。
①字符串连接:使用+
运算符或append
成员函数连接字符串
string str1 = "hello";
string str2 = "world";
string result = str1 + " " + str2; // 使用+运算符连接
cout << result << endl; // 输出:hello worldstring str3 = "hello";
str3.append(" ");
str3.append(str2); // 使用append成员函数连接
cout << str3 << endl; // 输出:hello world
②字符串比较:可以使用关系运算符(==
、!=
、<
、<=
、>
、>=
)或compare
成员函数比较字符串
if (str1 == str2) {cout << "str1等于str2" << endl;
} else {cout << "str1不等于str2" << endl;
}int cmp = str1.compare(str2);
if (cmp == 0) {cout << "str1等于str2" << endl;
} else if (cmp < 0) {cout << "str1小于str2" << endl;
} else {cout << "str1大于str2" << endl;
}
③查找子串:使用find
或rfind
成员函数查找子串的位置
size_t pos = str.find("world");
if (pos != string::npos) {cout << "找到子串,位置为:" << pos << endl;
} else {cout << "未找到子串" << endl;
}size_t rpos = str.rfind("o");
cout << "最后一个'o'的位置为:" << rpos << endl;
④替换子串:使用replace
成员函数替换字符串中的子串
string str =
八、字符串输入输出处理
①读取整行输入:使用 getline()
代替 cin >>
以避免空格截断
string line;
getline(cin, line); // 读取一行输入(包括空格)
②格式化处理:结合 stringstream
进行字符串分割或转换
string data = "10 3.14 hello";
stringstream ss(data);
int num; double d; string s;
ss >> num >> d >> s; // 解析为 num=10, d=3.14, s="hello"
九、内存管理与性能优化
9.1 容量管理
-
capacity()
:返回当前分配的存储容量。 -
reserve(n)
:预分配至少n
个字符的内存,减少动态分配次数。 -
shrink_to_fit()
:请求减少容量以匹配实际大小(C++11)。
9.2 避免不必要的拷贝
-
使用移动语义(C++11)提升性能:
string s1 = "Hello";
string s2 = std::move(s1); // s1 变为空,s2 接管资源
-
传递
const string&
避免拷贝。
十、字符串与数值的转换
字符串 → 数值
string s = "123";
int num = stoi(s); // 转换为 int
double d = stod("3.14"); // 转换为 double
数值 → 字符串
string s1 = to_string(42); // "42"
string s2 = to_string(3.1415); // "3.1415"
十一、C++11 及后续版本的新特性
字面量后缀
using namespace std::string_literals;
auto s = "Hello"s; // 直接生成 string 类型(而非 const char*)
范围 for 循环
for (char c : s) {cout << c << " ";
}
十二、string
类型在实际应用中的示例
文件读取与处理:在处理文本文件时,string
类型非常有用。例如,从文件中逐行读取内容并进行处理:
#include <iostream>
#include <fstream>
#include <string>
int main() {std::ifstream file("test.txt");if (file.is_open()) {std::string line;while (std::getline(file, line)) {// 对每一行进行处理std::cout << line << std::endl;}file.close();} else {std::cerr << "Unable to open file" << std::endl;}return 0;
}
字符串查找与替换:在处理字符串时,经常需要查找特定的子字符串并进行替换。string
类型提供了 find()
成员函数来查找子字符串的位置,以及 replace()
成员函数来进行替换:
std::string str = "hello world";
size_t pos = str.find("world");
if (pos != std::string::npos) {str.replace(pos, 5, "C++");std::cout << str << std::endl; // 输出: hello C++
}
希望这篇文章能够帮助你对 string
类型有更深入的理解和掌握。如果还有其他关于 C++ 的问题,欢迎继续探索和学习。
十三、 参考资料
-
《C++ Primer》
-
cppreference.com