当前位置: 首页 > news >正文

C++入门篇7---string类

所谓的string类,其实就是我们所说的字符串,本质和c语言中的字符串数组一样,但是为了更符合C++面向对象的特性,特地将它写成了一个单独的类,方便我们的使用

对其定义有兴趣的可以去看string类的文档介绍,这里就不做过多的介绍了

一、了解string类的接口,及其相关的功能

1.构造函数相关接口

(constructor)函数名称功能说明
string()构造空的string对象,即空字符串
string(const char*s)用C中的字符串构造string类
string(size_t n,char c)用n个c字符创建string对象
string(const string& s)

 拷贝构造  

#include<iostream>
#include<string>
using namespace std;
int main()
{string s1;string s2("hhh");string s3(3,'a');string s4(s2);cout << s1 << endl;cout << s2 << endl;cout << s3 << endl;cout << s4 << endl;return 0;
}

 2. string类对象的容量操作

函数名称功能说明
size返回字符串的有效长度,'\0'除外
length返回字符串的有效长度,和上面一个函数功能一样
capacity返回空间大小(即共能存放多少个字符,'\0'除外)
empty检查字符串是否为空
clear清空字符串,但一般不释放空间,即capacity不变
reserve为字符串预留空间,减少扩容次数
resize将有效字符的个数改成n个,多出来的空间用字符c(传入参数)填充
shrink_to_fit将字符串的capacity缩小至和size一样大,(一般不用)
#include<iostream>
#include<string>
using namespace std;
int main()
{string s("hello world");cout << s << endl;cout << s.size() << endl;cout << s.length() << endl;cout << s.capacity() << endl;cout << s.empty() << endl;cout << "------------" << endl;s.clear();cout << s << endl;cout << s.size() << endl;cout << s.length() << endl;cout << s.capacity() << endl;cout << s.empty() << endl;cout << "------------" << endl;s.reserve(100);cout << s << endl;cout << s.size() << endl;cout << s.length() << endl;cout << s.capacity() << endl;cout << s.empty() << endl;cout << "------------" << endl;s.resize(10, 'a');cout << s << endl;cout << s.size() << endl;cout << s.length() << endl;cout << s.capacity() << endl;cout << s.empty() << endl;cout << "------------" << endl;return 0;
}

注意:1. resize(size_t n) 与 resize(size_t n, char c)都是将字符串中有效字符个数改变到n个,不同的是当字符个数增多时:resize(n)用0来填充多出的元素空间,resize(size_t n, char c)用字符c来填充多出的元素空间。注意:resize在改变元素个数时,如果是将元素个数增多,可能会改变底层容量的大小,如果是将元素个数减少,底层空间总大小不变。

2.reserve(size_t n = 0)为string预留空间,不改变有效元素个数,当reserve的参数小于
string的底层空间总大小时,reserver不会改变容量大小。

3.string类对象的访问及遍历操作

函数名称功能说明
operator[ ]返回pos位置的字符
begin+endbegin获取第一个字符的迭代器+end获取最后一个字符下一个位置的迭代器
rbegin+rendrbegin获取最后一个字符的迭代器+rend获取第一个字符前一个位置的迭代器
范围forC++11支持更简洁的范围for的新遍历方式
#include<iostream>
#include<string>
using namespace std;
int main()
{string x = "hello world";//本质是隐式类型转化+拷贝构造,即调用构造函数创建临时变量,然后拷贝构造,编辑器优化后是一个构造函数string::iterator it1 = x.begin();//正向迭代器//这里不建议用it1<x.end(),因为string类的迭代器it1++底层是指针后移,//但是其他类的迭代器不一定是这样实现的,而!=是通用的while (it1 != x.end()){cout << *it1 << " ";++it1;}cout << endl;string::reverse_iterator it2 = x.rbegin();//逆向迭代器while (it2 != x.rend()){cout << *it2 << " ";++it2;}cout << endl;for (auto& s : x)//底层实现就是上面的正向迭代器{cout << s << " ";}cout << endl;for (int i = 0; i < x.size(); i++){cout << x[i] << " ";}const string y = "good game";string::const_iterator it3 = y.begin();//具有常属性的对象的迭代器写法string::const_reverse_iterator it4 = y.rbegin();return 0;
}

 

 4.string类对象的修改操作

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

 下面是一些测试用例,可以去自己调试调试,当然还有写其他的用法没写,有兴趣可以去查查文档,一般来说下面的用法就够用了

