C++:STL-string

前言

本文主要介绍STL六大组件中的容器之一:string,在学习C++的过程中,我们要将C++视为一个语言联邦(摘录于Effective C++条款一)。如何理解这句话呢,我们学习C++,可将其分为四个板块;分别为C、Object-Oriented C++(面向对象的C++)、Template C++(模板)、STL。本文就介绍STL中的string

C语言字符串的局限性

C语言中的字符串处理依赖于字符数组和一系列标准库函数(如strcpystrcatstrlen等)。这些方法虽然基本能满足需求,但存在几个显著的缺点:

  1. 安全性问题:C语言中的字符串操作常常设计直接的内存操作问题,荣誉造成缓冲区的溢出、内存泄漏的等安全问题,例如strcpy函数在赋值数据时不会检查目标缓冲区的大小,这可能导致超出其容量的写操作。
  2. 效率低下:C语言的字符串操作通常需要手动管理字符串长度和内存,如需拼接字符串时,肯需要多次调用strlen来获取当前长度,然后再添加新内容,这样的操作效率较低。
  3. 使用不便:C语言的字符串需要程序员对内存非常小心谨慎的操作,容易出错且代码难以维护。

C++string类的优势

与C语言的基本字符串处理相比,C++的string类提供了一个更安全、更高效、更易用的字符串操作方式:

  1. 自动内存管理:string类自动管理内存,使用者不需要关心内存分配和释放的问题,极大地降低了内存泄漏和缓冲区溢出的风险。
  2. 丰富的成员函数:string类内置了大量的成员函数,如append, find, replace, substr等,使得字符串的处理更为方便和直观。
  3. 动态大小:string对象可以根据需要动态增长和缩小,无需预先声明最大容量,这一点与静态大小的C语言字符数组形成鲜明对比。
  4. 操作符重载和迭代器支持:string类重载了多个操作符(如+、=等),支持迭代器,使得字符串操作更符合C++的对象操作习惯,也支持现代C++中的范围for循环和算法库函数。
  5. 兼容性和灵活性:尽管string以字节为单位进行操作,对于多字节字符集的支持可能有限,但它在大多数情况下能够兼容处理UTF-8等编码,尤其是在使用支持这些编码的库时。

string类

C++ 中提供了专门的头文件string(注意不是 string.h,这个是C风格字符串相关函数的头文件),来支持string类型。string类定义隐藏了字符串的数组性质,让我们可以像处理普通变量那样处理字符串。string对象和字符数组之间的主要区别是:可以将string对象声明为简单变量,而不是数组

标准库中的string类文档介绍

1.字符串时表示字符序列的类。

2.标准的字符串类提供了对此类对象的支持,其接口累死与标准字符容器的接口,但添加了专门用于操作单字节字符字符串的设计特性。

3.string类是使用char(即作文他的字符类型,使用他的默认char_traits和分配器类型)

4.string类是basic_string模版类的一个实例,它使用char来实例化basic_string模板类,并用char_traits和allocator作文basic_string分默认参数(根于更多漫步信息参考basic_string)。

5.注意,这个类独立于所使用的编码来处理字节:如果用来处理多字节或变长字符(符UTF-8)的序列,这个类的缩影成员(如长度或大小)已经它的迭代器,将仍然按照字节(而不是实际编码的字符)来操作。

字符串作为字符序列

string类本质上是一个用于表示字符序列的容器。它封装了字符数组的许多复杂操作,提供了一种更安全、更直观的方式来处理文本数据。用户不需要关心底层的字符数组和内存管理,所有这些都由string类自动处理。

接口与标准容器

string类的接口设计借鉴了标准库中STL容器的模式,例如vector和deque。这意味着string提供了类似于这些容器的多种成员函数,如迭代器的支持、元素访问、修改操作、容量查询等。这种设计使得string类即熟悉又易于使用对于已经熟悉其他C++标准容器的开发者。

string类的常用接口说明

string类对象的常见构造

(constructor)函数名称功能说明
string()构造空的string类对象,即空字符串
string(const char* s)用C-string来构造string类对象
string(size_t n,char c)string类对象中包含n个字符c
string(const string& s)拷贝构造函数
string s1;              // 构造空的string类对象s1
string s2("hello bit"); // 用C格式字符串构造string类对象s2
string s3(s2);          // 拷贝构造s3

string类对象的容量操作

函数名称功能说明
size返回字符串有效字符长度
length返回字符串有效字符长度
capacity返回空间总大小
empty检查字符串释放为空串,是返回true,否返回false
clear清空有效字符
reserve为字符串预留空间
resize将有效字符的个数改成n个,多出的空间用字符c填充

