std::string 是 C++ 标准模板库(STL)中一个非常强大和常用的类,用于处理字符串。下面我将详细介绍 std::string 的全部使用语法。
在这里插入图片描述


1. 头文件与基本定义

要使用 std::string,必须包含 <string> 头文件。

#include <iostream>
#include <string>

// C++11 之后,可以使用 using 简化书写
using std::string;

2. 构造与初始化

创建 std::string 对象有多种方式。

语法 说明 示例
string s; 默认构造:创建一个空字符串。 string s1;
string s(str); 拷贝构造:用另一个 string 对象 str 初始化。 string s2(s1);
string s("hello"); 用 C 风格字符串(const char*)初始化。 string s3("Hello, World!");
string s("hello", n); 用 C 风格字符串的前 n 个字符初始化。 string s4("Hello, World!", 5); // s4 为 "Hello"
string s(n, 'c'); n 个字符 'c' 来初始化。 string s5(10, '='); // s5 为 "=========="
string s(s2, pos); 用 string 对象 s2 从索引 pos 开始到末尾的子串初始化。 string s6(s3, 7); // s6 为 "World!"
string s(s2, pos, len); 用 string 对象 s2 从索引 pos 开始,长度为 len 的子串初始化。 string s7(s3, 0, 5); // s7 为 "Hello"
string s(iter1, iter2); 用迭代器区间 [iter1, iter2) 的内容初始化。 string s8(s3.begin(), s3.begin() + 5); // s8 为 "Hello"
string s = "hello"; 赋值初始化,等同于 string s("hello"); string s9 = "direct assignment";
string s {'h','e','l','l','o'}; 初始化列表 (C++11)。 string s10 {'a', 'b', 'c'}; // s10 为 "abc"

示例代码:

#include <iostream>
#include <string>

int main() {
    // 默认构造
    std::string s1;
    std::cout << "s1 (default): \"" << s1 << "\"\n";

    // C-style string
    std::string s2("Hello C++");
    std::cout << "s2 (from C-string): \"" << s2 << "\"\n";

    // 拷贝构造
    std::string s3(s2);
    std::cout << "s3 (copy from s2): \"" << s3 << "\"\n";

    // n 个字符 'c'
    std::string s4(5, 'A');
    std::cout << "s4 (from 5 'A's): \"" << s4 << "\"\n";

    // 从另一个 string 的子串
    std::string s5(s2, 6, 3); // 从 s2 的索引 6 开始,长度为 3
    std::cout << "s5 (substring of s2): \"" << s5 << "\"\n";

    return 0;
}

3. 容量管理

这些函数用于查询或管理字符串的存储空间。

函数 说明 示例
s.size() / s.length() 返回字符串中字符的个数(两者功能完全相同)。 int len = s.length();
s.capacity() 返回在不重新分配内存的情况下,字符串可以容纳的字符数。 int cap = s.capacity();
s.max_size() 返回字符串可能达到的最大长度。 size_t maxSize = s.max_size();
s.resize(n) 改变字符串大小为 n。如果 n > size(),则用空字符填充;如果 n < size(),则截断。 s.resize(20);
s.resize(n, 'c') 改变大小为 n,若 n > size(),则用字符 'c' 填充。 s.resize(20, ' ');
s.reserve(n) 预留至少能存储 n 个字符的内存空间。这不改变 size(),只影响 capacity() s.reserve(100);
s.clear() 清空字符串内容,使其变为空字符串 (size() 变为 0)。 s.clear();
s.empty() 判断字符串是否为空,等价于 s.size() == 0 if (s.empty()) { ... }
s.shrink_to_fit() (C++11) 将 capacity() 减少到与 size() 相同的大小,释放多余内存。 s.shrink_to_fit();

示例代码:

#include <iostream>
#include <string>

int main() {
    std::string s = "Hello";
    std::cout << "Initial string: \"" << s << "\"\n";
    std::cout << "size(): " << s.size() << "\n";
    std::cout << "capacity(): " << s.capacity() << "\n";

    s.reserve(50);
    std::cout << "\nAfter reserve(50):\n";
    std::cout << "size(): " << s.size() << "\n";
    std::cout << "capacity(): " << s.capacity() << "\n";

    s.resize(10);
    std::cout << "\nAfter resize(10):\n";
    std::cout << "s: \"" << s << "\"\n";
    std::cout << "size(): " << s.size() << "\n";

    s.shrink_to_fit();
    std::cout << "\nAfter shrink_to_fit():\n";
    std::cout << "capacity(): " << s.capacity() << "\n";

    s.clear();
    std::cout << "\nAfter clear(), is empty? " << (s.empty() ? "Yes" : "No") << "\n";

    return 0;
}

4. 元素访问

