c++——string详解

string简介

String 类

string是表示字符序列的对象, 与普通的char*不一样,本质上是一个类,内部封装了各种函数

标准字符串类通过类似于标准字节容器的接口为此类对象提供支持,但添加了专门设计用于处理单字节字符字符串的功能。

字符串类是 basic_string 类模板的实例化,它使用 char(即字节)作为其字符类型,以及其默认的 char_traits 和分配器类型(有关模板的更多信息,请参阅basic_string)。

请注意,此类处理字节与所使用的编码无关:如果用于处理多字节或可变长度字符(如 UTF-8)的序列,则此类的所有成员(如长度或大小)及其迭代器仍将根据字节(而不是实际编码字符)进行操作。

成员类型

value_type char
traits_type char_traits
allocator_type allocator
reference char&
const_reference const char&
pointer char*
const_pointer const char*
iterator a random access iterator to char (convertible to const_iterator)
const_iterator a random access iterator to const char
reverse_iterator reverse_iterator
const_reverse_iterator reverse_iterator<const_iterator>
difference_type ptrdiff_t
size_type size_t

迭代器(Iterator)

迭代器(Iterator)是一种设计模式,用于提供一种方法来访问容器(如数组、集合、列表等)中的元素,而不暴露其底层表示。在C++中,迭代器被广泛应用于标准库中的各种容器,如 vector、list、map 等,以及其他数据结构。它们提供了一种统一的方式来遍历容器中的元素,并允许对容器中的元素进行读写操作。

迭代器的原理:

迭代器的类型名是iterator,本质上是一个类,也可以看作一个指针么,使用迭代器要加上域名比如string::iterator。

调用迭代器的函数为 .begin()返回相当于头指针的迭代器, .end()返回相当于指向尾部元素下一个位置的指针,这个不可访问数据,用来当终止条件。

迭代器实际上是一种指向容器元素的对象,它允许逐个访问容器的元素,并且支持对容器元素的操作。迭代器一般提供以下几种操作:

解引用(Dereferencing): 通过迭代器访问容器中的元素值。
递增(Incrementing): 将迭代器指向下一个元素。
比较(Comparing): 比较两个迭代器的位置关系,例如判断是否相等或大小关系。

迭代器的实现原理基于面向对象的设计,通过重载运算符来实现上述操作,例如 * 运算符用于解引用,++ 运算符用于递增迭代器。

注意事项:

失效问题: 在使用迭代器遍历容器时,若容器发生了增删操作,可能会导致迭代器失效(invalidated)。失效的迭代器不能再被使用,因此在进行插入或删除操作后,通常需要更新迭代器或者小心使用。

范围控制: 确保迭代器在有效的范围内操作,避免越界访问容器。

可变性问题: 不同类型的迭代器可能对容器的可变性有不同的影响。例如,使用 const_iterator 可以确保不修改容器元素。

迭代器类型: 不同的容器可能提供不同类型的迭代器,如正向迭代器、逆向迭代器等,应根据需要选择合适的迭代器类型。

示例:

以下是一个简单的示例,演示如何使用迭代器遍历和修改一个 vector 容器中的元素:

#include <iostream>
#include <vector>

using namespace std;

int main() {
   
    string s = "123456789";

    // 使用迭代器遍历并输出元素
    cout << "Original vector: ";
    for (auto it = numbers.begin(); it != numbers.end(); ++it) {
   
        cout << *it << " ";
    }
    cout << endl;

    // 使用迭代器修改元素
    for (string::iterator it = numbers.begin(); it != numbers.end(); ++it) {
   
        *it *= 2;
    }

    // 再次遍历输出修改后的元素
    cout << "Modified vector: ";
    for (auto it = numbers.begin(); it != numbers.end(); ++it) {
   
        cout << *it << " ";
    }
    cout << endl;

    return 0;
}

在这个例子中,我们使用 vector 的迭代器 begin() 和 end() 来遍历容器中的元素,并且通过解引用迭代器 *it 来修改元素的值。这个例子展示了迭代器的基本用法和注意事项。

自动类型推导auto

自动类型推导(Automatic Type Deduction)是C++11引入的特性,通过关键字 auto 来实现。它允许编译器根据变量的初始化表达式推断出其类型,而无需显式地指定类型名。这种特性的引入使得代码更加简洁和易于维护,尤其是在处理复杂的模板类型时尤为有用。

使用场景和语法

在以下几种情况下,可以使用 auto 进行类型推导:

变量声明和初始化

auto x = 5; // 推导为 int
auto pi = 3.14; // 推导为 double
auto name = "John"; // 推导为 const char*

在这些示例中,编译器会根据右侧的初始化表达式推断出变量的类型。

函数返回类型推导(C++14)

auto add(int a, int b) {
   
    return a + b; // 推导为 int
}

函数的返回类型可以使用 auto,编译器会根据函数体中的返回语句推断返回类型。

迭代器和泛型编程

std::vector<int> numbers = {
   1, 2, 3, 4, 5};
for (auto it = numbers.begin(); it != numbers.end(); ++it) {
   
    // *it 推断为 int&
    std::cout << *it << " ";
}

在迭代器等泛型编程中,使用 auto 可以简化代码,特别是当容器的类型较复杂或是使用了模板时。

注意事项

类型推导的准确性: auto 推导的类型与初始化表达式密切相关,例如 auto x = 5; 推导为 int,而 auto y = 5.0; 推导为 double。

