Bootstrap

c++——string详解

string简介

String 类

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

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

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

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

成员类型

value_typechar
traits_typechar_traits
allocator_typeallocator
referencechar&
const_referenceconst char&
pointerchar*
const_pointerconst char*
iteratora random access iterator to char (convertible to const_iterator)
const_iteratora random access iterator to const char
reverse_iteratorreverse_iterator
const_reverse_iteratorreverse_iterator<const_iterator>
difference_typeptrdiff_t
size_typesize_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++11及以后)
std::string str("Hello World", 5);  // 使用字符数组的一部分初始化

这种构造函数从一个字符数组的一部分或者一个迭代器范围内的内容来初始化 std::string 对象。

初始化列表构造函数(C++11及以后)
std::string str{'H', 'e', 'l', 'l', 'o'};  // 使用初始化列表初始化

这种构造函数从一个初始化列表来初始化 std::string 对象。

带分配器的构造函数
std::allocator<char> alloc;
std::string str(alloc);  // 使用分配器初始化

这种构造函数可以传入一个分配器来初始化 std::string 对象。

示例
#include <iostream>
#include <string>

int main() {
    // 默认构造函数
    std::string str1;  // str1 是空字符串

    // 字符串字面值和长度构造函数
    const char* cstr = "Hello";
    std::string str2(cstr);  // str2 是 "Hello"
    std::string str3(cstr, 3);  // str3 是 "Hel"

    // 复制构造函数
    std::string str4(str2);  // str4 是 "Hello"

    // 重复字符构造函数
    std::string str5(5, 'A');  // str5 是 "AAAAA"

    // 移动构造函数
    std::string str6 = std::move(str5);  // str6 是 "AAAAA",str5 可能为空

    // 区间构造函数
    std::string str7("Hello World", 5);  // str7 是 "Hello"

    // 初始化列表构造函数
    std::string str8{'H', 'e', 'l', 'l', 'o'};  // str8 是 "Hello"

    std::cout << "str1: " << str1 << std::endl;
    std::cout << "str2: " << str2 << std::endl;
    std::cout << "str3: " << str3 << std::endl;
    std::cout << "str4: " << str4 << std::endl;
    std::cout << "str5: " << str5 << std::endl;
    std::cout << "str6: " << str6 << std::endl;
    std::cout << "str7: " << str7 << std::endl;
    std::cout << "str8: " << str8 << std::endl;

    return 0;
}

析构函数

std::string 类型的析构函数在 C++ 标准库中定义,负责释放字符串对象所分配的内存。析构函数通常在对象生命周期结束时自动调用,用于清理对象占用的资源,包括内存、打开的文件等。

在 std::string 中,析构函数的实现通常是隐含的,也就是编译器会自动生成一个默认的析构函数。这个析构函数的任务是释放与字符串相关的内存,包括动态分配的字符数组和可能的辅助数据结构,如短字符串优化(SSO,Small String Optimization)所用的存储空间。

以下是一个简化的伪代码表示 std::string 的析构函数可能是如何实现的:

class string {
private:
    char* data;   // 指向存储字符串的动态数组
    size_t length; // 字符串长度
    size_t capacity; // 当前分配的容量

public:
    // 构造函数等其他成员函数

    ~string() {
        if (data != nullptr) {
            delete[] data; // 释放动态分配的字符数组
        }
    }
};

在这个示例中,析构函数检查 data 是否为 nullptr,如果不是,则使用 delete[] 操作符释放 data 指向的动态分配的字符数组。这确保在字符串对象生命周期结束时,其占用的内存得到释放,防止内存泄漏。

需要注意的是,现代的 C++ 标准库实现通常会使用更复杂的技术来管理字符串,包括小字符串优化和其他性能优化,但核心思想仍然是在适当的时候释放分配的资源。

赋值运算符重载std::string::operator=

语法结构