size()和length():

size_t size() const;
size_t length() const;
std::string str = "Hello, world!";
std::cout << "Length of string: " << str.length() << std::endl; // 输出 13
std::cout << "Size of string: " << str.size() << std::endl;     // 同样输出 13

这两个函数都返回字符串当前的长度,即字符串中字符的数量,这两种并无相异,忧郁string出现的较早原因,当时没有STL其他容器,先出现了length,后来为了统一接口,与其他容器接口保持一致,因此出现了size。

capacity():

size_t capacity() const;

std::string str = "Test";
std::cout << "Capacity of string:" << str.capacity() << std::endl; // 输出分配的内存大小

capacity()函数返回为字符串分配的存储空间的大小,通常这个值大于或等于size()。这可以给出底层数组的空间大小,有助了解内存的使用情况。

empty:

bool empty() const;
std::string str;
std::cout << "Is the string empty? " << (str.empty() ? "Yes" : "No") << std::endl; // 输出 'Yes'

empty()函数检查字符串是否为空(即长度为0)。如果字符串为空,返回true,否则返回false。

clear:

void clear() noexcept;
std::string str = "Something";
str.clear(); // 清空字符串
std::cout << "String after clear: '" << str << "'" << std::endl; // 输出 ''

clear()函数删除字符串中的所有字符,使其长度变为0,这个函数不会改变容量的大小。

reserve:

void reserve(size_t n = 0);
std::string str;
str.reserve(100); // 为存储至少100个字符预分配内存
std::cout << "New capacity after reserve: " << str.capacity() << std::endl;

reserve()函数试图改变字符串的容量,即预先分配足够的内存来存储至少n个字符,避免多次增加字符串大小时的重复分配。

resize:

void resize(size_t n);
void resize(size_t n, char c);
std::string str = "Hello";
str.resize(10, 'x'); // "Helloxxxxx"
str.resize(3);       // "Hel"

resize()函数更改字符串的长度,如果新的长度大于当前长度,新位置将于字符c填充(如果提供了c的话)。如果新的长度小于当前长度,多余的字符将被截断,空间大小不会被改变。

string类的访问及遍历操作

在std::string类中,访问和遍历字符串的方法包括使用下标操作符、迭代器和范围for循环。这些方法提供了灵活的方式来访问和遍历字符串中的字符。

函数名称功能说明
operator[]返回pos位置的字符,const string类对象调用
begin + endbegin获取一个字符的迭代器+end获取最后一个字符下一个位置的迭代器
rbegin + rend反向迭代器rbegin获取一个字符的迭代器+rend获取最后一个字符下一个位置的迭代器
范围forC++11支持更简介的范围for的新遍历方式

operator[]:

std::string str = "Hello, world!";
char ch1 = str[0];  // 访问第一个字符,ch1 = 'H'
char ch2 = str[7];  // 访问第八个字符,ch2 = 'w'std::cout << "First character: " << ch1 << std::endl;
std::cout << "Eighth character: " << ch2 << std::endl;// 修改字符串中的字符
str[5] = '!';
std::cout << "Modified string: " << str << std::endl;  // 输出 "Hello! world!"

下标操作符operator[]允许你访问字符串中的特定位置的字符,这种访问方式是随机访问,时间复杂度为O(1)。

迭代器:

std::string str = "Hello";
std::cout << "Characters in string: ";// 使用正向迭代器遍历字符串
for (auto it = str.begin(); it != str.end(); ++it) {std::cout << *it << ' ';
}
std::cout << std::endl;// 使用反向迭代器遍历字符串
std::cout << "Characters in reverse: ";
for (auto rit = str.rbegin(); rit != str.rend(); ++rit) {std::cout << *rit << ' ';
}
std::cout << std::endl;

迭代器提供了一种方式按顺序访问容器中的每个元素。std::string支持正向和反向迭代器

范围for:

std::string str = "world";std::cout << "Characters in string using range-for: ";
for (char c : str) {std::cout << c << ' ';
}
std::cout << std::endl;// 修改字符串中的字符(需要使用引用)
for (char &c : str) {c = toupper(c);  // 将字符转换为大写
}
std::cout << "Modified string: " << str << std::endl;  // 输出 "WORLD"

范围for循环是C++11引入的一个特性,它允许简介的变量容器中的所有元素,在使用范围for循环遍历std::string时,可以直接访问每个字符。

