全面解析String类

一、String 类初相识

在 C 语言的世界里,字符串是以'\0'结尾的字符集合,为了方便操作,C 标准库提供了一系列str系列的库函数,如strcpy、strcat、strlen等。虽然这些库函数在一定程度上满足了我们对字符串的操作需求,但是它们与字符串是分离开的,不太符合面向对象编程(OOP)的思想。而且,C 语言中字符串的底层空间需要用户自己管理,这就像让你自己搭建帐篷去露营,虽然很有挑战性,但也容易出错。稍不留神,就可能会出现越界访问的情况,比如在使用strcpy函数时,如果目标缓冲区的大小不足以容纳源字符串,就会导致缓冲区溢出,这可是一个很严重的问题,就像你把太多的东西塞进一个小袋子里,袋子可能会被撑破。


下面是一个简单的 C 语言字符串操作示例:

#include <stdio.h>
#include <string.h>int main() {char str1[20] = "Hello";char str2[] = " World";// 拼接字符串strcat(str1, str2);printf("拼接后的字符串: %s\n", str1);// 计算字符串长度int len = strlen(str1);printf("字符串长度: %d\n", len);return 0;
}

在这个示例中,我们使用了strcat函数来拼接两个字符串,使用strlen函数来计算字符串的长度。虽然这些操作看起来很简单,但是需要我们自己管理字符串的存储空间,并且要小心避免缓冲区溢出等问题。而在 C++ 的标准库中,string类就像是一个专门为你搭建好的豪华帐篷,为我们提供了更加安全、方便和高效的字符串处理方式。它将字符串的操作和数据封装在一起,完全符合 OOP 的思想,让我们可以像操作普通对象一样操作字符串。string类还会自动管理字符串的内存空间,这就像帐篷会自动根据你的需求调整大小,你不用担心空间不够用或者空间浪费的问题。而且,string类提供了丰富的成员函数,让我们可以轻松地完成字符串的各种操作,如拼接、查找、替换等,就像豪华帐篷里配备了各种高级设施,让你的露营体验更加舒适和便捷。

在 OJ(Online Judge)中,有关字符串的题目基本都是以string类的形式出现。在实际工作中,为了 追求简单、方便和快捷,大家也基本都使用string类,很少有人再去使用 C 库中的字符串操作函数。 所以,掌握string类的使用是非常必要的,它将大大提高我们的编程效率和代码的安全性。

二、String 类的基础操作

2.1 构造函数大揭秘

string类提供了多种构造函数,以满足不同的初始化需求。下面是一些常见的构造函数及其用法:

无参构造函数:创建一个空的string对象。

string s1;

有参构造函数:使用 C 风格字符串或其他string对象来初始化string。

string s2("Hello, C++");

string s3(s2);

指定字符和数量构造函数:创建一个包含指定数量相同字符的string对象。

string s4(5, 'a');// s4:"aaaaa"

部分复制构造函数:从 C 风格字符串的指定位置开始,复制指定长度的字符来初始化string。

char c[] = "0123456789";

string s5(c, 5); // s5:"01234"

迭代器构造函数:使用迭代器指定的范围来初始化string。

char c2[] = "0123456789";
string s6(c2 + 1, c2 + 7); // s6:"123456"

子字符串构造函数:从另一个string对象的指定位置开始,复制指定长度的子字符串来初始化string。

string temp("0123456789");
string s7(temp, 0, 5); // s7:"01234"

2.2 容量操作

string类提供了一系列函数来获取和管理字符串的容量和长度,这些函数对于优化字符串操作和避免不必要的内存分配非常重要。

size () 和 length ():这两个函数都返回字符串中有效字符的长度,它们的功能完全相同,只是为了与 其他容器的接口保持一致,才同时提供了这两个函数。一般情况下,我们更常用size()。

string s("Hello, World!");

cout<< s.size() << s.length()<<endl;

capacity():返回当前为字符串分配的总容量,这个容量可能大于字符串的实际长度,用于减少频繁的内存重新分配。

string s("Hello");
cout << s.capacity() << endl;

empty():检查字符串是否为空,为空则返回true,否则返回false。

string s1;
string s2("Hello");

cout << s1.empty()<< endl;
cout << s2.empty() << endl;

clear():清空字符串中的有效字符,但不会释放底层分配的内存空间,即容量不变。