string (1)string& operator= (const string& str);
c-string (2)string& operator= (const char* s);
character (3)string& operator= (char c);
initializer list (4)string& operator= (initializer_list il);
move (5)string& operator= (string&& str) noexcept;

使用案例

(1)string& operator=(const string& str);

这是标准的赋值运算符重载,用于将一个 std::string 对象赋值给另一个 std::string 对象。它通过深拷贝来复制字符串内容。

示例

std::string str1 = "Hello";
std::string str2;
str2 = str1; // 使用重载的赋值运算符,将 str1 的内容赋给 str2

(2)string& operator=(const char* s);

这个赋值运算符重载允许将一个 C 字符串(以 null 结尾的字符数组)赋给 std::string 对象。它将 C 字符串中的内容复制到 std::string 对象中。

示例

std::string str;
const char* cstr = "World";
str = cstr; // 使用重载的赋值运算符,将 cstr 指向的字符串赋给 str

(3) string& operator=(char c);

这个赋值运算符重载允许将一个单个字符赋给 std::string 对象,这将创建一个包含该字符的单字符字符串。

示例

std::string str;
char ch = 'A';
str = ch; // 使用重载的赋值运算符,将字符 'A' 赋给 str,即 str 变成 "A"

(4) string& operator=(initializer_list<char> il);

这个赋值运算符重载允许使用初始化列表来赋值给 std::string 对象,初始化列表是一组用大括号 {} 括起来的元素。

示例

std::string str;
str = {'H', 'e', 'l', 'l', 'o'}; // 使用重载的赋值运算符,将初始化列表中的字符赋给 str,即 str 变成 "Hello"

(5)string& operator=(string&& str) noexcept;

这是移动赋值运算符重载,允许将右值引用的 std::string 对象移动到当前的 std::string 对象中。移动赋值通常比深拷贝更高效,因为它只是转移资源的所有权而不是复制整个内容。

示例

std::string str1 = "Hello";
std::string str2;
str2 = std::move(str1); // 使用移动赋值运算符,将 str1 的内容移动到 str2 中

迭代器函数

迭代器

  • begin() 和 end()

begin(): 返回一个迭代器,指向字符串的第一个字符。
end(): 返回一个迭代器,指向字符串末尾的下一个位置(即超出字符串的位置)。
示例:

std::string str = "Hello";
for (auto it = str.begin(); it != str.end(); ++it) {
    std::cout << *it << " ";
}
// 输出: H e l l o
  • rbegin() 和 rend()

rbegin(): 返回一个反向迭代器,指向字符串的最后一个字符。
rend(): 返回一个反向迭代器,指向字符串起始位置的前一个位置。
示例:

std::string str = "Hello";
for (auto it = str.rbegin(); it != str.rend(); ++it) {
    std::cout << *it << " ";
}
// 输出: o l l e H (反向输出字符串)
  • cbegin() 和 cend()

cbegin(): 返回一个常量迭代器,指向字符串的第一个字符。
cend(): 返回一个常量迭代器,指向字符串末尾的下一个位置。
示例:

std::string str = "Hello";
for (auto it = str.cbegin(); it != str.cend(); ++it) {
    std::cout << *it << " ";
}
// 输出: H e l l o
  • crbegin() 和 crend()

crbegin(): 返回一个常量反向迭代器,指向字符串的最后一个字符。
crend(): 返回一个常量反向迭代器,指向字符串起始位置的前一个位置。
示例:

std::string str = "Hello";
for (auto it = str.crbegin(); it != str.crend(); ++it) {
    std::cout << *it << " ";
}
// 输出: o l l e H (常量反向输出字符串)

示例解释

这些迭代器允许你以不同的方式遍历 std::string 对象的内容,包括正向和反向遍历,以及使用常量迭代器来保证数据不被修改。
使用迭代器的好处之一是可以与标准算法库中的算法一起使用,例如 std::find、std::sort 等,以对字符串进行各种操作和查找。

Capacity相关函数

1. size() 和 length()

