当前位置: 代码网 > it编程>编程语言>C/C++ > C++之STL--string的使用

C++之STL--string的使用

2025年06月03日 C/C++ 我要评论
深入探索 c++ stl 中的 std::string在 c++ 编程中,字符串处理是一个常见的任务,而 c++ 标准模板库(stl)中的 std::string 类为我们提供了强大的功能来简化这一过

深入探索 c++ stl 中的 std::string

在 c++ 编程中,字符串处理是一个常见的任务,而 c++ 标准模板库(stl)中的 std::string 类为我们提供了强大的功能来简化这一过程。

一、std::string 的基本概念

std::string 是 c++ stl 中的一个类,用于表示和操作字符串。它属于 <string> 头文件,是基于模板的 std::basic_string 类的一个特化版本,专门用于处理字符类型为 char 的字符串。与传统的 c 风格字符串(以空字符结束的字符数组)相比,std::string 提供了更高的安全性和更丰富的功能。

1. 内存管理

std::string 内部会动态管理内存,这意味着你不需要手动分配和释放内存。

当你对字符串进行修改时,std::string 会自动调整内存大小以适应新的内容。

  • 例如:
std::string str = "hello";
str += ", world!"; // 内部自动调整内存大小

2. 安全性

std::string 不会像 c 风格字符串那样容易出现越界访问或内存泄漏的问题。

它提供了边界检查和异常处理机制,确保字符串操作的安全性。

二、std::string 的构造与初始化

std::string 提供了多种构造方式,可以根据不同的需求选择合适的构造函数。

1. 默认构造

std::string str; // 创建一个空字符串

2. 从 c 风格字符串构造

const char* c_str = "hello";
std::string str(c_str); // 使用 c 风格字符串初始化

3. 从字符串的一部分构造

std::string str1 = "hello world";
std::string str2(str1, 6, 5); // 从 str1 的第 6 个字符开始,取 5 个字符
// str2 的内容为 "world"

4. 使用重复字符构造

std::string str(5, 'a'); // 创建一个包含 5 个 'a' 的字符串
// str 的内容为 "aaaaa"

三、std::string 的常用操作

1. 字符串拼接

std::string 提供了多种方式来拼接字符串,包括使用 + 运算符和 += 运算符。

std::string str1 = "hello";
std::string str2 = "world";
std::string str3 = str1 + ", " + str2 + "!"; // 使用 + 拼接
str1 += " "; // 使用 += 拼接
str1 += str2;
// str1 的内容为 "hello world"

2. 字符串比较

std::string 支持使用比较运算符(如 ==!=<> 等)来比较字符串内容。

std::string str1 = "apple";
std::string str2 = "banana";
if (str1 < str2) {
    std::cout << "apple is less than banana" << std::endl;
}

3. 字符串查找

std::string 提供了 find 方法,用于查找子字符串的位置。

std::string str = "hello world";
size_t pos = str.find("world");
if (pos != std::string::npos) {
    std::cout << "found 'world' at position " << pos << std::endl;
}

4. 字符串替换

std::stringreplace 方法可以用来替换字符串中的部分内容。

std::string str = "hello world";
str.replace(6, 5, "universe");
// str 的内容变为 "hello universe"

5. 字符串分割

虽然 std::string 没有直接提供分割字符串的方法,但可以通过循环和 find 方法实现。

std::string str = "apple,banana,orange";
std::string delimiter = ",";
size_t pos = 0;
std::string token;
while ((pos = str.find(delimiter)) != std::string::npos) {
    token = str.substr(0, pos);
    std::cout << token << std::endl;
    str.erase(0, pos + delimiter.length());
}
std::cout << str << std::endl; // 输出最后一个子字符串

6. 字符串大小和容量

std::string 提供了 sizecapacity 方法来获取字符串的长度和当前分配的内存容量。

std::string str = "hello";
std::cout << "size: " << str.size() << std::endl; // 输出 5
std::cout << "capacity: " << str.capacity() << std::endl; // 输出实际分配的容量