string s("Hello, World!");
s.clear();
cout << s.size()<< endl;
cout << s .capacity() << endl;

reserve():为字符串预留指定大小的容量,避免在后续操作中频繁的内存重新分配,提高效率。如果指定的容量小于当前容量,则该操作通常不会改变容量。

string s;
s.reserve(100);
cout << s.capacity() << endl;

resize():将字符串的有效字符长度调整为指定的大小。如果新长度大于原长度,会在字符串末尾填充指定字符(默认为空字符'\0');如果新长度小于原长度,会截断字符串。

string s("Hello");
s.resize(8, 'a');
s.resize(3); 

2.3 访问与遍历方法

operator[]:通过下标访问字符串中的字符,就像访问数组一样。需要注意的是,下标从 0 开始,并 且要确保下标不超出字符串的有效长度,否则会导致未定义行为。

string s("Hello");​
cout << "第一个字符: " << s[0] << endl;​
cout << "最后一个字符: " << s[s.size() - 1] << endl;

迭代器(begin、end 等):string类提供了begin()和end()函数,分别返回指向字符串第一个字符和 最后一个字符下一个位置的迭代器。通过迭代器,我们可以遍历字符串中的每个字符。此外,还 有rbegin()和rend()函数,用于反向遍历字符串。

string s("Hello");​
// 正向遍历​
for (string::iterator it = s.begin(); it!= s.end(); ++it) {​
    cout << *it << " ";​
}​
cout << endl;​
// 反向遍历​
for (string::reverse_iterator rit = s.rbegin(); rit!= s.rend(); ++rit) {​
    cout << *rit << " ";​
}​
cout << endl;

范围 for:C++11 引入的范围 for 循环,为遍历字符串提供了一种更简洁的方式。它会自动遍历字符串中的每个字符,无需手动管理迭代器。

string s("Hello");

for (char ch : s) {

cout << ch << " ";

}

cout << endl;

2.4 修改操作大集合

push_back():在字符串的末尾添加一个字符。

string s("Hello");

s.push_back('!');

cout << "添加字符后的字符串: " << s << endl;

append():在字符串的末尾追加另一个字符串,可以是 C 风格字符串、string对象或字符序列。

string s1("Hello");

string s2(" World");

s1.append(s2);

cout << "追加字符串后的字符串: " << s1 << endl;

operator+=:这是一个更常用的追加操作符,它可以在字符串的末尾追加单个字符、C 风格字符串或string对象,功能与push_back()和append()类似,但使用起来更加简洁。

string s("Hello");​
s += " World";​
s += '!';​
cout << "使用operator+=后的字符串: " << s << endl;

insert():在字符串的指定位置插入字符或字符串。可以插入单个字符、C 风格字符串、string对象或字符序列,还可以使用迭代器指定插入的位置和范围。

string s("Hello");

s.insert(5, ", World");

cout << "插入字符串后的字符串: " << s << endl;

erase():删除字符串中的部分字符,可以指定删除的起始位置和长度,也可以使用迭代器指定删除的范围。

string s("Hello, World!");

s.erase(5, 7);

cout << "删除部分字符后的字符串: " << s << endl;

replace():用新的字符串替换字符串中的部分内容,可以指定替换的起始位置和长度,以及用于替换的新字符串。

string s("Hello, World!");

s.replace(0, 5, "Hi");

cout << "替换部分字符串后的字符串: " << s << endl;

find () 和 rfind ():find()函数从字符串的指定位置开始,向后查找指定的字符或子字符串,返回第一次出现的位置;rfind()函数则从指定位置开始,向前查找,返回最后一次出现的位置。如果找不到,这两个函数都会返回string::npos,这是一个表示无效位置的常量。

#include<iostream>
using namespace std;
int main()
{string s("Hello, World!");size_t pos1 = s.find("World");if (pos1 != string::npos) {cout << "找到子字符串'World',位置为: " << pos1 << endl;}else {cout << "未找到子字符串'World'" << endl;}size_t pos2 = s.rfind('o');if (pos2 != string::npos) {cout << "找到字符'o'最后一次出现的位置为: " << pos2 << endl;}else {cout << "未找到字符'o'" << endl;}
}

substr():从字符串的指定位置开始,截取指定长度的子字符串并返回。如果不指定长度,则截取从指定位置到字符串末尾的所有字符。