size(): 返回字符串中字符的数量。
length(): 也返回字符串中字符的数量,与 size() 功能相同。
示例使用:

std::string str = "Hello";
std::cout << "Size of string: " << str.size() << std::endl;
std::cout << "Length of string: " << str.length() << std::endl;
// 输出:
// Size of string: 5
// Length of string: 5
2. max_size()

max_size(): 返回 std::string 可以包含的最大字符数。
示例使用:

std::string str = "Hello";
std::cout << "Max size of string: " << str.max_size() << std::endl;
// 输出实际上会根据系统和编译器的不同而有所变化
3. resize()

resize(new_size): 改变字符串的大小,如果新大小比当前大小大,则填充额外的字符;如果新大小小于当前大小,则截断字符串。

示例使用:

std::string str = "Hello";
str.resize(8, '!');
std::cout << "Resized string: " << str << std::endl;
// 输出: Resized string: Hello!!!
4. capacity()

capacity(): 返回字符串当前分配的存储容量,即能够保存的字符数而不需要重新分配内存的最大值。
示例使用:

std::string str = "Hello";
std::cout << "Capacity of string: " << str.capacity() << std::endl;
// 输出: Capacity of string: 15 (这只是一个示例,实际容量取决于实现)
5. reserve()

reserve(new_cap): 请求字符串预留足够的空间来容纳至少 new_cap 个字符。

示例使用:

std::string str;
str.reserve(20);
str = "Hello";
std::cout << "Capacity after reserve: " << str.capacity() << std::endl;
// 输出: Capacity after reserve: 20
6. clear()

clear(): 清空字符串,使其成为空字符串。

示例使用:

std::string str = "Hello";
str.clear();
std::cout << "String after clear: " << str << std::endl;
// 输出: String after clear: ""
7. empty()

empty(): 检查字符串是否为空。

示例使用:

std::string str = "Hello";
if (str.empty()) {
    std::cout << "String is empty." << std::endl;
} else {
    std::cout << "String is not empty." << std::endl;
}
// 输出: String is not empty.
8. shrink_to_fit()

shrink_to_fit(): 请求字符串减少其容量以适应其当前大小。

示例使用:

std::string str = "Hello";
str.reserve(20); // 假设之前进行了容量预留
str.shrink_to_fit();
std::cout << "Capacity after shrink_to_fit: " << str.capacity() << std::endl;
// 输出: Capacity after shrink_to_fit: 5 (实际效果依赖于具体实现)

注意事项

  • 性能影响:resize()、reserve() 和 shrink_to_fit() 可能会导致内存的重新分配,因此频繁调用这些函数可能会影响性能。
  • 字符串存储与容量:capacity() 返回的值可能大于 size(),因为字符串在内部可能有额外的空间用于预留和避免频繁重新分配。

访问字符串函数

在C++的 std::string 类中,有几种方法可以访问字符串中的字符,包括 operator[]、at()、back() 和 front()。下面逐一介绍它们的用法和示例。

1. operator[]

operator[]: 提供对字符串中单个字符的访问和修改,使用类似数组下标的方式访问。

示例使用:

std::string str = "Hello";
char ch = str[0]; // 访问第一个字符 'H'
str[1] = 'a';     // 修改第二个字符为 'a'
std::cout << "Modified string: " << str << std::endl;
// 输出: Modified string: Hallo
2. at()

at(pos): 提供对字符串中单个字符的访问和修改,使用位置索引 pos。

示例使用:

std::string str = "Hello";
char ch = str.at(0); // 访问第一个字符 'H'
str.at(1) = 'a';     // 修改第二个字符为 'a'
std::cout << "Modified string: " << str << std::endl;
// 输出: Modified string: Hallo
3. back()

back(): 返回字符串的最后一个字符,不修改字符串本身。

示例使用:

std::string str = "Hello";
char last = str.back(); // 获取最后一个字符 'o'
std::cout << "Last character: " << last << std::endl;
// 输出: Last character: o
4. front()

