news 2026/5/6 18:56:15

C++ STL string 用法详解与示例

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
C++ STL string 用法详解与示例

目录

引言

1. 字符串的创建和初始化

2. 字符串基本操作

2.1 获取字符串信息

2.2 访问和修改字符

3. 字符串修改操作

3.1 追加字符串

3.2 插入字符串

3.3 删除字串内容

3.4 替换字符串

4. 字符串查找和子字符串

4.1 查找操作

4.2 提取子字符串

5. 字符串比较

6. 字符串与数值转换

6.1 数值转换为字符串

6.2 字符串转换为数值

7. 字符串输入输出

7.1 输入输出操作

8. 其他有用操作

8.1 调整字符串大小

8.2 字符串交换


引言

在C++编程中,字符串处理是日常开发中必不可少的一部分。C++标准模板库(STL)中的string类提供了强大而灵活的字符串操作功能,相比传统的C风格字符串(字符数组),string更加安全、易用且功能丰富。本文将详细介绍string类的常用方法,并通过实际示例展示其用法。

1. 字符串的创建和初始化

#include <iostream> #include <string> int main() { // 1. 默认构造函数,创建空字符串 std::string str1; // 2. 使用C风格字符串初始化 std::string str2 = "Hello, World!"; std::string str3("Hello, C++"); // 3. 使用另一个string对象初始化 std::string str4(str3); std::string str5 = str2; // 4. 使用部分字符序列初始化 std::string str6("Hello, World!", 5); // 只取前5个字符: "Hello" // 5. 使用多个相同字符初始化 std::string str7(10, '*'); // "**********" // 6. 使用迭代器初始化 std::string str8(str2.begin(), str2.begin() + 5); // "Hello" std::cout << str1 << std::endl; std::cout << str2 << std::endl; std::cout << str3 << std::endl; std::cout << str4 << std::endl; std::cout << str5 << std::endl; std::cout << str6 << std::endl; std::cout << str7 << std::endl; std::cout << str8 << std::endl; return 0; }

结果:

2. 字符串基本操作

2.1 获取字符串信息

#include <iostream> #include <string> int main() { std::string str = "Hello, C++ STL!......"; // 获取字符串长度 std::cout << "Length: " << str.length() << std::endl; std::cout << "Size: " << str.size() << std::endl; std::cout << "Capacity: " << str.capacity() << std::endl; // 检查字符串是否为空 std::string emptyStr; std::cout << "Is empty? " << emptyStr.empty() << std::endl; // 1 (true) std::cout << "Is str empty? " << str.empty() << std::endl; // 0 (false) // 获取C风格字符串 const char* cstr = str.c_str(); std::cout << "C-string: " << cstr << std::endl; return 0; }

结果:

补充:

1. size()和length()在功能上完全相同,它们都返回字符串当前包含的字符数。

为什么有两个相同的函数?

string类的诞生是早于STL容器的,早期的string类用length来表示字符数,后来为了与STL容器接口保持一致,所以添加了size()函数,我个人更推荐使用size(),既方便记忆,也更能体现STL容器设计理念的一致性。

2. capacity()返回的是当前为字符串分配的内存空间(以字符数为单位),这个空间可以容纳的字符数。这个值通常大于或等于size()

当向字符串添加字符时,如果size()小于capacity(),则不需要重新分配内存。只有当size()达到capacity()时,再添加字符就会触发内存重新分配,增加capacity(),以便容纳更多的字符。

为了减少重新分配内存所造成的性能开销,通常扩容的逻辑为按原来容量的1.5倍到2倍进行扩容。

3.c_str()的存在打通了C语言的字符串与C++字符串之间的隔阂,实现了向下兼容,事实上string类的底层就是管理了一个动态数组,c_str()就是返回这个数组的首元素地址。

2.2 访问和修改字符

#include <iostream> #include <string> int main() { std::string str = "Hello"; // 使用下标访问 std::cout << "str[0] = " << str[0] << std::endl; // 'H' std::cout << "str[1] = " << str[1] << std::endl; // 'e' // 使用at()访问(会检查边界) std::cout << "str.at(2) = " << str.at(2) << std::endl; // 'l' // 修改字符 str[0] = 'h'; str.at(1) = 'E'; std::cout << "After modification: " << str << std::endl; // "hello" // 获取第一个和最后一个字符 std::cout << "Front: " << str.front() << std::endl; // 'h' std::cout << "Back: " << str.back() << std::endl; // 'o' return 0; }

结果:

补充:

1. at()访问元素和[]访问元素的核心区别总结

特性

operator[](str[index])

at()(str.at(index))

边界检查

不进行边界检查

进行边界检查