如何访问字符串中的单个字符。

语法 说明
s[i] 下标运算符 []:返回索引 i 处的字符的引用。不进行边界检查
s.at(i) at() 函数:返回索引 i 处的字符的引用。会进行边界检查,如果越界会抛出 std::out_of_range 异常。
s.front() 返回第一个字符的引用。
s.back() 返回最后一个字符的引用。
s.c_str() 返回一个指向以空字符 \0 结尾的 C 风格字符串的指针 (const char*)。
s.data() c_str() 类似,但不保证一定以 \0 结尾(C++11之后保证)。

示例代码:

#include <iostream>
#include <string>
#include <stdexcept>

int main() {
    std::string s = "World";

    // 使用 []
    s[0] = 'w';
    std::cout << "Using []: " << s << "\n"; // "world"

    // 使用 at()
    try {
        s.at(1) = 'O';
        std::cout << "Using at(): " << s << "\n"; // "wOrld"
        char c = s.at(10); // 越界,会抛出异常
    } catch (const std::out_of_range& e) {
        std::cerr << "Exception caught: " << e.what() << '\n';
    }

    std::cout << "front(): " << s.front() << "\n";
    std::cout << "back(): " << s.back() << "\n";

    // 转换为 C 风格字符串
    const char* c_str = s.c_str();
    printf("C-style string: %s\n", c_str);

    return 0;
}

5. 迭代器

用于遍历字符串,行为类似于指针。

函数 说明
s.begin() 返回指向字符串第一个字符的正向迭代器。
s.end() 返回指向字符串末尾(最后一个字符的下一个位置)的正向迭代器。
s.rbegin() 返回指向字符串最后一个字符的反向迭代器。
s.rend() 返回指向字符串开头(第一个字符的前一个位置)的反向迭代器。
s.cbegin(), s.cend() (C++11) const 版本的 begin()end()
s.crbegin(), s.crend() (C++11) const 版本的 rbegin()rend()

示例代码:

#include <iostream>
#include <string>
#include <algorithm> // for std::for_each

int main() {
    std::string s = "Example";

    // 正向遍历
    std::cout << "Forward iteration: ";
    for (auto it = s.begin(); it != s.end(); ++it) {
        std::cout << *it;
    }
    std::cout << "\n";

    // 反向遍历
    std::cout << "Reverse iteration: ";
    for (auto it = s.rbegin(); it != s.rend(); ++it) {
        std::cout << *it;
    }
    std::cout << "\n";
    
    // C++11 范围 for 循环 (内部使用了迭代器)
    std::cout << "Range-based for loop: ";
    for (char c : s) {
        std::cout << c;
    }
    std::cout << "\n";

    return 0;
}

6. 内容修改

函数 说明
s += str operator+=:在字符串末尾追加 str(可以是 stringconst char*char)。
s.append(...) append:重载版本丰富,功能与 += 类似,可以在末尾追加 string、C 风格字符串、字符等。
s.push_back(c) 在字符串末尾追加一个字符 c
s.pop_back() (C++11) 删除字符串的最后一个字符。
s.assign(...) assign:赋新值,会替换掉原有内容。重载版本丰富。
s.insert(pos, ...) insert:在索引 pos 处插入内容。可插入 string、C 风格字符串、字符等。
s.erase(pos, len) erase:删除从索引 pos 开始,长度为 len 的子串。
s.replace(pos, len, ...) replace:将从 pos 开始,长度为 len 的子串替换为新内容。
s1.swap(s2) 交换两个 string 对象的内容。

示例代码:

#include <iostream>
#include <string>

int main() {
    std::string s = "Hello";
    
    // 追加
    s += " World"; // s: "Hello World"
    s.push_back('!'); // s: "Hello World!"
    std::cout << "After append: " << s << "\n";

    // 插入
    s.insert(6, "Beautiful "); // s: "Hello Beautiful World!"
    std::cout << "After insert: " << s << "\n";

    // 替换
    s.replace(6, 9, "Cruel"); // s: "Hello Cruel World!"
    std::cout << "After replace: " << s << "\n";

    // 删除
    s.erase(6, 6); // s: "Hello World!"
    std::cout << "After erase: " << s << "\n";

    // 交换
    std::string s2 = "C++";
    s.swap(s2);
    std::cout << "s is now: " << s << ", s2 is now: " << s2 << "\n";

    return 0;
}

7. 字符串操作

查找

查找函数返回找到的子串或字符的起始索引。如果找不到,则返回 std::string::npos (一个特殊的静态常量)。

