C++ 中的 string 类:全面解析与应用实践(上)
🤖🌟 欢迎降临张有志的未来科技实验室🤖🌟
专栏:C++
👨💻👩💻 先赞后看,已成习惯👨💻👩💻
👨💻👩💻 创作不易,多多支持👨💻👩💻
🚀 启动创新引擎,揭秘C++的密码🚀
引言
- 编程中字符串至关重要。无论是构建用户界面、处理数据还是网络通信,都离不开字符串操作。
- C 语言里的 char 数组处理字符串时,需手动管理内存,容易出现缓冲区溢出等错误,像字符串拼接、复制等常见操作,代码编写繁琐且易出错。
- C++ 的 string 类则是强大的字符串处理工具。它能自动处理内存分配与释放,避免手动管理的风险。还提供大量实用成员函数,如拼接、查找、替换、比较等操作都很便捷,可有效提升开发效率,助力开发者专注核心业务逻辑,在 C++ 编程里处理字符串极为得力。
💡目录
引言
一、string 类基础
string 类对象的创建及初始化
二、string 类基本操作
(一)字符串访问
(二)字符串长度获取
(三)字符串拼接
(四) 探讨拼接时的内存管理与性能优化( reserve( ) 方法的应用)
(五)空字符串的判断
三、string类对象的比较
1.==、>、<、!= 等运算符在 string 类中的应用
2. compare() 方法的深入讲解,包括返回值含义与多参数用法
区分大小写与不区分大小写比较的实现方式及应用场景
区分大小写比较
不区分大小写比较
string常用成员函数编辑
一、string 类基础
C++ 标准库(Standard Template Library, STL)是 C++ 的核心组成部分之一,提供了丰富的数据结构和算法。
<string>是 C++ 标准库中用于处理字符串的头文件。在 C++ 中,字符串是由字符组成的序列。
<string>头文件提供了std::string类,它是对 C 风格字符串的封装,提供了更安全、更易用的字符串操作功能。
想要使用string类,需包含头文件string与iostream:
#include<iostream>
#include<string>
string 类对象的创建及初始化
1. 直接赋值初始化
#include<iostream>
#include<string>int main(){std::string str1 = "Hello, World!";std::cout << str1 << std::endl;return 0;
}

2.默认构造函数
#include <iostream>
#include <string>int main() {std::string str2;std::cout << "str2的长度为: " << str2.length() << std::endl;return 0;
}

3.指定长度初始化
#include <iostream>
#include <string>int main() {std::string str4(10, 'a');std::cout << str4 << std::endl;return 0;
}

二、string 类基本操作
(一)字符串访问
1.下标访问
#include <iostream>
#include <string>int main() {std::string str = "Hello";char firstChar = str[0]; // 获取字符串的第一个字符 'H'std::cout << "第一个字符: " << firstChar << std::endl;// 也可以修改单个字符str[0] = 'J';std::cout << "修改后的字符串: " << str << std::endl;return 0;
}

2.迭代器遍历
#include <iostream>
#include <string>int main() {std::string str = "World";std::string::iterator it;for (it = str.begin(); it!= str.end(); ++it) {std::cout << *it;}std::cout << std::endl;return 0;
}

string类提供了 begin()和end()函数分别返回指向字符串开头和结尾(不包含最后一个字符)的迭代器- 可以使用常量迭代器
const_iterator来遍历不可修改的字符串,以增强程序的安全性和规范性。
(二)字符串长度获取
1. length() 与 size() 方法的使用及区别
string 类中的 length() 和 size()方法在功能上基本相同,都用于获取字符串中字符的数量,并返回 size_t 类型。
#include <iostream>
#include <string>int main() {std::string str = "Test String";std::cout << "字符串长度(length): " << str.length() << std::endl;std::cout << "字符串长度(size): " << str.size() << std::endl;return 0;
}

2. 获取字符串长度并应用于实际逻辑
#include <iostream>
#include <string>int main() {std::string password;std::cout << "请输入密码: ";std::cin >> password;if (password.length() < 8) {std::cout << "密码长度不足 8 位,请重新输入。" << std::endl;// 可以在这里进行重新输入密码等相关逻辑处理} else {std::cout << "密码长度符合要求。" << std::endl;}return 0;
}