越界行为

未定义行为(可能导致崩溃)

抛出std::out_of_range异常

性能

更高效(无检查开销)

稍慢(有检查开销)

适用场景

已知索引安全的快速访问

需要安全检查的情况

异常安全

不抛出异常

抛出异常

3. 字符串修改操作

3.1 追加字符串

#include <iostream> #include <string> int main() { std::string str = "Hello"; // 使用+=运算符 str += ", World"; std::cout << "After +=: " << str << std::endl; // "Hello, World" // 使用append()函数 str.append("!"); std::cout << "After append: " << str << std::endl; // "Hello, World!" str.append(" Welcome to C++", 9); // 只追加前9个字符 std::cout << "After append with length: " << str << std::endl; // "Hello, World! Welcome" // 追加多个相同字符 str.append(3, '!'); std::cout << "After append chars: " << str << std::endl; // "Hello, World! Welcome!!!" return 0; }

结果:

3.2 插入字符串

#include <iostream> #include <string> int main() { std::string str = "Hello World!"; // 在指定位置插入 str.insert(6, "Beautiful "); std::cout << "After insert: " << str << std::endl; // "Hello Beautiful World!" // 插入部分字符串 std::string insertStr = "Amazing and "; str.insert(6, insertStr, 0, 8); // 从insertStr的第0个位置开始插入8个字符 std::cout << "After partial insert: " << str << std::endl; // "Hello Amazing Beautiful World!" // 插入多个相同字符 str.insert(0, 3, '*'); // 在开头插入3个* std::cout << "After inserting chars: " << str << std::endl; // "***Hello Amazing Beautiful World!" return 0; }

结果:

3.3 删除字串内容

#include <iostream> #include <string> int main() { std::string str = "Hello, World! This is C++."; // 删除从位置7开始的5个字符 str.erase(7, 5); std::cout << "After erase: " << str << std::endl; // "Hello, ! This is C++." // 删除从位置7到末尾的所有字符 std::string str2 = "Hello, World!"; str2.erase(7); std::cout << "After erase to end: " << str2 << std::endl; // "Hello, " // 删除最后一个字符 str2.pop_back(); std::cout << "After pop_back: " << str2 << std::endl; // "Hello," // 清空整个字符串 str2.clear(); std::cout << "After clear, is empty? " << str2.empty() << std::endl; // 1 (true) return 0; }

结果:

3.4 替换字符串

#include <iostream> #include <string> int main() { std::string str = "Hello, World!"; // 替换从位置7开始的5个字符 str.replace(7, 5, "C++"); std::cout << "After replace: " << str << std::endl; // "Hello, C++!" // 使用子字符串替换 std::string newStr = "Amazing cpp"; str.replace(7, 3, newStr, 8, 3); // 用newStr中从8开始的3个字符替换 std::cout << "After replace with substring: " << str << std::endl; // "Hello, cpp!" return 0; }

结果:

4. 字符串查找和子字符串

4.1 查找操作

#include <iostream> #include <string> int main() { std::string str = "Hello, World! Hello, C++!"; // 查找子字符串 size_t pos = str.find("Hello"); if (pos != std::string::npos) { std::cout << "Found 'Hello' at position: " << pos << std::endl; // 0 } // 从指定位置开始查找 pos = str.find("Hello", 1); if (pos != std::string::npos) { std::cout << "Found second 'Hello' at position: " << pos << std::endl; // 14 } // 查找字符 pos = str.find('W'); if (pos != std::string::npos) { std::cout << "Found 'W' at position: " << pos << std::endl; // 7 } // 反向查找 pos = str.rfind("Hello"); if (pos != std::string::npos) { std::cout << "Found last 'Hello' at position: " << pos << std::endl; // 14 } // 查找字符集中任意字符首次出现的位置 pos = str.find_first_of(" ,!");//字符集就是(" ,!") if (pos != std::string::npos) { std::cout << "First of ', !' at position: " << pos << std::endl; // 5 } // 查找不在字符集中的字符首次出现的位置 pos = str.find_first_not_of("Helo");//字符集就是("Helo") if (pos != std::string::npos) { std::cout << "First not of 'Helo' at position: " << pos << std::endl; // 4 (,) } return 0; }

结果:

补充:

1. 上面的这些查找函数,如果找到了目标字符或字符串,则返回字符下标或字符串首元素下标,如果没有找到目标字符或字符串,则返回string::npos表示"没有找到"或"无效位置"。std::string::npos是C++中std::string类的一个静态常量成员。

// npos的定义 static const size_t npos = -1;

尽管它被定义为-1,但由于size_t无符号整型-1会被转换为该类型的最大值