front(): 返回字符串的第一个字符,不修改字符串本身。

示例使用:

std::string str = "Hello";
char first = str.front(); // 获取第一个字符 'H'
std::cout << "First character: " << first << std::endl;
// 输出: First character: H

注意事项

  • 越界访问:operator[] 和 at() 在访问越界时会导致 std::out_of_range 异常的抛出,因此在访问之前最好先检查字符串的长度或使用异常处理。
  • 性能差异:operator[] 通常比 at() 更快,因为它不会进行边界检查,但可能更不安全。
  • 常用性:通常情况下,operator[] 是最常用的字符串访问方法,因为它简洁而直接。

重铸函数

operator+=

语法结构:

string& operator+=(const string& str);
string& operator+=(const char* s);
string& operator+=(char c);

案例:

string s = "Hello";
s += " World";
cout << s << endl; // 输出:Hello World

s += '!';
cout << s << endl; // 输出:Hello World!
append

语法结构:

string& append(const string& str);
string& append(const string& str, size_t subpos, size_t sublen);
string& append(const char* s);
string& append(const char* s, size_t n);
string& append(size_t n, char c);

案例:

string s = "Hello";
s.append(" World");
cout << s << endl; // 输出:Hello World

s.append(3, '!');
cout << s << endl; // 输出:Hello World!!!
push_back

语法结构:

void push_back(char c);

案例:

string s = "Hello";
s.push_back('!');
cout << s << endl; // 输出:Hello!
assign

语法结构:

string& assign(const string& str);
string& assign(const string& str, size_t subpos, size_t sublen);
string& assign(const char* s);
string& assign(const char* s, size_t n);
string& assign(size_t n, char c);

案例:

string s;
s.assign("Hello");
cout << s << endl; // 输出:Hello

s.assign(3, '!');
cout << s << endl; // 输出:!!!
insert

语法结构:

string& insert(size_t pos, const string& str);
string& insert(size_t pos, const string& str, size_t subpos, size_t sublen);
string& insert(size_t pos, const char* s);
string& insert(size_t pos, const char* s, size_t n);
string& insert(size_t pos, size_t n, char c);

案例:

string s = "Hello";
s.insert(5, " World");
cout << s << endl; // 输出:Hello World

s.insert(11, 3, '!');
cout << s << endl; // 输出:Hello World!!!
erase

语法结构:

string& erase(size_t pos = 0, size_t len = npos);
案例:
cpp
string s = "Hello World!";
s.erase(5, 6); // 从位置5开始删除6个字符
cout << s << endl; // 输出:Hello!
replace

语法结构:

string& replace(size_t pos, size_t len, const string& str);
string& replace(size_t pos, size_t len, const string& str, size_t subpos, size_t sublen);
string& replace(size_t pos, size_t len, const char* s);
string& replace(size_t pos, size_t len, const char* s, size_t n);
string& replace(size_t pos, size_t len, size_t n, char c);

案例:

string s = "Hello World!";
s.replace(6, 6, "there"); // 从位置6开始,删除6个字符并插入新字符串
cout << s << endl; // 输出:Hello there!
swap

语法结构:

void swap(string& str);

案例:

string s1 = "Hello";
string s2 = "World";
s1.swap(s2);
cout << s1 << " " << s2 << endl; // 输出:World Hello
pop_back

语法结构:

void pop_back();

案例:

string s = "Hello!";
s.pop_back(); // 删除最后一个字符
cout << s << endl; // 输出:Hello

返回C语言风格指针函数

c_str
const char* c_str() const noexcept;

返回一个指向包含字符串内容的常规 C 字符串 (const char*),以空字符结尾。
这个函数通常用于需要传递 C 风格字符串(例如给 C 函数调用)的场景。

示例

#include <iostream>
#include <string>

int main() {
    std::string str = "Hello, world!";
    const char* cstr = str.c_str();

    std::cout << "C-style string: " << cstr << std::endl;

    return 0;
}
data
const char* data() const noexcept;