void test1()
{string x;x.push_back('a');x.push_back('b');x.push_back('c');cout << x << endl;x.append("def");cout << x << endl;x += 'e';cout << x << endl;x += "fgh";cout << x << endl;
}void test2()
{string x = "test.txt";FILE* fp = fopen(x.c_str(), "w");//...//当我们调用C语言中的一些需要类似char*参数的相关接口时,//我们就需要将string转成C语言中的字符串,进行调用fclose(fp);
}void test3()
{string s = "hello world";size_t p = s.find('l');//默认从起始位置开始找if (p != string::npos)//没找到时会返回nposcout << p << " " << s[p] << endl;p = s.find('l',5);//从下标为5的位置开始找if (p != string::npos)cout << p << " " << s[p] << endl;p = s.find("world");//默认从其实位置开始找if (p != string::npos)cout << p << " " << s[p] << endl;p=s.find("world",3);//从下标为3的位置开始找if (p != string::npos)cout << p << " " << s[p] << endl;p = s.find("word", 1, 2);//从下标1开始找和word前两个字符匹配的地方if (p != string::npos)cout << p << " " << s[p] << endl;//string x = "word";//p = s.find(x, 1);//从下标1开始在s中找x,也可以默认从0开始//rfind用法和find用法一样
}void test4()
{string x = "you are right";cout << x.substr(0, 3) << endl;//从下标0开始往后取3个字符返回,返回类型是stringcout << x.substr(4, 3) << endl;//从下标4开始往后取3个字符返回,返回类型是stringcout << x.substr(8, 5) << endl;//从下标8开始往后取5个字符返回,返回类型是string
}int main()
{//test1();//test3();//test4();return 0;
}

5.string类的非成员函数介绍

函数名称功能说明
operator++运算符重载
operator>>输入运算符重载
operator<<输出运算符重载
getline获取一行字符串

上面的函数就不一一枚举用法了,基本一看就懂,不确定的可以去查查文档,或者自己调试看看

总结:string相关的接口一般就是这些,还有些不常用没写,如果感兴趣可以去查查文档,学完后可以去找些题目来练练,其实很快就能记住string的常用接口用法

二、实现string类的常用接口

#include<iostream>
using namespace std;
#include<assert.h>
namespace zxws
{class string{public:string(const char* str = ""):_size(strlen(str)), _capacity(strlen(str)){_str = new char[_capacity + 1];strcpy(_str, str);}void swap(string& tmp){std::swap(_str, tmp._str);std::swap(_size, tmp._size);std::swap(_capacity, tmp._capacity);}string(const string& s):_str(nullptr),_size(0),_capacity(0){string tmp(s._str);swap(tmp);}~string(){delete[] _str;_str = nullptr;_size = _capacity = 0;}const char* c_str() const{return _str;}string& operator=(string tmp){swap(tmp);return *this;}char& operator[](size_t pos){assert(pos < _size);return _str[pos];}const char& operator[](size_t pos) const{assert(pos < _size);return _str[pos];}size_t size() const{return _size;}size_t capacity()const{return _capacity;}void reserve(size_t n){if (n > _capacity){char* tmp = new char[n + 1];strcpy(tmp, _str);delete[] _str;_str = tmp;_capacity = n;}}void resize(size_t n,char x = '\0'){if (n <= _size){_str[n] = '\0';_size = n;}else{reserve(n);while (n--){push_back(x);}}}void push_back(char x){if (_size == _capacity)reserve(_capacity == 0 ? 4 : _capacity * 2);_str[_size++] = x;_str[_size] = '\0';}void append(const char* str){size_t len = strlen(str);if (_size + len > _capacity)reserve(_size + len);strcpy(_str+_size, str);_size += len;}void append(size_t n, char x){reserve(_size + n);while (n--){push_back(x);}}string& operator+=(char x){push_back(x);return *this;}string& operator+=(const char* str){append(str);return *this;}size_t find(char x, size_t pos = 0){assert(pos < _size);for (size_t i = pos; i < _size; i++){if (x == _str[pos])return i;}return npos;}size_t find(const char* str, size_t pos = 0){assert(pos < _size);char* p = strstr(_str, str);return p == nullptr ? npos : p - _str;}void insert(size_t pos, char x){assert(pos <= _size);reserve(_size + 1);for (size_t i = _size + 1; i > pos; i--){_str[i] = _str[i - 1];}_str[pos] = x;_size++;}void insert(size_t pos, const char* str){assert(pos < _size);size_t len = strlen(str);reserve(_size + len);for (size_t i =_size+1,j=_size+len ; i > pos; i--,j--){_str[j] = _str[i - 1];}strncpy(_str + pos, str, len);_size += len;}void erase(size_t pos,size_t n=npos){assert(pos < _size);if (n == npos || pos + n >= _size){_str[pos] = '\0';_size = pos;}else{for (size_t i = pos, j = pos + n; j <= _size; i++, j++){_str[i] = _str[j];}_size -= n;}}typedef char* iterator;typedef const char* const_iterator;iterator begin(){return _str;}const_iterator begin() const{return _str;}iterator end(){return _str + _size;}const_iterator end() const{return _str + _size;}string substr(size_t pos,size_t n=npos) const{assert(pos < _size);string tmp;size_t end = pos + n;if (n == npos || pos + n >= _size){n = _size - pos;end = _size;}tmp.reserve(n);for (size_t i = pos; i < end; i++)tmp += _str[i];return tmp;}bool operator<(const string& s) const{return strcmp(_str, s._str) < 0;}bool operator==(const string& s) const{return strcmp(_str, s._str) == 0;}bool operator<=(const string& s) const{return *this<s||*this==s;}bool operator>(const string& s) const{return !(*this <= s);}bool operator>=(const string& s) const{return !(*this < s);}bool operator!=(const string& s) const{return !(*this == s);}void clear(){_str[0] = '\0';_size = 0;}private:char* _str;size_t _size;size_t _capacity;const static size_t npos;friend ostream& operator<<(ostream& cout, const string& s);friend istream& operator>>(istream& cin, const string& s);};const size_t string::npos = -1;ostream& operator<<(ostream& cout, const string& s){for (size_t i = 0; i < s._size; i++){cout << s[i];}return cout;}istream& operator>>(istream& cin, string& s){s.clear();char buff[129] = { 0 };char x = getchar();int i = 0;while (x == ' ' || x == '\n')x = getchar();while (x != '\n' && x != ' '){buff[i++] = x;if (i == 128){buff[i] = '\0';s += buff;i = 0;}x = getchar();}if (i) {buff[i] = '\0';s += buff;}return cin;}
};