7. 字符访问

可以通过下标运算符 []at 方法访问字符串中的字符。

std::string str = "hello";
char c = str[0]; // 使用下标访问
char d = str.at(1); // 使用 at 方法访问

四.string类对象的访问及遍历操作

std::string的容量相关概念

在深入了解容量操作之前,我们需要明确几个与std::string容量相关的重要概念:

1. size(或length)

size函数返回字符串中实际存储的字符数量,不包括末尾的空字符'\0'length函数与size功能完全相同,只是名字不同。

std::string str = "hello, world!";
std::cout << "size: " << str.size() << std::endl; // 输出:size: 13

2. capacity

capacity函数返回字符串当前分配的内存容量,单位是字符数。

capacity通常大于或等于size,因为std::string会预留一些额外的内存,以便在字符串扩展时减少内存分配的次数。

std::string str = "hello, world!";
std::cout << "capacity: " << str.capacity() << std::endl; // 输出:capacity: 15(具体值可能因实现而异)

3. max_size

max_size函数返回std::string能够存储的最大字符数。

这个值通常取决于系统的内存限制和std::string的实现。

std::string str;
std::cout << "max size: " << str.max_size() << std::endl; // 输出:max size: 18446744073709551615(64位系统)

reserve:预留内存

reserve函数用于显式地为std::string预留一定量的内存。这可以减少在字符串频繁扩展时的内存分配次数,从而提高性能。

使用场景

当你知道字符串将要存储大量字符时,可以使用reserve预先分配足够的内存。

例如,当你从文件中读取大量文本并拼接到字符串中时,reserve可以显著提高效率。

示例代码

std::string str;
str.reserve(1000); // 预留1000个字符的内存
for (int i = 0; i < 1000; ++i) {
    str += 'a';
}
std::cout << "size: " << str.size() << std::endl; // 输出:size: 1000
std::cout << "capacity: " << str.capacity() << std::endl; // 输出:capacity: 1000

注意事项

  • reserve不会改变字符串的内容,只是改变其容量。
  • 如果reserve的参数小于当前capacitystd::string的容量不会减少。
  • reserve是一个非强制性操作,具体行为可能因标准库的实现而异。

shrink_to_fit:收缩内存

shrink_to_fit函数用于收缩std::string的容量,使其尽可能接近实际的size

这可以减少不必要的内存占用,但需要注意的是,shrink_to_fit是一个非强制性操作,具体行为可能因标准库的实现而异。

使用场景

当你完成了一个字符串的频繁修改操作后,可以使用shrink_to_fit来释放多余的内存。

例如,在字符串拼接完成后,调用shrink_to_fit可以优化内存使用。

示例代码

std::string str = "hello";
str += "world";
str.shrink_to_fit();
std::cout << "size: " << str.size() << std::endl; // 输出:size: 10
std::cout << "capacity: " << str.capacity() << std::endl; // 输出:capacity: 10(具体值可能因实现而异)

注意事项

  • shrink_to_fit不会改变字符串的内容,只是尝试减少其容量。
  • shrink_to_fit是一个非强制性操作,可能不会立即生效。

resize:调整字符串大小

resize函数用于调整字符串的大小。如果新的大小大于当前size,则会用指定的字符填充新分配的部分;如果新的大小小于当前size,则会截断字符串。

示例代码

std::string str = "hello, world!";
str.resize(5); // 截断字符串
std::cout << "resized string: " << str << std::endl; // 输出:hello

str.resize(10, 'x'); // 扩展字符串并用'x'填充
std::cout << "resized string: " << str << std::endl; // 输出:helloxxxxx

注意事项

  • resize会改变字符串的内容,而reserveshrink_to_fit不会。
  • resize的第二个参数是可选的,默认填充字符为空字符'\0'

容量操作的性能优化

合理使用std::string的容量操作可以显著提高程序的性能。

以下是一些优化建议:

1. 预留足够的内存

如果你知道字符串将要存储大量字符,使用reserve预先分配足够的内存可以减少内存分配的次数。