函数 说明
s.find(str, pos=0) 从索引 pos 开始,正向查找子串 str 第一次出现的位置。
s.rfind(str, pos=npos) 从索引 pos 开始,反向查找子串 str 最后一次出现的位置。
s.find_first_of(chars, pos=0) pos 开始,查找 chars任意一个字符首次出现的位置。
s.find_last_of(chars, pos=npos) pos 开始,反向查找 chars任意一个字符最后一次出现的位置。
s.find_first_not_of(chars, pos=0) pos 开始,查找不属于 chars 的第一个字符的位置。
s.find_last_not_of(chars, pos=npos) pos 开始,反向查找不属于 chars 的第一个字符的位置。
比较
函数/运算符 说明
s1.compare(s2) 字典序比较。返回 0 (相等), <0 (s1 < s2), >0 (s1 > s2)。
==, !=, <, >, <=, >= 重载的比较运算符,直接进行字典序比较,更直观。
子串
函数 说明
s.substr(pos=0, len=npos) 返回一个新的 string 对象,内容是原字符串从 pos 开始,长度为 len 的子串。

示例代码:

#include <iostream>
#include <string>

int main() {
    std::string text = "The quick brown fox jumps over the lazy dog.";
    std::string::size_type pos;

    // find
    pos = text.find("fox");
    if (pos != std::string::npos) {
        std::cout << "\"fox\" found at index: " << pos << "\n";
    }

    // find_first_of (查找元音字母)
    pos = text.find_first_of("aeiou");
    if (pos != std::string::npos) {
        std::cout << "First vowel found at index: " << pos << "\n";
    }
    
    // compare
    std::string s1 = "abc", s2 = "abd";
    if (s1.compare(s2) < 0) {
        std::cout << s1 << " is less than " << s2 << "\n";
    }
    // 更常用的方式
    if (s1 < s2) {
        std::cout << s1 << " is less than " << s2 << "\n";
    }

    // substr
    std::string sub = text.substr(4, 5); // 从索引4开始,长度为5
    std::cout << "Substring: \"" << sub << "\"\n"; // "quick"

    return 0;
}

8. 输入/输出 (I/O)

语法 说明
std::cin >> s 从标准输入读取一个字符串,遇到空白符(空格、制表符、换行符)停止。
std::cout << s 将字符串 s 输出到标准输出。
std::getline(cin, s) cin 读取一行,直到遇到换行符为止。换行符会被读取并丢弃。
std::getline(cin, s, delim) cin 读取,直到遇到分隔符 delim 为止。delim 会被读取并丢弃。

示例代码:

#include <iostream>
#include <string>

int main() {
    std::string word, line;

    std::cout << "Enter a single word: ";
    std::cin >> word;
    std::cout << "You entered: " << word << "\n";

    // 清除输入缓冲区中剩余的换行符
    std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); 

    std::cout << "Enter a full line: ";
    std::getline(std::cin, line);
    std::cout << "You entered: " << line << "\n";

    return 0;
}

9. 数值转换 (C++11)

C++11 在 <string> 头文件中提供了一组方便的函数,用于在字符串和数值类型之间进行转换。

函数 说明
std::to_string(val) 将各种数值类型(int, double 等)转换为 std::string
std::stoi(s, &pos, base) 将字符串 s 转换为 int
std::stol(s, ...) 转换为 long
std::stoll(s, ...) 转换为 long long
std::stoul(s, ...) 转换为 unsigned long
std::stoull(s, ...) 转换为 unsigned long long
std::stof(s, ...) 转换为 float
std::stod(s, ...) 转换为 double
std::stold(s, ...) 转换为 long double

sto* 系列函数参数说明:

  • s: 要转换的字符串。

  • &pos (可选): 一个 size_t 指针,用于存储转换过程中处理的字符数。

  • base (可选): 转换的基数 (如 10, 16, 8)。

示例代码:

#include <iostream>
#include <string>

int main() {
    // 数值转字符串
    double pi = 3.14159;
    std::string pi_str = std::to_string(pi);
    std::cout << "pi as string: " << pi_str << "\n";

    // 字符串转数值
    std::string num_str = "42 is the answer";
    try {
        size_t processed_chars;
        int num = std::stoi(num_str, &processed_chars);
        std::cout << "Parsed number: " << num << "\n";
        std::cout << "Characters processed: " << processed_chars << "\n";
        std::cout << "Remaining string: " << num_str.substr(processed_chars) << "\n";
    } catch (const std::invalid_argument& e) {
        std::cerr << "Invalid argument: " << e.what() << '\n';
    } catch (const std::out_of_range& e) {
        std::cerr << "Out of range: " << e.what() << '\n';
    }

    return 0;
}

原本打算将上一篇(数组),这篇和下一篇(指针)放在一起的,但是将知识点稍微拆散一点会显得没那么笨重,所以我后面的笔记还是控制在 3000 字以内(不含代码)。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