开发者

C++之STL--string的使用

开发者 https://www.devze.com 2025-06-04 10:50 出处:网络 作者: zzh_zao
目录深入探索 C++ STL 中的 std::string一、std::string 的基本概念二、std::string 的构造与初始化三、std::string 的常用操作四.string类对象的访问及遍历操作std::string的容量相关概念reserve:预留内存shrink_t
目录
  • 深入探索 C++ STL 中的 std::string
  • 一、std::string 的基本概念
  • 二、std::string 的构造与初始化
  • 三、std::string 的常用操作
  • 四.string类对象的访问及遍历操作
    • std::string的容量相关概念
    • reserve:预留内存
    • shrink_to_fit:收缩内存
    • resize:调整字符串大小
    • 容量操作的性能优化
  • 五.string类对象的修改操作
    • std::string的修改操作概述
    • 直接修改字符
    • 插入操作
    • 删除操作
    • 替换操作
    • 追加操作
    • 清空字符串
    • 使用std::stringstream进行复杂修改
  • 六.string类非成员函数
    • 什么是std::string的非成员函数?
    • 常见的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 提供了多种构造方式,可以根据不同python的需求选择合适的构造函数。

    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 (inwww.devze.comt 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会改变字符串的内容,而reserve编程客栈shrink_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 能够大大提高代码的可读性和安全性。

    以上为个人经验,希望能给大家一个参考,也希望大家多多支持编程客栈(www.devze.com)。

    0

    精彩评论

    暂无评论...
    验证码 换一张
    取 消

    关注公众号