C++【泛型编程】【string类常用接口】学习

目录

泛型编程

推演实例化

显示实例化

类模板

类模板的声明和定义分离

STL

string 

string的构造和拷贝构造

选取特定字符串拷贝 

 解析:

关于npos的解析

验证

从一个字符串中拷贝前几个字符

解析:

注意:

验证:

size()& length()

string::operator[ ]

迭代器对string进行访问

capacity

capacity的扩容机制

在g++下

 ​编辑

在VS22下

reserve

​编辑

无数据扩容:

在VS22底下运行

在g++底下运行

​编辑

无数据缩容:

在VS22底下

在g++底下 

有数据缩容

在VS22底下

 在g++底下

总结:

resize

重新分配字符串长度

在VS22

 在g++下

resize是既影响空间,又影响数据

operator+= 

insert

 pos位置插入一个实例对象

pos位置插入一个实例对象的子字符串

pos位置直接插入字符串

erase

​编辑

清楚部分字符串

find

 rfine

c_str

substr

find_first_of

getline


泛型编程

泛型编程是跟具体类型无关的代码,关键字template(模板)

什么是模板?

意思就是说写一个swap函数,针对不同的类型,我需要写很多很多种

void swap(int a, int b);
void swap(double a, double b);
void swap(char a, char b);
void swap(short a, short b);
……

有了模板之后,就可以套模板 ,就相当于套公式一样的简单了

模板有推演实例化和显示实例化

推演实例化

template<typename T>
typename 可以改为 class,typename是类型名的意思
void swap(T& a,T& b){T temp = a;a = b;b = temp;
} 
int main() {int a = 1, b = 2;double c = 1.1, d = 2.2;printf("原来我的a是%d,b是%d\n", a, b);Swap(a, b);printf("现在我的a是%d,b是%d\n", a, b);printf("原来我的c是%lf,d是%lf\n", c, d);Swap(c, d);printf("现在我的c是%lf,d是%lf\n", c, d);return 0;
}

 

所以面对要写众多函数,我一个函数模板就搞定了

当然还可以多参数

template<class A,class B>
void fun(A& a, B& b) {cout << a << "  " << b << endl;
}void test2() {int a = 1;double b = 2.0;char c = 'd';int* p = &a;fun(a, c);fun(b, p);
}int main() {test2();return 0;
}

给它参数,让模板自己推那是什么吧

以上都是推演实例化

显示实例化

下面看一个返回类型的模板

template<class T>
T* fun1() {T* p = new T[10];return p;
}

 当我们创建出这个模板的时候,我们就会面临一个问题,就是当我们没有办法去推演这个T应该是什么类型的时候

此刻,推演不了,那我们就要告诉它,它应该返回什么类型的值

void test3() {int* ret = fun1<int>();
}

在函数后面告诉这个函数,你应该是个什么样的值,函数名<类型>

当两者功能一样的普通函数和函数模板同时存在的时候

如果参数是普通函数有的,则直接用现成的,如果不是普通参数有的,则会先走函数模板

类模板

类模板都是显示实例化

普通类中,类名就是类型

类模板中,类名就不是类型了,要类名<数据类型>才是整个类的类型

那么为什么要有类模板

当我写一个栈的时候,正常的写法是:

class Stack {
private:int* _a;int _top;int _capacity;
public:Stack(int n = 4){_a = new int[n];_top = 0;_capacity = n;}~Stack(){delete[] _a;_a = nullptr;_top = _capacity = 0;}};

当我想要构建整型栈的时候很容易,很轻松,直接实例化对象即可

那,当我想要构建 double 栈的时候呢???整型栈类还能派上用场吗,显然是不能的

需要将 int* _a; 改为 double* _a;

需要将 _a = new int [n] 改为 _a = new double [n]; 

这就意味着我要写两个类呀,极其不方便,所以有了类模板

template<class T>
class Stack {
private:T* _a;int _top;int _capacity;
public:Stack(int n = 4) {cout << "wogouzaole" << endl;_a = new T[n];_top = 0; _capacity = n;}~Stack(){cout << "xigou" << endl;delete[] _a;_a = nullptr;_top = _capacity = 0;}
};
int main() {Stack<int> s1;Stack<double> s2;return 0;
}

比如Stack<int> 和 Stack<double>是两个不同的类型

他们两个不是同一个类型,即类模板实例化是不同类型,得到的类也是不同的

问题:

那么写出了不同类型的模板后,相应的构造函数是否也需要跟着改变呢?

回答:

我们首先要知道构造函数是函数名跟类名相同,而 Stack<T>是什么,是类型,不是类名

所以构造函数不能够

        Stack<T>() {

        }

而要继续

        Stack(){

        }

类模板的声明和定义分离

1,类模板的函数声明和定义分离要在同一个文件

2,定义要在前头加上类的类型 ,即        类<类型>

template<class T>
class Stack {
private:T* _a;int _top;int _capacity;
public:Stack(int n = 4);~Stack();
};template<class T>
Stack<T>::Stack(int n) {cout << "wogouzaole" << endl;_a = new T[n];_top = 0; _capacity = n;
}template<class T>
Stack<T>::~Stack() {cout << "xigou" << endl;delete[] _a;_a = nullptr;_top = 0;_capacity = 0;
}

STL

STL只是C++标准库的其中一部分,STL是标准模板库的缩写,它是C++标准库的重要组成部分

STL数据结构和算法运用较为广泛,下面的string就是STL里面的一个模板之一 

string 

使用string模板的时候需要引入头文件 #include<string>

string的构造和拷贝构造

跟我们平常写的类差不多类型 

	string s1;                //(1)string s2("hell0 string");//(4)string s3 = s2;           //(2)

选取特定字符串拷贝 

substring (3)

string (const string& str, size_t pos, size_t len = npos);

 解析:

(3) substring constructor

Copies the portion of str that begins at the character position pos and spans len characters (or until the end of str, if either str is too short or if len is string::npos).

从str对象里拷贝一部分字符串,长度从你选取开始的地方到跨越的长度,如果字符串太短或者len  = -1 的话,就直接到末尾

关于npos的解析

npos是size_t 类型的,即无符号整数

而-1是什么,-1在底层的补码形式是 11111111 11111111 11111111 11111111

如果给到无符号整数的话,那么这个值就可以认为其是无穷大的,所以 npos = -1 的时候就可以认为是无限大

验证

从一个字符串中拷贝前几个字符

from sequence (5)
string (const char* s, size_t n);

解析:

Copies the first n characters from the array of characters pointed by s.

注意:

它跟string (const string& str, size_t pos, size_t len = npos);不同的是,它的第一个显示参数是const char* s ,而不是str 

所以如果用str的话,会被当作string (const string& str, size_t pos, size_t len = npos);来执行,执行结果就是从str的第五个位置开始,将此后的所有字符串拷贝,违背了我们想要拷贝前几个字符的初衷

验证:

size()& length()

功能:计算字符串长度,size和length不包含\0

string::operator[ ]

它有两种重载,一种const,一种非const

它的功能是返回的是字符串一个指定位置的引用,用法可以参考数组

	for (size_t i = 0; i < s2.size(); i++) {cout << s2[i] << " ";}cout << endl;

s[i]的本质是s.operator[ ](i)

如果没有const修饰的话,还可以修改:s[i] = 'x';

迭代器对string进行访问

	string::iterator it = s2.begin();while (it != s2.end()) {cout << *it << " ";it++;}

iterator 就像是用指针的方式进行遍历,iterator的访问方式是可以线性的访问,在今后的在物理空间上非连续的容器中能够大展身手,基于此特点迭代器是容器的主流访问形式

const_iterator 和 const iterator 有着本质的区别:

const_iterator的本质是保护迭代器指向的数据*it 不被修改

const iterator 的本质是保护迭代器本身不能修改,即 it 不能修改


capacity

capacity的扩容机制

 1 #include <iostream>2 #include <string>3 using namespace std;4 5 int main(){6   string s1("hello string");7   size_t old = s1.capacity();8   cout<<old<<endl;9   for(size_t i=0;i<1000;i++){                                                                                                                                                       10     s1.push_back('x');11     if(old!=s1.capacity()){12       cout<<s1.capacity()<<endl;13       old = s1.capacity();14     }15   }16   return 0;17 }

在g++下

 

g++很省,基本上是你字符串有多少就给你多少空间,并且每次达到扩容机制的时候都是2倍2倍的扩,很有规律

在VS22下

capacity在VS22下大概是每次呈1.5倍以此扩容 


reserve

无数据扩容:

确定自己需要多少空间,就可以使用reserve,有时候给多了可能是因为考虑到了对齐规则,不同的平台可能是不同的,扩容机制和空间机制都是一样的,根据平台而定