(三)字符串拼接
1. 使用 + 运算符拼接字符串
#include <iostream>
#include <string>int main() {std::string firstName = "John";std::string lastName = "Doe";std::string fullName = firstName + " " + lastName;std::cout << "全名: " << fullName << std::endl;return 0;
}

2. append( ) 函数
#include <iostream>
#include <string>int main() {std::string str1 = "Hello";std::string str2 = " World";std::string str3 = "!";// 拼接一个字符串str1.append(str2);// 拼接一个字符串的一部分str1.append(str3, 0, 1);std::cout << str1 << std::endl;return 0;
}

这里先将 str2 拼接到 str1 后面,然后将 str3 的从索引 0 开始长度为 1 的部分(即
'!')拼接到 str1 上。
(四) 探讨拼接时的内存管理与性能优化( reserve( ) 方法的应用)
当进行多次字符串拼接时,如果不加以优化,可能会导致频繁的内存重新分配,降低程序性能
#include <iostream>
#include <string>int main() {std::string result;for (int i = 0; i < 1000; ++i) {std::string temp = std::to_string(i);result += temp;}std::cout << result << std::endl;return 0;
}
每次执行 result += temp 时,string 对象可能会重新分配内存来容纳新拼接的内容。为了避免这种情况,可以使用 reserve() 方法预先分配足够的内存空间
#include <iostream>
#include <string>int main() {std::string result;int estimatedLength = 0;for (int i = 0; i < 1000; ++i) {std::string temp = std::to_string(i);estimatedLength += temp.length();}result.reserve(estimatedLength);for (int i = 0; i < 1000; ++i) {std::string temp = std::to_string(i);result += temp;}std::cout << result << std::endl;return 0;
}
首先预估字符串的长度并提前开辟空间,以此来避免多次开辟空间降低效率
#include <iostream>
#include <string>
#include <ctime>// 未优化的多次字符串拼接函数
void withoutReserve() {std::string result;for (int i = 0; i < 1000; ++i) {std::string temp = std::to_string(i);result += temp;}
}// 使用reserve优化后的多次字符串拼接函数
void withReserve() {std::string result;int estimatedLength = 0;for (int i = 0; i < 1000; ++i) {std::string temp = std::to_string(i);estimatedLength += temp.length();}result.reserve(estimatedLength);for (int i = 0; i < 1000; ++i) {std::string temp = std::to_string(i);result += temp;}
}int main() {clock_t start1, end1, start2, end2;// 测量未优化代码的执行时间start1 = clock();withoutReserve();end1 = clock();// 测量优化后代码的执行时间start2 = clock();withReserve();end2 = clock();double time1 = static_cast<double>(end1 - start1) / CLOCKS_PER_SEC;double time2 = static_cast<double>(end2 - start2) / CLOCKS_PER_SEC;std::cout << "未使用reserve的代码执行时间: " << time1 << " 秒" << std::endl;std::cout << "使用reserve的代码执行时间: " << time2 << " 秒" << std::endl;return 0;
}

使用reserve()函数后,效率明显提高(在数据较大时)
(五)空字符串的判断
1. 使用empty()函数
std::string strToCheck = "";
if (strToCheck.empty()) {std::cout << "这是一个空字符串。" << std::endl;
}

2.比较长度
std::string anotherStrToCheck;
if (anotherStrToCheck.length() == 0) {std::cout << "这个字符串长度为0,是一个空字符串。" << std::endl;
}

三、string类对象的比较
1.==、>、<、!= 等运算符在 string 类中的应用
#include <iostream>
#include <string>int main() {std::string str1 = "apple";std::string str2 = "banana";std::string str3 = "apple";if (str1 == str3) {std::cout << "str1 和 str3 相等" << std::endl;}if (str1!= str2) {std::cout << "str1 和 str2 不相等" << std::endl;}return 0;
}

2. compare() 方法的深入讲解,包括返回值含义与多参数用法
compare( ) 的基本用法是将当前字符串与另一个字符串进行比较,返回值为一个整数,其含义如下:
- 如果当前字符串小于比较的字符串,返回值小于 0
- 如果当前字符串等于比较的字符串,返回值等于 0
- 如果当前字符串大于比较的字符串,返回值大于 0
#include <iostream>
#include <string>// 函数用于比较两个完整字符串
void compareFullStrings() {std::string strX = "hello";std::string strY = "world";int result = strX.compare(strY);if (result < 0) {std::cout << "strX 小于 strY" << std::endl;}
}// 函数用于从指定位置和长度比较字符串与子串
void compareSubstring() {std::string longStr = "This is a long string";std::string subStr = "long";// 从索引10开始比较,比较长度为4int posResult = longStr.compare(10, 4, subStr);if (posResult == 0) {std::cout << "从索引10开始的子串与subStr相等" << std::endl;}
}int main() {std::cout << "比较两个完整字符串的结果:" << std::endl;compareFullStrings();std::cout << "比较指定位置子串的结果:" << std::endl;compareSubstring();return 0;
}