2. 及时收缩内存

在完成字符串的频繁修改操作后,使用shrink_to_fit可以释放多余的内存,优化内存使用。

3. 避免不必要的拷贝

std::string的拷贝构造和赋值操作可能会导致不必要的内存分配和拷贝。如果可能,尽量使用引用或std::move来避免拷贝。

五.string类对象的修改操作

std::string的修改操作概述

std::string提供了多种方法来修改字符串的内容,包括插入、删除、替换、直接修改字符等。

这些操作使得字符串的编辑变得非常灵活,同时也避免了c语言中直接操作字符数组时可能出现的内存错误。

直接修改字符

std::string支持通过下标操作符[]at函数直接修改字符串中的字符。

这两种方式的主要区别在于,[]操作符不进行边界检查,而at函数会进行边界检查并抛出异常。

示例代码

std::string str = "hello, world!";
str[0] = 'h'; // 将第一个字符修改为小写的'h'
str.at(7) = 'w'; // 将第8个字符(索引为7)修改为小写的'w'
std::cout << str << std::endl; // 输出:hello, world!

注意事项

  • 使用[]操作符时,如果索引超出字符串范围,行为是未定义的。
  • 使用at函数时,如果索引超出范围,会抛出std::out_of_range异常。

插入操作

std::string提供了多种插入操作,允许你在字符串的任意位置插入字符、字符串或字符数组。

1. 插入单个字符

std::string str = "hello, world!";
str.insert(5, "x"); // 在索引5的位置插入字符'x'
std::cout << str << std::endl; // 输出:hellox, world!

2. 插入字符串

std::string str = "hello, world!";
str.insert(7, "c++"); // 在索引7的位置插入字符串"c++"
std::cout << str << std::endl; // 输出:hello, c++world!

3. 插入字符数组

std::string str = "hello, world!";
char arr[] = "python";
str.insert(7, arr); // 在索引7的位置插入字符数组"python"
std::cout << str << std::endl; // 输出:hello, pythonworld!

注意事项

  • 插入操作会改变字符串的sizecapacity
  • 如果插入位置超出字符串范围,行为是未定义的。

删除操作

std::string提供了erase函数,用于删除字符串中的一部分内容。

示例代码

std::string str = "hello, world!";
str.erase(7, 5); // 从索引7开始删除5个字符
std::cout << str << std::endl; // 输出:hello, !

参数说明

  • 第一个参数是删除的起始位置(索引)。
  • 第二个参数是删除的字符数。

注意事项

  • 如果删除的起始位置超出字符串范围,行为是未定义的。
  • 删除操作会改变字符串的size,但不会改变capacity

替换操作

std::string提供了replace函数,用于替换字符串中的一部分内容。

示例代码

std::string str = "hello, world!";
str.replace(7, 5, "c++"); // 从索引7开始,替换5个字符为"c++"
std::cout << str << std::endl; // 输出:hello, c++!

参数说明

  • 第一个参数是替换的起始位置(索引)。
  • 第二个参数是替换的字符数。
  • 第三个参数是新的内容。

注意事项

  • 替换操作会改变字符串的size,但不会改变capacity
  • 如果替换的起始位置超出字符串范围,行为是未定义的。

追加操作

std::string提供了多种追加操作,允许你在字符串的末尾添加字符、字符串或字符数组。

1. 追加单个字符

std::string str = "hello";
str.push_back(' '); // 追加一个空格
str += 'w'; // 追加字符'w'
std::cout << str << std::endl; // 输出:hello w

2. 追加字符串

std::string str = "hello ";
str += "world"; // 追加字符串"world"
std::cout << str << std::endl; // 输出:hello world

3. 追加字符数组

std::string str = "hello ";
char arr[] = "c++";
str.append(arr); // 追加字符数组"c++"
std::cout << str << std::endl; // 输出:hello c++

注意事项

  • 追加操作会改变字符串的size,但不会改变capacity
  • 如果capacity不足,std::string会自动分配更大的内存。