string类对象的修改操作

类提供了多种方法来修改字符串的内容,这些方法包括添加、删除、插入和替换字符等操作,下面这些方法的详细介绍和使用实例。

函数名称功能说明
push_back在字符串后尾插入字符c
append在字符串后追加一个字符串
operator+=在字符串后追加字符串str
c_str返回c格式字符串
find + npos从字符串pos位置开始往后开始找字符c,返回该字符在字符串中的位置
rfind从字符串pos位置开始往后开始找字符c,返回该字符在字符串中的位置
substr在str中从pos位置开始,截取n个字符,然后将其返回

push_back:

void push_back(char c);
std::string str = "Hello"; 
str.push_back('!'); 
std::cout << str << std::endl; // 输出 "Hello!"

push_back将一个字符追加到字符串的末尾。

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);
std::string str = "Hello";
str.append(" world", 6);  // 附加了 " world" 中的前6个字符
std::cout << str << std::endl;  // 输出 "Hello world"

append方法添加字符串、字符数组或多个相同字符到现有字符串的末尾。

operator+=:

void operator+=(const string& str);
void operator+=(char c);
void operator+=(const char* s);
std::string str = "Hello";
str += ", world!";
std::cout << str << std::endl;  // 输出 "Hello, world!"

operator+=用于将字符串、字符或者c字符串附加到现有的std::string对象上。

c_str:

int main()
{string s1("hello world");cout << s1.c_str() << endl;cout << s1.data() << endl;return 0;
}

c_str返回string类中存储字符串的字符指针,在C语言中字符串是以'\0'结尾的一些字符的集合。但在C++中,string类不以'\0'结尾,而是根据有效空间的大小结束。本质作用是:将const string* 类型转化为const char* 类型。

find和npos:

// 从string拷贝给字符数组
// size_t copy (char* s, size_t len, size_t pos = 0) const;
char arr[] = "hello world";
string s1("xxxxxxxxxxxxxxxx");
s1.copy(arr, 6, 2);
cout << s1 << endl;
// 寻找某个字符串的起始位置
// size_t find (const string& str, size_t pos = 0) const;
string tmp("abc");
string s2("abbadabcdeabcd");
size_t pos1 = s2.find(tmp, 0);
// 从后往前找
//size_t rfind (const string& str, size_t pos = npos) const;
size_t pos2 = s2.rfind(tmp, s2.size() - 1);
cout << pos1 << endl;
cout << pos2 << endl;

find有很多函数重载,学会一种就可以了,size_t find(const string& s, int pos = 0);s是需要查找的字符串,pos是从那个位置查找,如果未找到则返回npos(npos表示size_t 的最大值)。

rfind:

string s1("fghasdabc");
cout << s1.rfind('a') << endl;string s2("abc");
cout << s1.rfind(s2) << endl;
cout << s1.rfind('e') << endl;

rfind和find功能是一样的,不过一个是往前找,一个向后找的区别。

substr:

string s1("Hello World");cout << s1 << endl;
string s2(s1.substr(0, 5));cout << s1 << endl;
cout << s2 << endl;

在string中的pos位置截取n个字符,然后返回。

string类的深拷贝与浅拷贝问题

浅拷贝:

在类中如果用户没有显示实现而是由编译器自动生成的成员函数叫做默认成员函数,这样的成员函数有六个。默认成员函数中的拷贝构造函数和赋值运算符重载函数会以逐字节的方式将原对象的内容原封不动的拷贝或赋值给新的对象,如果对象中管理资源,最后就会导致多个对象共用一份资源,当其中一个对象销毁时会将该资源释放掉,其他对象再想操作该资源时就会发生访问违规,这便是浅拷贝。