4.2 提取子字符串

#include <iostream> #include <string> int main() { std::string str = "Hello, World! Welcome to C++ Programming."; // 提取子字符串 std::string sub1 = str.substr(7, 5);//返回从下标7开始的5个字符 std::cout << "Substring 1: " << sub1 << std::endl; // "World" // 从指定位置到末尾 std::string sub2 = str.substr(7);//返回从下标7开始后面所有字符 std::cout << "Substring 2: " << sub2 << std::endl; // "World! Welcome to C++ Programming." // 结合find使用 size_t commaPos = str.find(','); if (commaPos != std::string::npos) { std::string beforeComma = str.substr(0, commaPos); std::cout << "Before comma: " << beforeComma << std::endl; // "Hello" } return 0; }

结果:

5. 字符串比较

#include <iostream> #include <string> int main() { std::string str1 = "apple"; std::string str2 = "banana"; std::string str3 = "apple"; // 使用比较运算符 std::cout << std::boolalpha; std::cout << "str1 == str2: " << (str1 == str2) << std::endl; // false std::cout << "str1 == str3: " << (str1 == str3) << std::endl; // true std::cout << "str1 < str2: " << (str1 < str2) << std::endl; // true std::cout << "str1 > str2: " << (str1 > str2) << std::endl; // false // 使用compare()函数 int result = str1.compare(str2); if (result < 0) { std::cout << "str1 is less than str2" << std::endl; } else if (result > 0) { std::cout << "str1 is greater than str2" << std::endl; } else { std::cout << "str1 is equal to str2" << std::endl; } // 比较子字符串 std::string str4 = "Hello, World!"; std::string str5 = "Hello, C++!"; result = str4.compare(0, 5, str5, 0, 5); // 比较前5个字符 std::cout << "Compare first 5 chars: " << result << std::endl; // 0 (相等) return 0; }

结果:

补充:

1.注意:比较运算符的返回结果与字符串长度无关,字符串的比较逻辑为,从左到右依次比较每一个字符的ASCII码,>和<比较运算符,当遇到第一个ASCII码不相等的字符时,进行ASCII码比较,然后返回结果,比较结束。

2. compare()函数,例如:a.compare(b), a>b则返回值大于0,a<b则返回值小于0,a==b则返回值等于0.

6. 字符串与数值转换

6.1 数值转换为字符串

#include <iostream> #include <string> int main() { // C++11之后可以使用to_string函数 int num = 123; double pi = 3.14159; std::string str1 = std::to_string(num); std::string str2 = std::to_string(pi); std::cout << "Integer to string: " << str1 << std::endl; // "123" std::cout << "Double to string: " << str2 << std::endl; // "3.141590" return 0; }

结果:

6.2 字符串转换为数值

#include <iostream> #include <string> int main() { std::string str1 = "123"; std::string str2 = "3.14159"; std::string str3 = "100"; // 字符串转整数 int num1 = std::stoi(str1); std::cout << "String to int: " << num1 << std::endl; // 123 // 字符串转浮点数 double num2 = std::stod(str2); std::cout << "String to double: " << num2 << std::endl; // 3.14159 // 指定进制转换 int num3 = std::stoi(str3, nullptr, 2); // 二进制 std::cout << "Binary string to int: " << num3 << std::endl; // 4 // 获取转换停止的位置 std::string str4 = "123abc"; size_t pos; int num4 = std::stoi(str4, &pos); std::cout << "Number: " << num4 << ", Stopped at position: " << pos << std::endl; // 123, 3 return 0; }

结果:

7. 字符串输入输出

7.1 输入输出操作

#include <iostream> #include <string> #include <sstream> int main() { // 从标准输入读取 std::string input; std::cout << "Enter a string: "; std::getline(std::cin, input); std::cout << "You entered: " << input << std::endl; // 使用stringstream进行字符串分割 std::string data = "Apple Banana Cherry Date"; std::stringstream ss(data); std::string fruit; std::cout << "\nFruits:" << std::endl; while (std::getline(ss, fruit, ' ')) { std::cout << "- " << fruit << std::endl; } // 使用stringstream进行字符串拼接 std::stringstream ss2; ss2 << "The value is: " << 42 << " and pi is: " << 3.14; std::cout << "\n" << ss2.str() << std::endl; return 0; }

结果:

补充:

cin和getline获取字符串的区别

特性

cin >>

getline()

读取方式

读取到空白字符(空格、制表符、换行符)停止

读取到换行符停止

处理空白字符

跳过前导空白,遇到空白停止读取

不跳过空白,读取所有字符直到换行符

换行符处理

留在输入缓冲区中

从输入缓冲区读取并丢弃