相关文章:

C++入门篇7---string类

所谓的string类&#xff0c;其实就是我们所说的字符串&#xff0c;本质和c语言中的字符串数组一样&#xff0c;但是为了更符合C面向对象的特性&#xff0c;特地将它写成了一个单独的类&#xff0c;方便我们的使用 对其定义有兴趣的可以去看string类的文档介绍&#xff0c;这里…...

2308d的静态构造函数循环依赖示例

原文 //Steve: __gshared string[string] dict; shared static this() {dict ["a" : "b"]; }这里有两个论点:这不能是CRT构造器,因为它依赖于D运行时,并且认为它应该进入自己的模块是一个QoL问题,当你想要私有到类而不是私有到模块时,可为类提供它,因为语…...

Linux 目录和文件常见操作

就常见的命令&#xff1a; pwd pwd 显示当前的目录 目录迁移 我以如下的目录大致结构做一个简单的例子 cd 迁移到指定的路径&#xff0c;可以指定相对路径和绝对路径&#xff0c;默认相对 .指向当前路径&#xff0c;…/ 指向上一级的目录。 ls 列出文件及其目录 命令选…...

不基于比较的排序:基数排序

本篇只是讨论桶排序的具体实现&#xff0c;想了解更多算法内容可以在我的博客里搜&#xff0c;建议大家看看这篇排序算法总结&#xff1a;排序算法总结_鱼跃鹰飞的博客-CSDN博客 桶排序的原理&#xff1a; 代码&#xff1a;sort1是一个比较二逼的实现方式浪费空间&#xff0c;s…...

shell和反弹shell

文章目录 是什么&#xff1f;bash是什么&#xff1f;反弹shell 是什么&#xff1f; Shell 是一个用 C 语言编写的程序&#xff0c;它是用户使用 Linux 的桥梁。Shell 既是一种命令语言&#xff0c;又是一种程序设计语言。 Shell 是指一种应用程序&#xff0c;这个应用程序提供了…...

构建Docker容器监控系统(Cadvisor +Prometheus+Grafana)

Cadvisor PrometheusGrafana 1.1、Cadvisor产品简介 Cadvisor是Google开源的一款用于展示和分析容器运行状态的可视化工具。通过在主机上运行Cadvisor用户可以轻松的获取到当前主机上容器的运行统计信息&#xff0c;并以图表的形式向用户展示。 1.2、安装docker-ce [rootloc…...

java实现文件的下载

系统日志的获取不可能每次都登录服务器&#xff0c;所以在页面上能够下载系统运行的日志是必须的 如何来实现日志的下载&#xff0c;这样的一个功能 前端我们用到的是window.open(...)这样可以发送一个get请求到后台 后台接收到get请求之后&#xff0c;如何实现对文件的下载 R…...