可读性和维护性: 尽管 auto 可以简化代码,但有时显式指定类型可以增强代码的可读性和维护性,特别是在函数签名和复杂表达式中。

初始化表达式的重要性: 类型推导依赖于变量的初始化,如果初始化表达式改变,推导出的类型也会相应改变。

避免过度使用: 在代码可读性受影响或需要强调类型时,应避免过度使用 auto。

示例

下面是一个结合了多种情况的示例:

#include <iostream>
#include <vector>

int main() {
   
    auto num = 10; // 推导为 int
    auto name = "Alice"; // 推导为 const char*

    std::vector<double> values = {
   1.2, 3.4, 5.6};
    for (auto it = values.begin(); it != values.end(); ++it) {
   
        // *it 推导为 double&
        std::cout << *it << " ";
    }
    std::cout << std::endl;

    auto sum = [](int a, int b) {
    return a + b; }; // 推导为 int

    return 0;
}

string中的常用函数

构造函数

在c++11中总共有这些个构造函数

default (1) string();
copy (2) string (const string& str);
substring (3) string (const string& str, size_t pos, size_t len = npos);
from c-string (4) string (const char* s);
from buffer (5) string (const char* s, size_t n);
fill (6) string (size_t n, char c);
range (7) template string (InputIterator first, InputIterator last);
initializer list (8) string (initializer_list il);
move (9) string (string&& str) noexcept;

npos小知识

npos 是C++标准库中的一个静态成员常量,通常用于表示字符串和容器类中的无效或末尾位置。具体来说:

  • 对于 std::string 类型,npos 是 std::string::npos,它表示字符串的末尾位置或者无效位置。
  • 对于 std::vector、std::deque 等容器,也有类似的静态成员常量表示末尾或无效位置。

在实际使用中,npos 的值通常是一个很大的正整数,用来表示找不到或者无效的位置。例如,对于 std::string,npos 的值通常是 std::string::npos,这个值在大多数实现中是 -1,但是它是无符号数,因此实际的二进制值是 std::string::npos。

使用案例

默认构造函数

cpp
std::string str; // 创建一个空字符串
这种形式的构造函数创建一个空的字符串对象。

字符串字面值和长度构造函数

cpp
const char* cstr = “Hello”;
std::string str(cstr); // 使用C风格字符串初始化
std::string str(cstr, 3); // 使用部分C风格字符串初始化
这种构造函数接受一个 C 风格字符串 const char* 或者一个部分C风格字符串和长度,用于初始化 std::string 对象。

复制构造函数
std::string str1("Hello");
std::string str2(str1);  // 使用另一个字符串对象初始化

这种构造函数使用同类型的另一个 std::string 对象来初始化新的对象。

重复字符构造函数
std::string str(5, 'A');  // 创建包含5个'A'字符的字符串

这种构造函数创建一个由指定数量重复字符组成的字符串。

移动构造函数(C++11及以后)
std::string str1 = "Hello";
std::string str2 = std::move(str1);  // 使用移动语义来初始化str1 可能被置为空

这种构造函数使用移动语义来初始化一个新的 std::string 对象,通常用于转移资源所有权,提高性能

### C++ 中 `string` 类的详细介绍 #### 头文件与命名空间 为了使用 `string` 类,程序中必须包含特定的头文件并声明相应的命名空间。 ```cpp #include <string> using namespace std; ``` 这确保了后续代码能够识别和利用 `string` 的功能[^4]。 #### 基本概念 `string` 是 C++ 标准模板库的一部分,专门用于处理字符序列。它提供了丰富的接口来简化字符串的操作,比如创建、修改、查询等。相较于传统的C风格字符串(即以null结尾的字符数组),`string` 提供了更安全便捷的方法来进行各种操作,并且内置了许多实用的功能[^1]。 #### 创建与初始化 可以通过多种方式定义一个 `string` 变量: - 默认构造函数:`string str;` - 使用常量字符串初始化:`string greeting = "Hello";` - 拷贝另一个已存在的 `string` 对象:`string copyStr(str);` 这些不同的构造形式使得开发者可以根据实际需求灵活地构建所需的字符串对象。 #### 字符串连接 不同于C语言中的复杂指针运算或调用特定API实现字符串拼接,在C++里可以直接运用加号(`+`)完成两个甚至多个字符串之间的串联工作。 ```cpp string firstPart = "Good"; string secondPart = "Morning!"; string wholeSentence = firstPart + ", " + secondPart; // 结果为:"Good, Morning!" ``` 这种直观易懂的方式极大地提高了开发效率和可读性[^2]。 #### 访问单个字符 对于某些场景下需要逐字访问的情况,`string` 支持两种主要途径——索引运算符[] 和成员函数at() 。其中后者会在越界时抛出异常,从而提供更强的安全保障机制。 ```cpp const string sampleText("example"); char ch1 = sampleText[0]; // e try { char ch2 = sampleText.at(7); // 抛出out_of_range异常 } catch(const out_of_range& oor) { cerr << "Out of Range error: " << oor.what(); } ``` 此特性有助于防止潜在错误的发生,增强了应用程序稳定性[^3]。 #### 文件及其他I/O操作的支持 除了基本的数据结构属性外,`string` 还兼容标准输入输出流以及其他高级IO设施,允许直接向控制台打印或者从磁盘读取写入文本数据而无需额外转换过程。 ---
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值