#include<iostream>
using namespace std;
int main()
{string s("Hello, World!");string sub1 = s.substr(7);cout << "从位置7开始截取的子字符串: " << sub1 << endl;string sub2 = s.substr(0, 5);cout << "从位置0开始截取长度为5的子字符串: " << sub2 << endl;
}

好啦,到这里我们对 C++ `String` 类全面解析就到这里啦,希望今天的内容能给你带来收获,让你对字符串处理有新的认识。编程的世界丰富多彩,还有很多知识等你解锁,加油哦,期待你在代码世界里创造更多精彩!下一期我会带来string类的模拟实现。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/13960.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

pycharm 中的 Mark Directory As 的作用是什么?

文章目录 Mark Directory As 的作用PYTHONPATH 是什么PYTHONPATH 作用注意事项 Mark Directory As 的作用 可以查看官网&#xff1a;https://www.jetbrains.com/help/pycharm/project-structure-dialog.html#-9p9rve_3 我们这里以 Mark Directory As Sources 为例进行介绍。 这…

MySQL - 字段内分组

1、MySQL 5.7及之前版本 SELECT A.要显示的字段名称,FIRST_VALUE : A.分组字段名称,last :IF(FIRST_VALUE A.分组字段名称, last 1, 1 ) AS rn,FROM 表1 A,(SELECT last : 0, FIRST_VALUE : NULL ) BORDER BY A.排序字段例&#xff1a;SELECT A.DLR_CODE,A.VAILD_CARD_NO,A.L…

瞬态分析中的时域分析与频域分析:原理、对比与应用指南

目录 一、核心概念区分 二、时域分析&#xff1a;时间维度直接求解 1. 基本原理 2. 关键特点 3. 典型算法 4. 应用案例 三、频域分析&#xff1a;频率维度的等效映射 1. 基本原理 2. 关键特点 3. 典型方法 4. 应用案例 四、对比与选择依据 1. 方法论对比 2. 工程…

【DeepSeek】DeepSeek小模型蒸馏与本地部署深度解析DeepSeek小模型蒸馏与本地部署深度解析

一、引言与背景 在人工智能领域&#xff0c;大型语言模型&#xff08;LLM&#xff09;如DeepSeek以其卓越的自然语言理解和生成能力&#xff0c;推动了众多应用场景的发展。然而&#xff0c;大型模型的高昂计算和存储成本&#xff0c;以及潜在的数据隐私风险&#xff0c;限制了…

安卓/ios脚本开发按键精灵经验小分享

1. 程序的切换 我们经常碰到这样的需求&#xff1a;打开最近的应用列表&#xff0c;选取我们想要的程序。但是每个手机为了自己的风格&#xff0c;样式都有区别&#xff0c;甚至连列表的滑动方向都不一样&#xff0c;我们很难通过模拟操作来识别点击&#xff0c;那么我们做的只…

camera光心检测算法

1.概要 光心检测算法&#xff0c;基于opencv c实现&#xff0c;便于模组厂快速集成到软件工具中&#xff0c;适用于camera模组厂算法评估组装制程镜头与sensor的偏心程度&#xff0c;便于工程师了解制程的问题找出改善方向。 2.技术介绍 下图为camera模组厂抓取的bayer-raw经过…

OpenCV:特征检测总结

目录 一、什么是特征检测&#xff1f; 二、OpenCV 中的常见特征检测方法 1. Harris 角点检测 2. Shi-Tomasi 角点检测 3. Canny 边缘检测 4. SIFT&#xff08;尺度不变特征变换&#xff09; 5. ORB 三、特征检测的应用场景 1. 图像匹配 2. 运动检测 3. 自动驾驶 4.…

Docker安装pypiserver私服

Docker安装pypiserver私服 1 简介 Python开源包管理工具有pypiserver、devpi和Nexus等&#xff0c;pypiserver安装部署比较简单&#xff0c;性能也不错。 搭建pypiserver私服&#xff0c;可以自己构建镜像&#xff0c;也可以使用官网的docker镜像。 # Github地址 https://g…

什么是自动化测试?自动化测试的作用

&#x1f345; 点击文末小卡片&#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 一、自动化测试 所谓的自动化测试简单来说就是有计算机代替 人来单击被测软件的界面&#xff0c;执行一系列操作并进行验证。 自动化有点&#xff1a;通过执行…

AI驱动的智能流程自动化是什么