分享Python技术下AutojsPro7云控代码

引言 有图有真相&#xff0c;那短视频就更是真相了。下面是三大语言的短视频。 Java源码版云控示例&#xff1a; Java源码版云控示例在线视频 Net源码版云控示例&#xff1a; Net源码版云控示例在线视频亚丁号-知识付费平台 支付后可见 扫码付费可见 Python源码版云控示例…...

【Linux】网络通信

【Linux】网络通信 文章目录 【Linux】网络通信1、网络基础1.1 计算机网络1.2 网络模型TCP & UDP1&#xff09;IP地址2&#xff09;端口3&#xff09;TCP协议与UDP协议的比较 1.3 网络传输1.3.1 传输逻辑1.3.2 传输条件1.3.3 传输流程 1.4 地址管理 2、网络编程2.1 基本概念…...

【mysql】—— 表的约束

目录 序言 &#xff08;一&#xff09;空属性 &#xff08;二&#xff09;默认值 &#xff08;三&#xff09;列描述 &#xff08;四&#xff09;zerofill &#xff08;五&#xff09;主键 &#xff08;六&#xff09;自增长 &#xff08;七&#xff09;唯一键 &#…...

jeecgboot 登录成功默认其他路由

util.js...

【1572. 矩阵对角线元素的和】

来源&#xff1a;力扣&#xff08;LeetCode&#xff09; 描述&#xff1a; 给你一个正方形矩阵 mat&#xff0c;请你返回矩阵对角线元素的和。 请你返回在矩阵主对角线上的元素和副对角线上且不在主对角线上元素的和。 示例 1&#xff1a; 输入&#xff1a;mat [[1,2,3]…...

GaussDB 开发篇+Java调用JDBC访问openGauss数据库

★ 数据库信息 ✔ 数据库版本&#xff1a;openGauss 5.0.0 ✔ 数据库端口&#xff1a;5432 ✔ 数据库名称&#xff1a;db_zzt ★ Java代码 package PAC_001;import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sq…...

钕铁硼永磁材料基本概念

目录 一、何为磁性材料二、永磁材料的主要性能三、永磁材料的历史四、永磁材料的分类五、钕铁硼永磁材料5.1 产业链5.2 生产工艺 之前也写过其他行业的一些生产过程和工艺流程&#xff0c;大家有兴趣的可以翻翻以前的文章。 一、何为磁性材料 参加过九年义务教育的同学应该都知…...

2005-2020年280个地级市绿色全要素生产率测算原始数据

2005-2020年280个地级市绿色全要素生产率测算原始数据 1、时间&#xff1a;2005-2020年 2、来源&#xff1a;中国城市统计年鉴、中国区域统计年鉴、中国能源年鉴、中国环境年鉴等 3、范围&#xff1a;280个地级市 4、指标&#xff1a;年末单位从业人员数、规模以上工业企业…...

电流的测量(反馈电流表)

另一方面&#xff0c;反馈电流表使用不同的方法来产生电流测量&#xff08;见图 3&#xff09;。他们使用有源跨阻放大器将电流转换为电压读数。电压输出是电流输入的倒数乘以反馈电阻器 R F的值。 V输出 -I输入* R F 图 3. 反馈电流表方法使用有源跨阻放大器将电流转换为…...

白帽黑帽与linux安全操作

目录 白帽黑帽 Linux安全 白帽黑帽 白帽&#xff08;White Hat&#xff09;和黑帽&#xff08;Black Hat&#xff09;通常用于描述计算机安全领域中的两种不同角色。白帽黑客通常被认为是合法的安全专家&#xff0c;他们通过合法途径寻找和修复安全漏洞&#xff0c;帮助企业和…...

【TypeScript】进阶之路语法细节,类型和函数

进阶之路 类型别名(type)的使用接口(interface)的声明的使用二者区别&#xff1a; 联合类型和交叉类型联合类型交叉类型 类型断言获取DOM元素 非空类型断言字面量类型的使用类型缩小&#xff08;类型收窄&#xff09;TypeScript 函数类型函数类型表达式内部规则检测函数的调用签…...

每日一题 611有效三角形的个数(相向双指针)

题目 给定一个包含非负整数的数组 nums &#xff0c;返回其中可以组成三角形三条边的三元组个数。 示例 1: 输入: nums [2,2,3,4] 输出: 3 解释:有效的组合是: 2,3,4 (使用第一个 2) 2,3,4 (使用第二个 2) 2,2,3示例 2: 输入: nums [4,2,3,4] 输出: 4 题解 class Solu…...