返回一个指向字符串内容的常规字符数组 (const char*),不一定以空字符结尾。

与 c_str 相似,但 data 不保证以空字符结尾,因此更适合处理可能包含空字符的数据。

示例

#include <iostream>
#include <string>

int main() {
    std::string str = "Hello, world!";
    const char* rawData = str.data();

    std::cout << "Raw data: " << rawData << std::endl;

    return 0;
}

截取函数与比较函数

substr
string substr(size_type pos = 0, size_type count = npos) const;

返回从 pos 开始,包含 count 个字符的子字符串。
如果 count 超出字符串长度,子串将从 pos 到末尾。

示例

#include <iostream>
#include <string>

int main() {
    std::string str = "Hello, world!";
    std::string substr = str.substr(7, 5);  // 从位置 7 开始,长度为 5

    std::cout << "Substring: " << substr << std::endl;  // 输出:Substring: world

    return 0;
}
compare
int compare(const string& str) const noexcept;
int compare(size_type pos, size_type count, const string& str) const;
int compare(size_type pos, size_type count, const string& str, size_type pos2, size_type count2) const;
int compare(const char* s) const;

比较当前字符串与给定字符串 str 或字符数组 s。
返回值小于、等于或大于零,表示当前字符串小于、等于或大于参数字符串。

示例

#include <iostream>
#include <string>

int main() {
    std::string str1 = "apple";
    std::string str2 = "banana";

    int result = str1.compare(str2);

    if (result == 0) {
        std::cout << "Strings are equal." << std::endl;
    } else if (result < 0) {
        std::cout << "str1 is less than str2." << std::endl;
    } else {
        std::cout << "str1 is greater than str2." << std::endl;
    }

    return 0;
}

find函数

在C++中,std::string 类型提供了几种用于查找子字符串的函数,其中最常用的是 find 和 find_first_of。这些函数允许你在一个字符串中查找另一个子字符串或特定字符的位置。

find 函数

find 函数用于在主字符串中查找子字符串第一次出现的位置。它的语法如下:

size_t find(const string& str, size_t pos = 0) const noexcept;

str 是要查找的子字符串。
pos 是可选参数,指定查找的起始位置,默认为0。

示例

#include <iostream>
#include <string>

int main() {
    std::string sentence = "Hello, how are you?";
    size_t found = sentence.find("how");

    if (found != std::string::npos) {
        std::cout << "Found 'how' at position: " << found << std::endl;  // 输出:Found 'how' at position: 7
    } else {
        std::cout << "'how' not found." << std::endl;
    }

    return 0;
}

在上面的示例中,find(“how”) 将会返回子字符串 “how” 在 sentence 中第一次出现的位置索引。

find_first_of 函数

find_first_of 函数用于在主字符串中查找包含在另一个字符串(或字符集合)中的任何字符第一次出现的位置。它的语法如下:

size_t find_first_of(const string& str, size_t pos = 0) const noexcept;

str 是要查找的字符集合。
pos 是可选参数,指定查找的起始位置,默认为0。

示例

#include <iostream>
#include <string>

int main() {
    std::string sentence = "Hello, how are you?";
    size_t found = sentence.find_first_of("aeiou");

    if (found != std::string::npos) {
        std::cout << "Found vowel at position: " << found << std::endl;  // 输出:Found vowel at position: 1 (for 'e')
    } else {
        std::cout << "No vowels found." << std::endl;
    }

    return 0;
}

在上面的示例中,find_first_of(“aeiou”) 将会返回第一个元音字母(a, e, i, o, u)在 sentence 中出现的位置索引。

返回值说明

  • 如果找到了子字符串或字符集合,find 函数将返回该子字符串或字符集合第一次出现的索引。
  • 如果没有找到,这些函数会返回 std::string::npos,它是 size_t 类型的特殊常量,表示没有找到匹配项。
;