在当今快速发展的数字化时代&#xff0c;企业正在寻找更高效、更智能的方式来管理日常运营和复杂任务。其中&#xff0c;“AI驱动的智能流程自动化”&#xff08;Intelligent Process Automation, IPA&#xff09;成为了一个热门趋势。通过结合人工智能&#xff08;AI&#xff…

集合类不安全问题

ArrayList不是线程安全类&#xff0c;在多线程同时写的情况下&#xff0c;会抛出java.util.ConcurrentModificationException异常 解决办法&#xff1a; 1.使用Vector&#xff08;ArrayList所有方法加synchronized&#xff0c;太重&#xff09; 2.使用Collections.synchronized…

私有化部署DeepSeek并SpringBoot集成使用(附UI界面使用教程-支持语音、图片)

私有化部署DeepSeek并SpringBoot集成使用&#xff08;附UI界面使用教程-支持语音、图片&#xff09; windows部署ollama Ollama 是一个开源框架&#xff0c;专为在本地机器上便捷部署和运行大型语言模型&#xff08;LLM&#xff09;而设计 下载ollama 下载地址&#xff08;m…

Verilog代码实例

Verilog语言学习&#xff01; 文章目录 目录 文章目录 前言 一、基本逻辑门代码设计和仿真 1.1 反相器 1.2 与非门 1.3 四位与非门 二、组合逻辑代码设计和仿真 2.1 二选一逻辑 2.2 case语句实现多路选择逻辑 2.3 补码转换 2.4 7段数码管译码器 三、时序逻辑代码设计和仿真 3.1…

二级C语言题解:十进制转其他进制、非素数求和、重复数统计

目录 一、程序填空&#x1f4dd; --- 十进制转其他进制 题目&#x1f4c3; 分析&#x1f9d0; 二、程序修改&#x1f6e0;️ --- 非素数求和 题目&#x1f4c3; 分析&#x1f9d0; 三、程序设计&#x1f4bb; --- 重复数统计 题目&#x1f4c3; 分析&#x1f9d0; 前言…

BFS算法——广度优先搜索,探索未知的旅程(下)

文章目录 前言一. N叉树的层序遍历1.1 题目链接&#xff1a;https://leetcode.cn/problems/n-ary-tree-level-order-traversal/description/1.2 题目分析&#xff1a;1.3 思路讲解&#xff1a;1.4 代码实现&#xff1a; 二. 二叉树的锯齿形层序遍历2.1 题目链接&#xff1a;htt…

软件系统性能测试的重要性和测试类型分享

在现代软件开发领域&#xff0c;软件系统性能测试的重要性愈发凸显。软件系统性能测试是一种评估软件应用程序在特定工作负载下的响应时间、稳定性和资源消耗的测试过程。其目标是识别性能瓶颈&#xff0c;确保软件在不同的负载条件下依然能够高效运行。 一、软件系统性能测试…

Three.js 实现海面效果

Three.js 实现海面效果 https://threehub.cn/#/codeMirror?navigationThreeJS&classifyshader&idoceanShader import * as THREE from three import { OrbitControls } from three/examples/jsm/controls/OrbitControls.js import { Water } from three/examples/js…

C++----继承

一、继承的基本概念 本质&#xff1a;代码复用类关系建模&#xff08;是多态的基础&#xff09; class Person { /*...*/ }; class Student : public Person { /*...*/ }; // public继承 派生类继承基类成员&#xff08;数据方法&#xff09;&#xff0c;可以通过监视窗口检…

【MySQL】第二弹---数据库基础全解析:从概念到实践的深度探索

✨个人主页&#xff1a; 熬夜学编程的小林 &#x1f497;系列专栏&#xff1a; 【C语言详解】 【数据结构详解】【C详解】【Linux系统编程】【MySQL】 目录 1. 数据库基础 1.1 什么是数据库 1.2 主流数据库 1.3 基本使用 1.3.1 MySQL安装 1.3.2 连接服务器 1.3.3 服务器…

深度学习:解码智能的“数字炼金术”

深度学习&#xff1a;解码智能的“数字炼金术” 1943年&#xff0c;当神经科学家沃伦麦卡洛克和数学家沃尔特皮茨在论文中首次提出人工神经元模型时&#xff0c;他们或许没有想到&#xff0c;这个简单的数学公式会在80年后掀起改变人类文明的技术革命。深度学习作为这场革命的…