int main() {string s1;cout<<s1.capacity()<<endl;s1.reserve(100);cout << s1.capacity() << endl;s1.reserve(200);cout << s1.capacity() << endl;return 0;
}
在VS22底下运行

在g++底下运行

Linux会老老实实的开

无数据缩容:

在VS22底下

在g++底下 

在无数据地下会缩成我们想要的结果

有数据缩容

在VS22底下
int main() {string s1 = "hello reverse";cout << "s1的长度是" << s1.size() << endl;cout << "s1的原始容量是" << s1.capacity() << endl;s1.reserve(10);cout << "缩容后s1的长度是" << s1.size() << endl;cout << "缩容后s1的长度是" << s1.capacity() << endl;return 0;
}

 换成13

它的数据量受到保护不会变,容量也不会变

 在g++底下

总结:

reserve扩容机制可根据自己想要的空间来去指定,但最后得到的空间可能会有多不少,具体看不同的编译器;缩容的时候,会很好的保护数据。


resize

重新分配字符串长度

在VS22
int main() {string s1 = "hello resize";cout << "s1的长度是" << s1.size() << endl;cout << "s1的原始容量是" << s1.capacity() << endl;cout << endl;s1.resize(100);cout << "resize重分配后s1的长度是" << s1.size() << endl;cout << "resize重分配后s1的原始容量是" << " "; cout<< s1.capacity() << endl;return 0;
}

 resize重新开辟的空间,补充的是'\0'

 在g++下

g++还是一如既往的省吃俭用

resize是既影响空间,又影响数据

可以看出,一旦resize规划的大小比原来小,就会把一些数据除去,留下前几位

>capacity 扩容+尾插

capacity>=resize()>size() 尾插

size()>resize() 容量不变,但数据会直接丢失,即删除数据,保留前n个

resize更多的是开空间和初始化        


operator+= 

想要什么直接在它屁股后面加就好了,不用管那么多的 


insert

 pos位置插入一个实例对象

string& insert (size_t pos, const string& str);

pos位置插入一个实例对象的子字符串

string& insert (size_t pos, const string& str, size_t subpos, size_t sublen); 

Inserts a copy of a substring of str. The substring is the portion of str that begins at the character position subpos and spans sublen characters (or until the end of str, if either str is too short or if sublen is npos).

大致意思就是插入一个实例对象的子字符串,从子字符串的pos位置开始,到某个长度为止

eg:从字符串s1第六个位置插入,选择s2中,从第0个位置开始的后9个字符插入

pos位置直接插入字符串

string& insert (size_t pos, const char* s);Inserts a copy of the string formed by the null-terminated character sequence (C-string) pointed by s.

从s字符串中拷贝一份插入到第pos位置

 

 pos位置插入n个连续的字符

string& insert (size_t pos, size_t n, char c);

Inserts n consecutive copies of character c.

还有很多就不一一举例了 


erase

作用就是,清除字符串,减少长度

清楚部分字符串

string& erase (size_t pos = 0, size_t len = npos);


find

find既能找字符串,又能找字符

 

 rfine

与fine查找方向是相反的


c_str

可以使一个实例对象转换为由一个指针指向的字符串数组

一般在文件转换的时候能够使用到

 

int main() {string file_name("test.cpp");FILE* fout = fopen(file_name.c_str(), "r");char ch = fgetc(fout);while (ch != EOF) {cout << ch;ch = fgetc(fout);}
}

 


substr

切割字符串 ,参数是起始位置跟长度


find_first_of

Find character in string

Searches the string for the first character that matches any of the characters specified in its arguments.

就是找任何在目标字符串里面的字符

int main ()
{std::string str ("Please, replace the vowels in this sentence by asterisks.");std::size_t found = str.find_first_of("aeiou");while (found!=std::string::npos){str[found]='*';found=str.find_first_of("aeiou",found+1);}std::cout << str << '\n';return 0;
}
Pl**s*, r*pl*c* th* v*w*ls *n th*s s*nt*nc* by *st*r*sks.

结果就是屏蔽掉了所有有关"aeiou" 

它跟find_last_of 的区别就是,last是反着来找

与之相反的是

find_first_not_of 和 find_last_not_of

 


getline

我们在事件中不免会用上输入输出

如果我们想要对一个string实例化对象s1,进行输入的时候我们会先如何

	string s1;cin >> s1;

