string类型使用
在C++中,std::string是标准库中用来表示字符串的一种
类 **
型。它的底层实现是一个动态数组,它可以存储任意长度的字符串,自动处理内存的分配和释放。对于C++中的std::string类型数据传参,我们需要理解以下几个方面:
1. std::string 不是基本数据类型,而是一个类
std::string 是 C++ 标准库中的一个类,定义在头文件 <string> 中。它提供了用于操作字符串的各种方法,例如 length(), append(), substr() 等。
cpp#include <iostream>
#include <string>
int main() {
std::string str = "Hello, world!";
std::cout << str << std::endl;
return 0;
}
2. std::string 默认不是指针
虽然 std::string 实现内部可能使用指针来存储字符数组,但 std::string 类型本身不是指针。它是一个类,它在内部管理了自己的内存,因此在操作时不需要你手动分配或释放内存。
在 C++ 中,std::string 类封装了指针的管理,因此你可以像处理普通对象一样使用它。
3. std::string 的传参方式:传值、传指针和传引用
3.1 传值(Pass by Value)
如果你传递一个 std::string 的副本(即传值),会创建一个新的 std::string 对象。这个副本会有自己的内存空间,原始的字符串对象不会受到影响。
cppvoid func(std::string str) {
str += " modified"; // 这个修改不会影响外部的原始字符串
}
int main() {
std::string str = "Hello";
func(str);
std::cout << str << std::endl; // 输出: Hello
return 0;
}
3.2 传引用(Pass by Reference)
如果你传递 std::string 的引用(std::string&),函数可以直接修改原始字符串对象的内容。引用是一种“别名”,指向原始数据。
- 普通引用: 如果你不打算修改字符串内容,可以使用
const std::string&,这样既避免了不必要的拷贝,也保证了函数内部不会修改原始字符串。 - 非常量引用: 如果你打算修改传入的字符串,可以使用
std::string&。
cppvoid func(std::string& str) {
str += " modified"; // 修改传入的字符串
}
int main() {
std::string str = "Hello";
func(str);
std::cout << str << std::endl; // 输出: Hello modified
return 0;
}
3.3 传指针(Pass by Pointer)
如果你传递 std::string*(指针),那么可以通过指针访问并修改传入的字符串。
cppvoid func(std::string* str) {
str->append(" modified"); // 修改指针所指向的字符串
}
int main() {
std::string str = "Hello";
func(&str);
std::cout << str << std::endl; // 输出: Hello modified
return 0;
}
4. std::string 的特性
std::string 是一个非常强大的类,具备许多有用的特性和方法。以下是它的一些关键特性:
4.1 动态内存管理
std::string 对象会根据字符串的大小动态调整内存。当你对字符串进行修改时(例如追加字符、改变大小等),它会自动调整所需的内存空间。因此,你无需担心内存的分配和释放。
4.2 自动释放内存
std::string 会在它的生命周期结束时自动释放内存(通过析构函数)。这意味着你不需要像使用 C 风格字符串那样手动 malloc 或 free 内存。
4.3 支持范围检查
与 C 风格字符串不同,std::string 提供了范围检查,可以避免访问越界问题。你可以使用 at() 方法访问字符,并且它会在越界时抛出异常。
cppstd::string str = "Hello";
std::cout << str.at(2) << std::endl; // 输出: l
// 如果使用 at() 超出范围,则抛出 std::out_of_range 异常
// std::cout << str.at(10); // 报错:std::out_of_range
4.4 内存重用和效率
std::string 使用小字符串优化(small string optimization,SSO)来提高效率。对于短字符串,std::string 会直接将字符存储在它自己的内存块中,而不是分配堆内存。因此,std::string 对于短字符串的使用非常高效。
4.5 支持字符串拼接
std::string 提供了很多操作符和方法来方便地拼接和修改字符串。例如,+ 操作符可以用于字符串拼接。
cppstd::string str1 = "Hello";
std::string str2 = " World!";
std::string result = str1 + str2; // 拼接两个字符串
std::cout << result << std::endl; // 输出: Hello World!
4.6 支持查找、替换和分割
std::string 提供了很多用于查找、替换和分割字符串的函数。例如,find(), replace(), substr() 等。
cppstd::string str = "Hello, world!";
size_t pos = str.find("world");
if (pos != std::string::npos) {
std::cout << "Found 'world' at position " << pos << std::endl;
}
5. 总结:C++ 中 std::string 的传参
std::string默认是一个类,而不是指针。- 传递
std::string时,可以选择传值(会创建副本)、传引用(可以修改原数据)、或传指针(通过指针访问原数据)。 std::string内部管理自己的内存,自动进行内存分配和释放,支持范围检查、字符串拼接、查找替换等操作。
通常推荐通过常量引用(const std::string&)来传递字符串,因为它既避免了不必要的拷贝,又不会修改原始数据。
1. 字符串长度 ( length() 和 size() )
- 这两个方法用于返回字符串的长度。它们是等效的,可以互换使用。
cppstd::string str = "Hello, world!";
std::cout << "Length: " << str.length() << std::endl; // 输出: 13
std::cout << "Size: " << str.size() << std::endl; // 输出: 13
2. 访问字符 ( operator[] 和 at() )
operator[]
和
at()
都可以用来访问字符串中的单个字符。
- `operator[]` 不会进行范围检查,使用时需要确保索引合法。
- `at()` 会进行范围检查,超出索引会抛出 `std::out_of_range` 异常。
cppstd::string str = "Hello, world!";
std::cout << str[0] << std::endl; // 输出: H
std::cout << str.at(1) << std::endl; // 输出: e
// 使用 at() 超出范围时会抛出异常
try {
std::cout << str.at(20) << std::endl;
} catch (const std::out_of_range& e) {
std::cout << "Error: " << e.what() << std::endl;
}
3. 拼接字符串 ( operator+ 和 append() )
operator+用于拼接两个字符串,返回一个新的字符串。append()方法可以将另一个字符串附加到当前字符串末尾。
cppstd::string str1 = "Hello";
std::string str2 = " world!";
std::string result = str1 + str2;
std::cout << result << std::endl; // 输出: Hello world!
str1.append(" everyone");
std::cout << str1 << std::endl; // 输出: Hello everyone
4. 查找子字符串 ( find() )
find()用于查找子字符串在当前字符串中的位置。如果找到,返回该位置的索引,否则返回std::string::npos。
cppstd::string str = "Hello, world!";
size_t pos = str.find("world");
if (pos != std::string::npos) {
std::cout << "'world' found at index: " << pos << std::endl; // 输出: 7
}
5. 替换子字符串 ( replace() )
replace()用于替换字符串中的一部分。可以指定起始位置和替换的字符数。
cppstd::string str = "Hello, world!";
str.replace(7, 5, "C++"); // 从索引7开始替换5个字符为 "C++"
std::cout << str << std::endl; // 输出: Hello, C++!
6. 获取子字符串 ( substr() )
substr()用于从字符串中提取子字符串。可以指定起始位置和子字符串的长度。
cppstd::string str = "Hello, world!";
std::string sub = str.substr(7, 5); // 从索引7开始提取5个字符
std::cout << sub << std::endl; // 输出: world
7. 字符串大小写转换 ( toupper() 和 tolower() )
toupper()和tolower()是用于将字符转换为大写或小写,但它们只能作用于单个字符。- 如果需要对整个字符串进行转换,可以使用循环或
std::transform()。
cpp#include <cctype>
#include <algorithm>
std::string str = "Hello, world!";
for (char& c : str) {
c = std::toupper(c); // 将每个字符转换为大写
}
std::cout << str << std::endl; // 输出: HELLO, WORLD!
// 也可以使用 std::transform()
std::transform(str.begin(), str.end(), str.begin(), ::tolower);
std::cout << str << std::endl; // 输出: hello, world!
8. 去除空格 ( erase() 和 find_first_not_of() )
- 可以使用
erase()去除字符串两端的空格。find_first_not_of()用于查找第一个不等于给定字符的字符,常用于去除字符串两端的空白字符。
cppstd::string str = " Hello, world! ";
str.erase(0, str.find_first_not_of(" ")); // 去除前导空格
str.erase(str.find_last_not_of(" ") + 1); // 去除尾部空格
std::cout << "[" << str << "]" << std::endl; // 输出: [Hello, world!]
9. 字符串拆分 (使用 find() 和 substr() )
C++ 标准库本身没有内建的拆分字符串的方法,但可以通过 find() 和 substr() 来手动实现拆分。
cppstd::string str = "apple,banana,cherry";
size_t pos = 0;
std::string delimiter = ",";
while ((pos = str.find(delimiter)) != std::string::npos) {
std::string token = str.substr(0, pos);
std::cout << token << std::endl; // 输出: apple banana
str.erase(0, pos + delimiter.length());
}
std::cout << str << std::endl; // 输出: cherry
10. 比较字符串 ( compare() 和 == , != )
compare()方法用于比较两个字符串。如果字符串相等,返回 0;如果当前字符串小于目标字符串,返回负值;如果当前字符串大于目标字符串,返回正值。- 你也可以直接使用
==和!=来比较字符串。
cppstd::string str1 = "apple";
std::string str2 = "banana";
if (str1.compare(str2) < 0) {
std::cout << "apple is less than banana" << std::endl;
}
if (str1 == str2) {
std::cout << "The strings are equal." << std::endl;
} else {
std::cout << "The strings are not equal." << std::endl;
}
11. 字符串转换为数字 ( stoi() , stol() , stof() , stod() )
stoi()用于将字符串转换为整数,stof()用于将字符串转换为浮点数等。注意,若字符串格式不正确,它们会抛出异常。
cppstd::string str = "12345";
int num = std::stoi(str);
std::cout << num << std::endl; // 输出: 12345
std::string floatStr = "12.34";
float fnum = std::stof(floatStr);
std::cout << fnum << std::endl; // 输出: 12.34
12. 查找字符位置 ( find_first_of() , find_last_of() )
find_first_of()查找第一个匹配指定字符或字符集的位置。find_last_of()查找最后一个匹配指定字符或字符集的位置。
cppstd::string str = "apple,banana,cherry";
size_t pos = str.find_first_of("aeiou"); // 查找第一个元音字母的位置
std::cout << "First vowel at: " << pos << std::endl; // 输出: First vowel at: 0