区分大小写与不区分大小写比较的实现方式及应用场景
区分大小写比较
如前面所述,使用比较运算符(> == < != )和compare方法都是区分大小写的比较。这种比较方式在很多场景下是适用的,比如密码验证(包括大小写)才能通过验证
#include <iostream>
#include <string>int main() {std::string storedPassword = "Abc123";std::string inputPassword;std::cout << "请输入密码: ";std::cin >> inputPassword;if (inputPassword == storedPassword) {std::cout << "密码正确" << std::endl;} else {std::cout << "密码错误" << std::endl;}return 0;
}


不区分大小写比较
在一些场景中,例如文件名比较或者文本搜索时,可能不需要区分大小写。实现不区分大小写比较可以通过将字符串转换为统一的大小写形式后再进行比较。例如,可以使用 transform 函数结合 tolower 或 toupper 函数来实现。以下是一个不区分大小写比较两个字符串的示例
#include <iostream>
#include <algorithm>
#include <string>bool caseInsensitiveCompare(const std::string& str1, const std::string& str2) {std::string str1Copy = str1;std::string str2Copy = str2;std::transform(str1Copy.begin(), str1Copy.end(), str1Copy.begin(), [](unsigned char c) { return std::tolower(c); });std::transform(str2Copy.begin(), str2Copy.end(), str2Copy.begin(), [](unsigned char c) { return std::tolower(c); });return str1Copy == str2Copy;
}int main() {std::string file1 = "TEST.TXT";std::string file2 = "test.txt";if (caseInsensitiveCompare(file1, file2)) {std::cout << "文件名不区分大小写比较相等" << std::endl;} else {std::cout << "文件名不区分大小写比较不相等" << std::endl;}return 0;
}