接着再用cout对其进行打印出来

 

但是我们却发现,只打印出了hello,我的getline却不见了

但我换成这样又能读了

 

但是我的getline却给了s2

这是为何?

在 C++ 中,使用 cin 读取字符串时,如果输入的字符串中包含空格那么 cin 会一直读取到遇到第一个空格为止。因此,当我输入 "hello getline" 时,cin 会首先读取 "hello" 并将其存储在 s1 中。

此时,"getline" 仍然在输入缓冲区中,因为 cin 没有读取它。

接下来,当我尝试读取 s2 时,使用同样的 cin >> s2;cin 会立即从输入缓冲区中读取下一个单词 "getline",因为它是在之前的输入中留下的。这就是为什么不需要再次输入,s2 就已经被赋值了

 因此为了避免这种情况,需要使用getline这个函数接口

此刻便能一整句的将字符串输出来

涉及到两个参数,一个是流提取,另一个是实例化对象 

以上便是本次博文的学习内容了,如有大佬能够指点出论文错误,将不胜感激,谢谢阅读!

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

第13周 简历职位功能开发与Zookeeper实战

第13周 简历职位功能开发与Zookeeper实战 本章概述1. Mysql8窗口函数over使用1.1 演示表结构与数据1.2 案例1:获取男女总分数1.3 案例2****************************************************************************************本章概述 1. Mysql8窗口函数over使用 参考案例…

C++客户端Qt开发——Qt窗口(菜单栏)

Qt窗口是通过QMainWindow类来实现的。 QMainWindow是一个为用户提供主窗口程序的类&#xff0c;继承自QWidget类&#xff0c;并且提供了一个预定义的布局。QMainWindow包含一个菜单栏(menu bar)、多个工具栏(tool bars)、多个浮动窗口&#xff08;铆接部件)(dock widgets、一个…

算法从零到精通 (一) ~ 快慢双指针

1. 前言 快慢双指针是一种常用的算法技巧&#xff0c;通常用于解决涉及链表或数组的问题。它的基本思想是使用两个指针&#xff0c;一个移动速度快&#xff08;快指针&#xff09;&#xff0c;一个移动速度慢&#xff08;慢指针&#xff09;&#xff0c;来解决特定的问题。这两…

Vue中el的两种写法

大家好我是前端寄术区博主PleaSure乐事。今天了解到了Vue当中有关el的两种写法&#xff0c;记录下来与大家分享&#xff0c;希望对大家有所帮助。 方法一 解释 第一种方法我们直接用new创建并初始化一个新的 Vue 实例&#xff0c;并定义了 Vue 实例的数据对象&#xff0c;在给…

低代码如何加速数字化转型

数字化转型&#xff0c;正日益决定企业成功的关键。这里的一个关键因素是它可以以更快的速度和质量来实施技术计划。在当今瞬息万变的商业环境中&#xff0c;战略性地采用低代码平台对于旨在加快上市时间、增强业务敏捷性和促进跨团队无缝协作的首席技术官来说至关重要。日益增…

动手学深度学习——6.循环神经网络

1.序列模型 处理序列数据需要统计工具和新的深度神经网络架构。 为了简单起见&#xff0c;我们以 图8.1.1所示的股票价格&#xff08;富时100指数&#xff09;为例。 图8.1.1 近30年的富时100指数 其中&#xff0c;用&#x1d465;&#x1d461;表示价格&#xff0c;即在时间…

江科大/江协科技 STM32学习笔记P6

文章目录 LED闪烁&LE流水&蜂鸣器一、操作STM32的GPIO步骤二、RCC库函数什么是AHB与APB&#xff1f; 三、GPIO库函数GPIO初始化选择IO接口工作方式 四、四种方法实现LED闪灯 LED闪烁&LE流水&蜂鸣器 一、操作STM32的GPIO步骤 1、使用RCC开启GPIO的时钟 2、使用…

UE/Unity加载倾斜摄影太卡问题-使用局部网格简化重构导出为FBX/OBJ

工具 OSGB源数据灵易智模倾斜摄影编辑平台(下称OPEditor) 与另一篇文章里描述的导出时指定LOD层级的网格简化效果的区别 本功能属于导出时指定LOD层级的网格简化方法的升级版&#xff0c;可以基于某一LOD层级的局部数据进行进一步拓扑重构与纹理重烘焙自定义程度较高&#xff…

西蒙学习法