清空字符串

std::string提供了clear函数,用于清空字符串的内容,但不会释放内存。

示例代码

std::string str = "hello, world!";
str.clear();
std::cout << "size: " << str.size() << std::endl; // 输出:size: 0
std::cout << "capacity: " << str.capacity() << std::endl; // 输出:capacity: 15(具体值可能因实现而异)

注意事项

  • clear函数只会清空字符串的内容,不会释放内存。
  • 如果需要释放内存,可以结合shrink_to_fit使用。

使用std::stringstream进行复杂修改

对于复杂的字符串修改操作,可以使用std::stringstream

std::stringstream是一个非常灵活的工具,可以方便地进行字符串的拼接、格式化和提取。

示例代码

#include <sstream>

std::string str = "hello, world!";
std::stringstream ss(str);
std::string word;
ss >> word; // 提取第一个单词
ss << "c++"; // 替换为"c++"
ss >> word; // 提取第二个单词
ss << "programming"; // 替换为"programming"
str = ss.str(); // 将修改后的内容赋值回str
std::cout << str << std::endl; // 输出:hello, c++programming

六.string类非成员函数

什么是std::string的非成员函数?

std::string的非成员函数是指那些不属于std::string类的成员函数,但专门用于操作std::string对象的函数。

这些函数通常定义在<string>头文件中,或者通过标准库的其他部分提供。

非成员函数的优势在于它们可以提供更通用的操作方式,同时避免了对std::string类本身的过度扩展。

常见的std::string非成员函数

1. std::swap

std::swap用于交换两个std::string对象的内容。

它是一个非成员函数,可以高效地交换两个字符串的内容,而不需要逐个字符复制。

示例代码

#include <iostream>
#include <string>
#include <algorithm> // 包含std::swap

int main() {
    std::string str1 = "hello";
    std::string str2 = "world";

    std::swap(str1, str2);

    std::cout << "str1: " << str1 << std::endl; // 输出:str1: world
    std::cout << "str2: " << str2 << std::endl; // 输出:str2: hello
}

2. std::to_string

std::to_string是一个非常有用的非成员函数,用于将数值类型(如intfloatdouble等)转换为std::string

它提供了一种简单且类型安全的方式来实现数值与字符串之间的转换。

示例代码

#include <iostream>
#include <string>

int main() {
    int num = 42;
    double pi = 3.14159;

    std::string numstr = std::to_string(num);
    std::string pistr = std::to_string(pi);

    std::cout << "number as string: " << numstr << std::endl; // 输出:number as string: 42
    std::cout << "pi as string: " << pistr << std::endl; // 输出:pi as string: 3.141590
}

3. std::stoi、std::stod、std::stof等

这些函数用于将std::string对象转换为数值类型。

std::stoi将字符串转换为intstd::stod将字符串转换为doublestd::stof将字符串转换为float等。

这些函数提供了一种简单且安全的方式来解析字符串中的数值。

示例代码

#include <iostream>
#include <string>

int main() {
    std::string numstr = "42";
    std::string pistr = "3.14159";

    int num = std::stoi(numstr);
    double pi = std::stod(pistr);

    std::cout << "number from string: " << num << std::endl; // 输出:number from string: 42
    std::cout << "pi from string: " << pi << std::endl; // 输出:pi from string: 3.14159
}

4. std::getline

std::getline是一个非成员函数,用于从输入流(如std::cinstd::ifstream)中读取一行内容并存储到std::string对象中。它支持按分隔符读取,例如按逗号、空格等分隔。

示例代码

#include <iostream>
#include <string>
#include <sstream>

int main() {
    std::string line = "hello, world!";
    std::istringstream ss(line);
    std::string word;

    while (std::getline(ss, word, ',')) {
        std::cout << word << std::endl; // 输出:hello 和 world!
    }
}

5. std::operator<< 和 std::operator>>

这些操作符重载允许你直接使用std::cinstd::cout来输入和输出std::string对象。