Flink源码之JobMaster启动流程

Flink中Graph转换流程如下&#xff1a; Flink Job提交时各种类型Graph转换流程中&#xff0c;JobGraph是Client端形成StreamGraph后经过Operator Chain优化后形成的&#xff0c;然后提交给JobManager的Restserver&#xff0c;最终转发给JobManager的Dispatcher处理。 Completa…...

Python训练第四十三天

DAY 43 复习日 作业&#xff1a; kaggle找到一个图像数据集&#xff0c;用cnn网络进行训练并且用grad-cam做可视化 进阶&#xff1a;并拆分成多个文件 import torch import torch.nn as nn import torch.optim as optim from torchvision import datasets, transforms, models …...

基于深度学习的裂缝检测与分割研究方向的 数据集介绍

目录 一、基于深度学习的裂缝检测与分割研究方向 1. 任务定义与挑战 2. 主流方法与技术演进 3. 实际应用优化 二、裂缝检测与分割常用数据集详解 1. SDNET2018 2. CrackTree&#xff08;CrackTree200&#xff09; 3. AigleRN 4. CFD&#xff08;Concrete Crack Detect…...

Linux: network: switch:arp cache更新规则 [chatGPT]

文章目录 介绍概念普通包带有不同的mac,是否更新arp cache?普通包带有相同的mac,是否刷新 aging timeswitch是否会主动学习介绍 关于arp cache在switch侧的行为。有很多问题需要理解。 概念 HP L3 - IP Services Configuration Guide 文档里有写:dynamic arp entry的解说…...

Vue3 中使用 i18n

Vue3 中使用i18n 在 Vue 3 中使用国际化&#xff08;i18n&#xff09;可以通过官方的 vue-i18n 库来实现。vue-i18n 是专门为 Vue 应用设计的国际化解决方案&#xff0c;支持多语言切换、动态内容插值等功能。 以下是如何在 Vue 3 中使用 vue-i18n 的详细步骤&#xff1a; 1.…...

Cursor 工具项目构建指南: Python 3.8 环境下的 Prompt Rules 约束

简简单单 Online zuozuo: 简简单单 Online zuozuo 简简单单 Online zuozuo 简简单单 Online zuozuo 简简单单 Online zuozuo :本心、输入输出、结果 简简单单 Online zuozuo : 文章目录 Cursor 工具项目构建指南: Python 3.8 环境下的 Prompt Rules 约束前言项目简介技术栈…...

Redisson简明教程—你家的锁芯该换了

1.简介 各位攻城狮们&#xff0c;你还在使用原生命令来上锁么&#xff1f;看来你还是不够懒&#xff0c;饺子都给你包好了&#xff0c;你非要吃大饼配炒韭菜&#xff0c;快点改善一下“伙食”吧&#xff0c;写代码也要来点幸福感。今天咱们就来聊聊Redisson提供的各种锁&#…...

从 LeetCode 到日志匹配:一行 Swift 实现规则识别

文章目录 摘要描述题解答案题解代码分析示例测试及结果时间复杂度空间复杂度总结 摘要 在开发中我们经常遇到“模式匹配”的问题&#xff0c;比如日志分类、用户意图识别、甚至是在一些权限系统中做规则映射判断。这类问题的本质是判断两个结构是否具有一致的对应关系。LeetCo…...

山西省第十八届职业院校技能大赛 网络建设与运维赛项 样题

山西省第十八届职业院校技能大赛 网络建设与运维赛项 &#xff08;学生组&#xff09; 样题 2024 年 11 月 xx 日 2 赛题说明 一、竞赛项目简介 “网络建设与运维”竞赛共分为模块一&#xff1a;网络理论测试与网络 运维&#xff1b;模块二&#xff1a; 网络建设与调试&a…...

【设计模式-4.8】行为型——中介者模式

说明&#xff1a;本文介绍行为型设计模式之一的中介者模式 定义 中介者模式&#xff08;Mediator Pattern&#xff09;又叫作调节者模式或调停者模式。用一个中介对象封装一系列对象交互&#xff0c;中介者使各对象不需要显式地互相作用&#xff0c;从而使其耦合松散&#xf…...

深入解析C++五大常用设计模式:原理、实现与应用场景

设计模式是解决特定软件设计问题的经典方案&#xff0c;掌握它们能显著提升代码的可维护性和扩展性。本文详细解析C中五种最常用的设计模式&#xff0c;附带完整代码示例和实战技巧。 一、设计模式概述 设计模式是面向对象编程中可复用的解决方案&#xff0c;它们源于工程师们…...