西蒙学习法 《世界十大学习方法》之西蒙学习法

Python 基于 Django 的内容管理系统库之feincms使用详解

概要 在现代 Web 开发中,内容管理系统(CMS)已经成为管理和发布内容的重要工具。FeinCMS 是一个基于 Django 的简单且灵活的内容管理系统,它专注于提供一种轻量级但功能强大的 CMS 解决方案。对于开发者来说,FeinCMS 提供了一种易于扩展和定制的方式,可以满足不同项目的需…

MongoDB教程(二十一):MongoDB大文件存储GridFS

&#x1f49d;&#x1f49d;&#x1f49d;首先&#xff0c;欢迎各位来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里不仅可以有所收获&#xff0c;同时也能感受到一份轻松欢乐的氛围&#xff0c;祝你生活愉快&#xff01; 文章目录 引言一、GridFS…

数据库概念以及增删改

1.概念 、 2.通用语法 3.数据增删改

在 Postman 中设置全局 token

目录 问题描述解决方案 问题描述 在使用 Postman 进行接口测试时&#xff0c;经常会遇到在 Header 中添加 token 的情况。当接口数量较多时&#xff0c;需要为每个接口进行设置&#xff0c;而且当 token 失效时需要重新获取并设置&#xff0c;这样一来效率较低。 解决方案 下…

Python | Leetcode Python题解之第283题移动零

题目&#xff1a; 题解&#xff1a; class Solution:def moveZeroes(self, nums: List[int]) -> None:n len(nums)left right 0while right < n:if nums[right] ! 0:nums[left], nums[right] nums[right], nums[left]left 1right 1

TikTok Shop全托管上线JIT,并预计10月开放西班牙和爱尔兰站点

据悉&#xff0c;TikTok Shop官方近期在其全托管平台上正式推出了JIT&#xff08;Just-In-Time&#xff09;生产模式&#xff0c;这一创新举措彻底颠覆了传统供应链流程&#xff0c;实现了“先有订单&#xff0c;再精准供货”的高效运营模式。对于广大卖家而言&#xff0c;这无…

师资培训丨AIGC 技术与大模型应用开发实战线下广州班莅临泰迪智能科技参观调研

7月23日&#xff0c;2024年第二期全国数字人才技能提升师资培训班——AIGC 技术与大模型应用开发实战线下广州班莅临广东泰迪智能科技股份有限公司产教融合实训基地参观调研&#xff0c;来自全国各地三十多名高校教师参与本次活动。泰迪智能科技董事长张良均、校企合作经理吴桂…

PostgreSQL的学习心得和知识总结(一百四十九)|psql 的使用技巧:设置、预设、回显和已保存的查询

目录结构 注&#xff1a;提前言明 本文借鉴了以下博主、书籍或网站的内容&#xff0c;其列表如下&#xff1a; 1、参考书籍&#xff1a;《PostgreSQL数据库内核分析》 2、参考书籍&#xff1a;《数据库事务处理的艺术&#xff1a;事务管理与并发控制》 3、PostgreSQL数据库仓库…

rk3588s 定制版 USB adb , USB2.0与USB3.0 区别,adb 由typeC 转换到USB3.0(第二部分)

硬件资源&#xff1a; rk3588s 核心板定制的地板 软件资源&#xff1a; 网盘上的 android12 源码 1 硬件上 客户只想使用 type c 接口中的 usb2.0 OTG 。在硬件上&#xff0c;甚至连 CC芯片都没有连接。 关于一些前置的知识。 1 USB2.0 与 USB3.0 的区别。 usb3.0 兼容2.0 …

秋招复习笔记——八股文部分:网络TCP

TCP 三次握手和四次挥手 TCP 基本认识 序列号&#xff1a;在建立连接时由计算机生成的随机数作为其初始值&#xff0c;通过 SYN 包传给接收端主机&#xff0c;每发送一次数据&#xff0c;就「累加」一次该「数据字节数」的大小。用来解决网络包乱序问题。 确认应答号&#xf…

NOIP图论 最小生成树——Prim算法(详细图解)

最小生成树的概念 经典题目 prim算法简介 prim算法解析 &#xff08;详细图解&#xff09; 代码实现 代码实战 最小生成树的概念 在一给定的无向图G (V, E) 中&#xff0c;(u, v) 代表连接顶点 u 与顶点 v 的边&#xff0c;而 w(u, v) 代表此的边权重&#xff0c;若存在 …