读取整行

不能直接读取整行(遇到空格会停止)

专门用于读取整行

使用场景

读取单词、数字等以空白分隔的数据

读取包含空格的整行文本

#include <iostream> #include <string> int main() { std::string input1, input2; // 示例1: 使用getline读取 std::cout << "\n示例1: 使用getline读取" << std::endl; std::cout << "请输入一行文本(包含空格): "; std::cin.ignore(); // 清除上一个输入留下的换行符 std::getline(std::cin, input2); // 用户输入: Hello World std::cout << "getline读取的内容: \"" << input2 << "\"" << std::endl; std::cout << "长度: " << input2.length() << std::endl; // 示例2: 使用cin读取 std::cout << "示例2: 使用cin读取" << std::endl; std::cout << "请输入一行文本(包含空格): "; std::cin >> input1; // 用户输入: Hello World std::cout << "cin读取的内容: \"" << input1 << "\"" << std::endl; std::cout << "长度: " << input1.length() << std::endl; return 0; }

8. 其他有用操作

8.1 调整字符串大小

#include <iostream> #include <string> int main() { std::string str = "Hello"; std::string str2; str2.reserve(64); //如果提前知道要写入的字符串的长度,可以使用reserve()函数, //提前分配好足够的空间,减少后续重新分配内存造成的性能损失 std::cout <<"str2 Capacity: "<< str2.capacity() << std::endl; // 调整大小,如果新大小大于当前大小,用指定字符填充 str.resize(10, '!'); std::cout << "After resize to 10: " << str << std::endl; // "Hello!!!!!" // 调整大小,如果新大小小于当前大小,截断 str.resize(3); std::cout << "After resize to 3: " << str << std::endl; // "Hel" // 保留容量 std::string longStr = "This is a long string for testing capacity"; std::cout << "Capacity before: " << longStr.capacity() << std::endl; longStr.shrink_to_fit(); // 请求减少容量以适应大小,建议性请求,编译器不一定会执行 std::cout << "Capacity after shrink_to_fit: " << longStr.capacity() << std::endl; return 0; }

结果:

8.2 字符串交换

#include <iostream> #include <string> int main() { std::string str1 = "Hello"; std::string str2 = "World"; std::cout << "Before swap:" << std::endl; std::cout << "str1: " << str1 << std::endl; // "Hello" std::cout << "str2: " << str2 << std::endl; // "World" str1.swap(str2); std::cout << "\nAfter swap:" << std::endl; std::cout << "str1: " << str1 << std::endl; // "World" std::cout << "str2: " << str2 << std::endl; // "Hello" return 0; }

结果:


那么本期的内容就到这里了,觉得有收获的同学们可以给个点赞、评论、关注、收藏哦,谢谢大家。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/6 18:55:20

电商系统MySQL启动优化实战:从30秒到3秒的飞跃

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 基于电商高并发场景&#xff0c;生成MySQL 8.0最优启动配置&#xff1a;1.分配16GB内存的专用服务器&#xff1b;2.优化innodb_buffer_pool_size等核心参数&#xff1b;3.预加载常用…

作者头像 李华
网站建设 2026/5/6 10:30:15

万能交换函数模板解析

代码功能解析该代码实现了一个通用的交换函数模板&#xff0c;能够交换任意相同类型的两个变量值。以下是具体分析&#xff1a;模板函数定义template<class T> void Swap(T& x, T& y) {T tmp x;x y;y tmp; }使用template<class T>定义模板&#xff0c;T…

作者头像 李华
网站建设 2026/4/27 13:39:31

Vulkan教程(十三):着色器模块:Vulkan 可编程管线的核心载体

目录 一、SPIR-V 的核心优势 二、Slang 着色器语言基础 三、三角形渲染的着色器实现 3.1 顶点着色器(Vertex Shader) 3.2 片段着色器(Fragment Shader) 3.3 逐顶点颜色插值(进阶) 四、着色器编译(Slang → SPIR-V) 4.1 着色器文件组织 4.2 编译脚本(平台专属…

作者头像 李华
网站建设 2026/5/4 16:01:00

腾讯游戏单季收入破600亿元 :“铁王座”稳中有忧?

近日&#xff0c;腾讯在2025年第三季度财报中披露&#xff0c;总营收达1928.7亿元&#xff0c;同比增长15%&#xff1b;其中游戏业务收入为636亿元&#xff0c;同比增长22.8%&#xff0c;实现单季收入首次突破600亿元大关。这一里程碑标志着腾讯游戏在“回归大DAU、打造长青游戏…

作者头像 李华
网站建设 2026/5/2 21:37:27

12345

作者头像 李华