namespace qx
{class string{public:string(const char* s=""){if (nullptr == s){cout << "string():false" << endl;return;}char* ptr = new char[strlen(s) + 1];strcpy(_str, s);}//........private:char* _str;};
}int main()
{qx::string s1("hello world!");qx::string s2(s1);return 0;
}

由于类对象销毁时调用析构函数,会先将s2对象销毁,再调用析构进行销毁s1对象,但是因为拷贝构造是浅拷贝,导致s1和s2指向同一块内存空间,销毁掉s2之后内存空间被释放,s1找不到改内存空间,最终违规访问。

深拷贝:

如果一个类中涉及到资源管理,其拷贝构造函数、赋值运算符重载以及析构函数都必须要显示给出,一般情况都是按照深拷贝方式提供。

//显示实现拷贝构造
string(const string& str):_str(nullptr)
{string strTmp(str._str);swap(_str, strTmp._str);
}//显示实现赋值运算符重载
string& operator=(string& str)
{if (this != &str){string strTmp(str);swap(_str, strTmp._str);}
}//显示实现析构函数
~string()
{if (_str){delete[] _str;_str = nullptr;}
}

深拷贝即给每个对象独立分配资源,保证多个对象之间不会因为共享资源而造成多次释放导致程序崩溃的问题。

string总结

深入探讨C++标准库中的string类,从其构造函数、容量操作函数,到访问及遍历操作,以及类对象的修改操作。string类作为C++中处理字符串的核心工具,提供了丰富的接口来高效、安全地管理和操作字符串。掌握这些功能不仅可以提高编程效率,还能帮助开发者编写更加健壮和可维护的代码,有效地处理现代软件开发中的文本数据挑战。

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

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

相关文章

数据降维-主成分分析PCA

1.背景&#xff1a; 在以前计算能力还很弱的年代&#xff0c;我们要分析经济数据是一件很困难的事情&#xff0c;所以我们需要对指标特征进行降维&#xff1b; 2.数据降维的意义&#xff1a; 一般我们降维的特征数据彼此之间是存在一定的相关性的&#xff0c; 二维降至一维…

2024年区块链、信号处理与航空航天国际学术会议(ICBSPA 2024)

2024年区块链、信号处理与航空航天国际学术会议&#xff08;ICBSPA 2024) 2024 International Conference on Blockchain, Signal Processing, and Aerospace 一、【会议简介】 随着科技的飞速发展&#xff0c;区块链、信号处理与航空航天等领域的交叉融合正成为推动科技进步的…

【代码随想录】【动态规划】背包问题 - 完全背包

完全背包 模板&#xff1a;完全背包问题 问题描述 完全背包问题与01背包问题唯一的区别在于&#xff1a; 在01背包中&#xff1a;每个物品只有一个&#xff0c;要么放入背包&#xff0c;要么不放入背包在完全背包中&#xff1a;每个物品有无限多个&#xff0c;可以不放入背…

卓豪Zoho CRM怎么收费?多少钱一年?

卓豪Zoho CRM作为一款功能强大且高度可定制的企业级客户关系管理系统&#xff0c;其收费标准因版本不同而有所差异&#xff0c;旨在满足不同规模及需求的企业。Zoho CRM提供多种套餐选择&#xff0c;包括但不限于免费版、标准版、专业版、企业版以及旗舰版。每种版本都包含了核…

基于Springboot的大学生平时成绩量化管理系统(有报告)。Javaee项目,springboot项目。

演示视频&#xff1a; 基于Springboot的大学生平时成绩量化管理系统&#xff08;有报告&#xff09;。Javaee项目&#xff0c;springboot项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三…

娱乐营销的新玩法:Kompas.ai如何让内容更加趣味化

在数字化时代&#xff0c;内容营销已成为品牌与消费者沟通的重要桥梁。然而&#xff0c;随着信息的爆炸式增长&#xff0c;用户的注意力越来越分散&#xff0c;传统的营销方式已经难以吸引用户的兴趣。在这种背景下&#xff0c;娱乐营销应运而生&#xff0c;它通过将娱乐元素融…

华东政法大学公布2024《负面清单期刊目录》,附目录

近日&#xff0c;华东政法大学公布2024《负面清单期刊目录》&#xff0c;包括《齐齐哈尔大学学报(哲学社会科学版)》《景德镇学院学报(社科)》《九江学院学报(社科)》《北京印刷学院学报》《江西电力职业技术学院学报》《中国多媒体与网络教学学报》《吉林省教育学院学报》《开…

Poetry Camera照相机将照片转换成诗歌并打印出来;吴恩达新课程深入了解Mistral;科学研究AI小助手data-to-paper

✨ 1: Poetry Camera 将拍摄的照片转换成诗歌并打印出来 Poetry Camera——一个能够把它所见之物转化成诗歌并打印出来的相机。你在一个美丽的公园&#xff0c;或者是一个充满故事的老街道。只要用Poetry Camera拍下这一刻&#xff0c;它就能立刻给你一首关于这个场景的诗。 …

【JAVA进阶篇教学】第十五篇:Java中AQS讲解

博主打算从0-1讲解下java进阶篇教学&#xff0c;今天教学第十五篇&#xff1a;Java中AQS讲解。 在Java并发编程中&#xff0c;AQS&#xff08;AbstractQueuedSynchronizer&#xff09;是一个重要的框架&#xff0c;用于实现同步器和锁的基础。它提供了一种灵活的方式来实现各种…

浏览器不兼容 replaceAll 方法问题解决

问题 在一些较旧版本的浏览器中可能会出现 replaceAll 方法不兼容&#xff0c;提示replaceAll 方法 undefined 的问题。浏览器版本兼容情况如下图所示&#xff1a; 解决 可以通过 replace 正则表达式 的方法来代替 replaceAll 方法&#xff1a; let str "我是一段文本…

CorelDRAW2024设计新境界,等你解锁!

CorelDRAW&#xff0c;这款由加拿大Corel公司开发的平面设计软件&#xff0c;自从1989年问世以来&#xff0c;就以其强大的功能和用户友好的界面&#xff0c;在全球设计师中享有极高的声誉。今天&#xff0c;我们要聊的主角是它的最新版本——CorelDRAW 2024。 CDR永久版安装包…

材料物理 笔记-8

原内容请参考哈尔滨工业大学何飞教授&#xff1a;https://www.bilibili.com/video/BV18b4y1Y7wd/?p12&spm_id_frompageDriver&vd_source61654d4a6e8d7941436149dd99026962 或《材料物理性能及其在材料研究中的应用》&#xff08;哈尔滨工业大学出版社&#xff09; ——…

出租车计价器设计与实现(论文 + 源码)

关于java出租车计价器设计与实现.zip资源-CSDN文库https://download.csdn.net/download/JW_559/89304164 出租车计价器设计与实现 摘 要 在我国&#xff0c;出租车行业是八十年代初兴起的一项新兴行业&#xff0c;随着出租车的产生&#xff0c;计价器也就应运而生。但当时在全…

【异常】SpringBoot整合RabbitMQ-发送消息报错

错误信息 reply-code406, reply-textPRECONDITION_FAILED - inequivalent arg ‘x-message-ttl’ for queue ‘hello-queue’ in vhost ‘/lq’: received none but current is the value ‘10000’ of type ‘signedint’, class-id50, method-id10 错误原因 hello-queue这…

日志的基本用法

目标 1. 掌握如何设置日志级别 2. 掌握如何设置日志格式 3. 掌握如何将日志信息输出到文件中 1. logging模块 Python中有一个标准库模块logging可以直接记录日志 1.1 基本用法 import logging logging.debug("这是一条调试信息") logging.info("这是一条…

迪安诊断数智中心战略与PMO负责人徐黎明受邀为第十三届中国PMO大会演讲嘉宾

全国PMO专业人士年度盛会 迪安诊断技术集团股份有限公司数智中心战略与PMO负责人徐黎明先生受邀为PMO评论主办的2024第十三届中国PMO大会演讲嘉宾&#xff0c;演讲议题为“软件研发项目管理指标体系建设实践”。大会将于6月29-30日在北京举办&#xff0c;敬请关注&#xff01; …

01-项目功能,架构设计介绍

稻草快速开发平台 开发背景就是通过此项目介绍使用SpringBoot Vue3两大技术栈开发一个拥有动态权限、路由的前后端分离项目&#xff0c;此项目可以继续完善&#xff0c;成为一个模板为将来快速开发做铺垫。 实现功能 开发流程 通过命令构建前端项目在VSCode中开发&#xff…

【话题】Agent AI智能体的未来

大家好&#xff0c;我是全栈小5&#xff0c;欢迎阅读小5的系列文章&#xff0c;这是《话题》系列文章 目录 背景一、Agent AI智能体的角色二、Agent AI智能体的发展路径三、Agent AI智能体可能带来的挑战文章推荐 背景 随着Agent AI智能体的智能化水平不断提高&#xff0c;它们…

Llama3中文聊天项目全能资源库

Llama3 中文聊天项目综合资源库&#xff0c;集合了与Lama3 模型相关的各种中文资料&#xff0c;包括微调版本、有趣的权重、训练、推理、评测和部署的教程视频与文档。1. 多版本支持与创新&#xff1a;该仓库提供了多个版本的Lama3 模型&#xff0c;包括基于不同技术和偏好的微…

STK12 RPO模块学习(2)

一、Coast RPO Sequence 这个序列运行卫星直到它达到了下面三个条件之一。 1&#xff09;截至时间。2)圈数到达了限制。3&#xff09;其他条件&#xff0c;比如近地点。 默认情况下&#xff0c;Astrogator使用“Earth HPOP Default v10”预报器。你能够修改呈其他修改器。下…