Loading...

string类型使用

2024-12-05
0
-
- 分钟
|

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 风格字符串那样手动 mallocfree 内存。

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

文章目录