string常用成员函数
相关文章:
C++ 中的 string 类:全面解析与应用实践(上)
🤖🌟 欢迎降临张有志的未来科技实验室🤖🌟 专栏:C 👨💻👩💻 先赞后看,已成习惯👨💻👩💻…...
量化交易系统开发-实时行情自动化交易-8.7.文华平台
19年创业做过一年的量化交易但没有成功,作为交易系统的开发人员积累了一些经验,最近想重新研究交易系统,一边整理一边写出来一些思考供大家参考,也希望跟做量化的朋友有更多的交流和合作。 接下来会对于文华平台介绍。 文华财经…...
美畅物联丨如何通过 FFmpeg 解码视频
FFmpeg是一款功能强大、在多媒体处理领域广泛应用的开源工具。它可以处理多种音频和视频格式,包含编码、解码、转码、流媒体处理等众多功能。前两天,我们在《美畅物联丨如何通过FFmpeg排查视频问题》一文中介绍了借助FFmpeg程序来辅助判断视频播放异常的…...
机器学习任务功略
loss如果大,训练资料没有学好,此时有两个可能: 1.model bias太过简单(找不到loss低的function)。 解决办法:增加输入的feacture,设一个更大的model,也可以用deep learning增加弹性…...
Web Worker 和 WebSocket的区别
Web Worker(消息传递机制) 定义:是为了在浏览器中提供多线程支持,允许 JavaScript 在后台线程运行,而不阻塞主线程。它非常适合执行耗时的计算任务或处理大量数据,避免主线程(通常是 UI 线程&a…...
JMeter实时性能压测可视化系统整合
一、相关工具简介: JMeter、Grafana 和 InfluxDB 结合实时地收集、分析和展示性能测试数据,进行更好地理解系统的性能表现,及时发现潜在问题并进行优化。 1,JMeter 实时生成性能数据,并将其发送到 InfluxDB 进行存储。2,InfluxDB 存储的数据。3,通过Grafana的仪表板,用…...
无限加载和懒加载及路由滚动及路由滚动不生效
这里写目录标题 列表无限加载懒加载定制路由滚动使用scrollBehavior不起效不管用的原因使用scrollTo来实现路由滚动elMain && elMain.scrollTo(...) 的作用是: 无限加载和懒加载的区别 列表无限加载 无限加载功能在现代网页和移动应用中广泛应用࿰…...
CSS底层基础:小白速来
1. CSS简介 CSS (Cascading Style Sheets) 是一种用来描述HTML或XML文档样式的语言。它使得开发者能够控制网页的布局和外观,包括字体、颜色、间距等。CSS通过选择器来指定要应用样式的元素,并定义这些元素的具体样式属性。 基本结构示例: …...
【MySQL 进阶之路】索引概述
第06章_索引 1.什么是索引 索引是存储引擎用于快速找到数据记录的一种数据结构,就好比一本教科书的目录部分,通过目录中找到对应文章的页码,便可快速定位到需要的文章。MySQL中也是一样的道理,进行数据查找时,首先查…...
【C++boost::asio网络编程】有关异步读写api的笔记
异步读写api 异步写操作async_write_someasync_send 异步读操作async_read_someasync_receive 定义一个Session类,主要是为了服务端专门为客户端服务创建的管理类 class Session { public:Session(std::shared_ptr<asio::ip::tcp::socket> socket);void Conn…...
Elasticsearch 的存储与查询
Elasticsearch 的存储与查询 在搜索系统领域,数据的存储与查询是两个最基础且至关重要的环节。Elasticsearch(ES) 在这两方面进行了深度优化,使其在关系型数据库或非关系型数据库中脱颖而出,成为搜索系统的首选。 映射 (Mapping) 映射 (Ma…...
008静态路由-特定主机路由
按照如上配置,用192.168.0.1 电脑ping 192.168.1.1 发现能够ping通 用192.168.0.1 电脑ping 192.168.2.1 发现不能ping通 这是因为192.168.0.1 和 192.168.1.1 使用的是同一个路由器R1。 192.168.0.1 和 192.168.2.1 通信需要先经过R1,再经过R2 …...
SystemUI 下拉框 Build 版本信息去掉
需求及场景 去掉SystemUI 下拉框 Build 版本信息 如下图所示:去掉 12 (SP1A.201812.016) 了解 去掉之前我们先了解它是个什么东西:其实就是一个Build RTM 信息显示 Android_12_build_SP1A.210812.016 修改文件 /frameworks/base/packages/Syste…...
【JS】栈内存、堆内存、事件机制区别、深拷贝、浅拷贝
js中,内存主要分为两种类型:栈内存(stack)、堆内存(heap),两种内存区域在存储和管理数据时有各自的特点和用途。 栈内存 访问顺序 栈是先进后出、后进先出的数据结构,栈内存是内存用…...
如何确保Java爬虫获得1688商品详情数据的准确性
在数字化商业时代,数据的价值日益凸显,尤其是对于电商平台而言。1688作为中国领先的B2B电子商务平台,提供了海量的商品数据接口,这些数据对于市场分析、库存管理、价格策略制定等商业活动至关重要。本文将详细介绍如何使用Java编写…...
【蓝牙通讯】iOS蓝牙开发基础介绍
1. iOS 蓝牙开发基础 在 iOS 中,蓝牙的操作主要是通过 Core Bluetooth 框架来实现。理解 Core Bluetooth 的基本组件和工作原理是学习 iOS 蓝牙开发的第一步。 核心知识点: Core Bluetooth 框架:这是 iOS 系统提供的专门用于蓝牙低功耗&am…...
Vue 90 ,Element 13 ,Vue + Element UI 中 el-switch 使用小细节解析,避免入坑(获取后端的数据类型自动转变)
目录 前言 在开发过程中,我们经常遇到一些看似简单的问题,但有时正是这些细节问题让我们头疼不已。今天,我就来和大家分享一个我在开发过程中遇到的 el-switch 使用的小坑,希望大家在使用时能够避免。 一. 问题背景 二. 问题分…...
echarts的双X轴,父级居中的相关配置
前言:折腾了一个星期,在最后一天中午,都快要放弃了,后来坚持下来,才有下面结果。 这个效果就相当是复合表头,第一行是子级,第二行是父级。 子级是奇数个时,父级label居中很简单&…...
RuoYi-Vue部署到Linux服务器(Jar+Nginx)
一、本地环境准备 源码下载、本地Jdk及Node.js环境安装,参考以下文章。 附:RuoYi-Vue下载与运行 二、服务器环境准备 1.安装Jdk 附:JDK8下载安装与配置环境变量(linux) 2.安装MySQL 附:MySQL8免安装版下载安装与配置(linux) 3.安装Redis 附:Redis下载安装与配置(…...
Linux firewalld常用命令
启动防火墙 systemctl start firewalld 停止防火墙 systemctl stop firewalld 防火墙开机自启动 systemctl enable firewalld 禁止防火墙开机自启动 systemctl disable firewalld 检查防火墙的状态 systemctl status firewalld 重新加载防火墙的配置 firewall-cmd -…...
高防服务器能够抵御哪些网络攻击呢?
高防服务器作为一种有着高度防御能力的服务器,可以帮助网站应对分布式拒绝服务攻击,有效识别和清理一些恶意的网络流量,为用户提供安全且稳定的网络环境,那么,高防服务器一般都可以抵御哪些网络攻击呢?下面…...
Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信
文章目录 Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信前言一、网络通信基础概念二、服务端与客户端的完整流程图解三、每一步的详细讲解和代码示例1. 创建Socket(服务端和客户端都要)2. 绑定本地地址和端口&#x…...
Fabric V2.5 通用溯源系统——增加图片上传与下载功能
fabric-trace项目在发布一年后,部署量已突破1000次,为支持更多场景,现新增支持图片信息上链,本文对图片上传、下载功能代码进行梳理,包含智能合约、后端、前端部分。 一、智能合约修改 为了增加图片信息上链溯源,需要对底层数据结构进行修改,在此对智能合约中的农产品数…...
GruntJS-前端自动化任务运行器从入门到实战
Grunt 完全指南:从入门到实战 一、Grunt 是什么? Grunt是一个基于 Node.js 的前端自动化任务运行器,主要用于自动化执行项目开发中重复性高的任务,例如文件压缩、代码编译、语法检查、单元测试、文件合并等。通过配置简洁的任务…...
Chrome 浏览器前端与客户端双向通信实战
Chrome 前端(即页面 JS / Web UI)与客户端(C 后端)的交互机制,是 Chromium 架构中非常核心的一环。下面我将按常见场景,从通道、流程、技术栈几个角度做一套完整的分析,特别适合你这种在分析和改…...
【深度学习新浪潮】什么是credit assignment problem?
Credit Assignment Problem(信用分配问题) 是机器学习,尤其是强化学习(RL)中的核心挑战之一,指的是如何将最终的奖励或惩罚准确地分配给导致该结果的各个中间动作或决策。在序列决策任务中,智能体执行一系列动作后获得一个最终奖励,但每个动作对最终结果的贡献程度往往…...
恶补电源:1.电桥
一、元器件的选择 搜索并选择电桥,再multisim中选择FWB,就有各种型号的电桥: 电桥是用来干嘛的呢? 它是一个由四个二极管搭成的“桥梁”形状的电路,用来把交流电(AC)变成直流电(DC)。…...
基于江科大stm32屏幕驱动,实现OLED多级菜单(动画效果),结构体链表实现(独创源码)
引言 在嵌入式系统中,用户界面的设计往往直接影响到用户体验。本文将以STM32微控制器和OLED显示屏为例,介绍如何实现一个多级菜单系统。该系统支持用户通过按键导航菜单,执行相应操作,并提供平滑的滚动动画效果。 本文设计了一个…...
【深尚想】TPS54618CQRTERQ1汽车级同步降压转换器电源芯片全面解析
1. 元器件定义与技术特点 TPS54618CQRTERQ1 是德州仪器(TI)推出的一款 汽车级同步降压转换器(DC-DC开关稳压器),属于高性能电源管理芯片。核心特性包括: 输入电压范围:2.95V–6V,输…...
嵌入式面试常问问题
以下内容面向嵌入式/系统方向的初学者与面试备考者,全面梳理了以下几大板块,并在每个板块末尾列出常见的面试问答思路,帮助你既能夯实基础,又能应对面试挑战。 一、TCP/IP 协议 1.1 TCP/IP 五层模型概述 链路层(Link Layer) 包括网卡驱动、以太网、Wi‑Fi、PPP 等。负责…...