它们是c++标准库提供的非成员函数,使得字符串的输入输出变得非常方便。

示例代码

#include <iostream>
#include <string>

int main() {
    std::string str;
    std::cout << "enter a string: ";
    std::cin >> str;

    std::cout << "you entered: " << str << std::endl;
}

6. std::operator+ 和 std::operator+=

虽然这些操作符是std::string的成员函数,但它们也可以作为非成员函数使用。

std::operator+用于拼接两个字符串,而std::operator+=用于将一个字符串追加到另一个字符串的末尾。

这些操作符使得字符串拼接变得非常直观。

示例代码

#include <iostream>
#include <string>

int main() {
    std::string str1 = "hello";
    std::string str2 = "world";

    std::string result = str1 + " " + str2; // 使用std::operator+
    str1 += " "; // 使用std::operator+=
    str1 += str2;

    std::cout << "result: " << result << std::endl; // 输出:result: hello world
    std::cout << "modified str1: " << str1 << std::endl; // 输出:modified str1: hello world
}

7. std::operator==、std::operator!=、std::operator<等

这些操作符重载允许你直接比较两个std::string对象。它们按照字典序进行比较,使得字符串的比较变得非常方便。

示例代码

#include <iostream>
#include <string>

int main() {
    std::string str1 = "hello";
    std::string str2 = "world";

    if (str1 == str2) {
        std::cout << "strings are equal." << std::endl;
    } else {
        std::cout << "strings are not equal." << std::endl; // 输出:strings are not equal.
    }

    if (str1 < str2) {
        std::cout << "str1 is less than str2." << std::endl; // 输出:str1 is less than str2.
    }
}

总结

std::string 是 c++ stl 中一个非常强大且灵活的工具,它提供了丰富的功能来处理字符串,同时避免了许多传统字符串操作的常见问题。

通过掌握 std::string 的构造、操作、性能优化以及高级用法,你可以更高效地编写字符串处理相关的代码。

在实际开发中,合理使用 std::string 能够大大提高代码的可读性和安全性。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。

(0)

相关文章:

  • QT项目打包成EXE文件的实现步骤

    一、前言在使用 qt 开发完应用程序后,我们通常需要将其打包成可执行文件(exe),以便在没有安装 qt 开发环境的其他计算机上运行。本文将详细介绍如何将 qt 项目打包成独立的 …

    2025年06月05日 编程语言
  • C/C++和OpenCV实现调用摄像头

    C/C++和OpenCV实现调用摄像头

    opencv 是一个强大的计算机视觉库,它使得从摄像头捕获和处理视频流变得非常简单。本文将指导你如何使用 c/c++ 和 opencv 来调用摄像头、读取视频帧... [阅读全文]
  • c/c++的opencv椒盐噪声的实现

    c/c++的opencv椒盐噪声的实现

    椒盐噪声(salt-and-pepper noise),也称为脉冲噪声(impulse noise),是数字图像中常见的一种噪声类型。它的特点是在图像中随机出现... [阅读全文]
  • C/C++的OpenCV 进行图像梯度提取的几种实现

    C/C++的OpenCV 进行图像梯度提取的几种实现

    图像梯度表示图像中像素强度的变化率和方向。它是图像分析中的一个基本概念,广泛应用于边缘检测、特征提取和物体识别等任务。opencv 提供了多种计算图像梯度的函数... [阅读全文]
  • c/c++的opencv实现图片膨胀

    c/c++的opencv实现图片膨胀

    图像膨胀 (dilation) 是形态学图像处理中的另一种基本操作,与腐蚀操作相对应。它通常用于填充图像中的小孔洞、连接断开的物体部分、以及加粗二值图像中的物体... [阅读全文]
  • C++  RabbitMq消息队列组件详解

    1. rabbitmq介绍rabbitmq - 消息队列组件:实现两个客户端主机之间消息传输的功能(发布&订阅)。一端发布消息,一端订阅消息,消息就会被推送到订阅消息那一端…

    2025年05月29日 编程语言

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com