模板初阶以及string类使用

模板初阶以及string类使用

    • 模板的简单认识
      • 1.泛型编程
      • 2.函数模板
        • 模板的原理图
        • 函数模板格式
        • 函数模板实例化
        • 非模板函数和模板函数的匹配原则
      • 3.类模板
        • 类模板的定义格式
        • 类模板的实例化
    • string
      • 1.string简介
      • 2.string常用的接口
    • 题目练习
      • 1.字符串相加
      • 2.字符串里面最后一个单词的长度
      • 3.翻转字符串区间

模板的简单认识

1.泛型编程

泛型编程:编写与类型无关的通用代码,是代码复用的一种手段。模板是泛型编程的基础。

实现加法:

//不使用模板,只使用函数重载,每一个需要的类型都需要写一份函数
int add(int a, int b)
{return a + b;
}double add(double a, double b)
{return a + b;
}int main()
{int a1 = 0;int b1 = 0;int c1 = add(a1, b1);double a2 = 0.1;double b2 = 0.5;double c2 = add(a2, b2);return 0;
}

两个函数只有类型上的不同,逻辑完全一致,能不能写一份表示逻辑的模板,让编译器帮我们生成函数呢?

2.函数模板

模板的原理图

模板的原理


函数模板格式

template<typename T1, typename T2,…,typename Tn>
返回值类型 函数名(参数列表){}

用函数模板来实现加法:

//模板不是具体的函数,真正的函数是由编译器去生成的
template<typename T>
T add(T a,T b)
{return a + b;
}
//typename是用来定义模板参数的关键字,也可以用classint main()
{int a1 = 0;int b1 = 0;int c1 = add(a1, b1);double a2 = 0.1;double b2 = 0.5;double c2 = add(a2, b2);return 0;
}

函数模板实例化

  1. 隐式实例化:由编译器依据实参来自行生成。
template<typename T>
T add(T a,T b)
{return a + b;
}int main()
{int a1 = 0;int b1 = 0;int c1 = add(a1, b1);//编译器生成int add(int a, int b);double a2 = 0.1;double b2 = 0.5;double c2 = add(a2, b2);//编译器生成double add(double a, double b);return 0;
}
  1. 显示实例化:在函数名后的<>中指定模板参数的实际类型

下面这个例子不显示实例化就会报错:

template<typename T>
T add(T a,T b)
{return a + b;
}int main()
{int a1 = 0;double b1 = 0.5;int c1 = add(a1, b1);//模板中两个参数类型是一致的,这里一个int,一个double,没有明确指定编译器无法生成函数return 0;
}

在这里插入图片描述
利用显示实例化解决:

template<typename T>
T add(T a,T b)
{return a + b;
}int main()
{int a1 = 0;double b1 = 0.5;double c1 = add<double>(a1, b1);//指定生成double add(double a,double b)并调用,和正常函数一样这里会进行隐式类型转换return 0;
}

非模板函数和模板函数的匹配原则

  1. 一个非模板函数可以和一个同名的函数模板同时存在,而且该函数模板还可以被实例化为这个非模板函数
//专门处理int
int add(int a, int b)
{return a + b;
}
//通用的函数模板
template<typename T>
T add(T a,T b)
{return a + b;
}int main()
{int a1 = 0;int b1 = 5;int c = add(a1, b1);//与非模板函数完全匹配,编译器不会生成c = add<int>(a1, b1); //指定编译器生成并调用//两个函数同时存在不冲突	return 0;
}
  1. 对于非模板函数和同名函数模板,如果其他条件都相同,在调动时会优先调用非模板函数而不会从该模板产生出一个实例。如果模板可以产生一个具有更好匹配的函数, 那么将选择模板
//专门处理int
int add(int a, int b)
{return a + b;
}
// 通用加法函数
template<class T1, class T2>
T1 add(T1 left, T2 right)
{return left + right;
}
int main()
{add(1, 2); // 与非函数模板类型完全匹配,不需要函数模板实例化add(1, 2.0); // 模板函数可以生成更加匹配的版本,编译器根据实参生成更加匹配的Add函数return 0;
}

3.类模板

类模板的定义格式

template<class T1, class T2, …, class Tn>
class 类模板名
{
// 类内成员定义
};

//和函数模板一样,这里并不是真正的类
template<class T>
class A
{
public:A(T a):_a(a){}//演示一下定义声明分离T get();
private:T _a;
};// 注意:类模板中函数放在类外进行定义时,需要加模板参数列表
template <class T>
T A<T>::get()
{return _a;
}

类模板的实例化

  类模板实例化需要在类模板名字后跟<>,然后将实例化的类型放在<>中即可,类模板名字不是真正的类,而实例化的结果才是真正的类。

int main()
{//A是类名,A<int>才是类型A<int> a(5);A<double> b(5.22);return 0;
}

string

1.string简介

在这里插入图片描述

  1. string是表示字符串的字符串类
  2. string类是basic_string模板类的一个实例,即typedef basic_string<char> string
  3. 该类的接口与常规容器的接口基本相同,再添加了一些专门用来操作string的常规操作。
  4. string是一个顺序容器,会自动扩容

2.string常用的接口

string类中有一个静态成员npos:static const size_t npos = -1;
本文只讲使用,不讲底层原理

  1. string类对象的常见构造
函数名称功能说明
string()
(常用)
构造空的string类对象,即空字符串
string(const char* s)
(常用)
用C字符串来构造对象
string(size_t n, char c)string类对象中前n个字符初始化为C
string(const string&s)
(常用)
拷贝构造
int main()
{string s1; // 构造空的string类对象s1string s2("hello"); // 用C格式字符串构造string类对象s2string s3(s2); // 拷贝构造s3return 0;
}

  1. string类对象的容量操作
函数名称功能说明
size_t size()
(常用)
返回有效字符数('\0’不算有效字符)
size_t length()和size()功能一致
size_t capacity()返回可存储有效字符的空间总大小,'\0’不算
bool empty()
(常用)
检查是否为空串,是返回true,否则返回false
void clear()
(常用)
清空字符串,变成空串
void reserve
(size_t n = 0)
(常用)
预留空间,n大于容量时扩容,不然什么都不做
void resize
(size_t n, char c)
n>有效字符数时从从字符串尾开始填充c直到字符串满;n>容量就先扩容再填充;n<有效字符数时缩短字符串,保留前n个字符。
int main()
{string s2("hello"); cout << s2.empty() << endl;s2.clear();//调用clear清理cout << s2.empty() << endl;cout << "capacity:" << s2.capacity() << endl;s2.reserve(100);//调用reserve预留空间cout << "reserve_capacity:" << s2.capacity() << endl;s2.resize(50, 'c');//填充cout << "s2:" << s2 << endl;s2.resize(10);//缩短到10字符cout << "s2:" << s2 << endl;return 0;
}

  1. string类对象的访问及遍历操作
函数名称功能说明
(const)char& operator ()运算符重载,可以像数组一样通过下标访问字符
(const_)iterator begin()和end()begin取第一个字符位置的迭代器,end取最后一个字符的下一个位置的迭代器(大家可以把迭代器想成指针,后面使用大家就明白了)
(const_)reverse_iterator rbegin()和rend()反向迭代器,使用和begin()一致,方向相反
范围forC++11支持,底层是迭代器
int main()
{string s2("hello"); //利用[]运算符重载遍历for (int i = 0; i < s2.size(); i++)cout << s2[i];cout << endl;//利用迭代器进行遍历,利用auto自动推导类型//这里是std::string::iteratorauto it = s2.begin();while (it != s2.end()){cout << *it;it++;}cout << endl;//反向迭代器遍历//这里是std::string::reverse_iteratorauto rit = s2.rbegin();while (rit != s2.rend()){cout << *rit ;rit++;}cout << endl;//范围for遍历for (auto ch : s2)cout << ch ;cout << endl;//修改for (auto& ch : s2)cout << ch ;return 0;
}

  1. string类对象的修改操作
函数名称功能说明
void push_back(char c)尾插一个字符c
string& append
(const char* s)
尾插一个字符串
string& operator+=()
(常用)
既可尾插字符串,也可单个字符,非常好用
const char* c_str()
(常用)
返回C格式字符串首地址
size_t find
(char c,size_t pos = 0)
(常用)
从pos位置开始寻找第一个出现c的位置并返回,否则返回npos
size_t rfind
(char c,size_t pos = npos)
从pos位置开始向前寻找第一次出现c的位置并返回,否则返回npos;当pos大于等于长度时,从尾开始向前搜索。(一般就是用这个函数搜索单个字符最后出现的位置)
string substr
(size_t pos = 0, size_t len = npos)
从pos位置开始截取len个字符,如果截取长度大于后面长度,就截取到字符串尾部结束,然后返回
1.string& insert
(size_t pos, size_t n, char c)
2.string& insert
(size_t pos, const char* s)
1.在pos位置插入n个c
2.在pos位置插入C格式字符串
int main()
{string s2("hello "); s2.push_back('w');s2.append("or");s2 += 'l';s2 += "dd!";cout << s2.c_str() << endl;cout << "pos(find):" << s2.find('w') << endl;cout << "pos(rfind):" << s2.rfind('d') << endl;if (s2.find('k') == std::string::npos)cout << "没找到" << endl;string sub = s2.substr(6, 6);cout << sub.c_str() << endl;//这里相当于头插'c's2.insert(0,1,'c');s2.insert(2,"hello ");return 0;
}

  1. string类非成员函数
函数功能说明
string operator+()先拷贝一份,实现尾插后返回,不改变原对象
operartor>>()
(常用)
输入运算符重载
operator<<()
(常用)
输出运算符重载
istream& getline
(istream& is, string& str)
读取一行字符,遇到’\n’才结束
bool operator>()    
(<,<=,>=,==,!=)
进行字符串比较
int main()
{string s2("hello "); string s3 = s2 + "world";cout << "s3:" <<  s3 << endl;cin >> s3;cout << "s3:" << s3 << endl;getchar();getline(cin, s3);//可以读取空格cout << "s3:" << s3 << endl;string s("hello");string s1("hellO");if (s == s1)cout << "s == s1" << endl;else if (s > s1)cout << "s > s1" << endl;else if (s < s1)cout << "s < s1" << endl;return 0;
}

题目练习

1.字符串相加

链接 :字符串相加


题目要求:
在这里插入图片描述


题解:
在这里插入图片描述

class Solution {
public:string addStrings(string num1, string num2) {//用来遍历int end1 = num1.size()-1;int end2 = num2.size()-1;//用来记录进位int flag = 0;int sum = 0;string str;while(end1 >= 0 || end2 >= 0){//只有不越界的情况才给值,否则给0int x1 = end1>=0?num1[end1]-'0':0;int x2 = end2>=0?num2[end2]-'0':0;sum = flag + x1 + x2;//这里使用尾插,头插效率比较慢str += ('0'+sum%10);flag = sum/10;end1--;end2--;}//还需要处理一种特殊情况,比如"9"+"1",同时结束刚好进位,需要补1if(flag == 1)str += '1';//数据是尾插的,需要逆置//reverse属于stl中的算法//只需要传入迭代器区间就能实现逆置reverse(str.begin(),str.end());return str;}
};

2.字符串里面最后一个单词的长度

链接:字符串里面最后一个单词的长度


题目要求:
在这里插入图片描述


题解:

#include <iostream>
#include<string>
using namespace std;int main() 
{string str;getline(cin,str);//直接调用rfind找最后一个空格的位置//没有找到说明只有一个单词,直接返回长度int pos = str.rfind(' ');if(pos == std::string::npos)cout << (str.size()) << endl;elsecout << (str.size()-(pos+1));
}

3.翻转字符串区间

链接:翻转字符串区间


题目要求:
在这里插入图片描述


题解:

class Solution 
{
public:string reverseStr(string s, int k) {int index1 = 0;int index2 = k-1;//每2k个字符中反转前k个字符//"abcdefg" ->前4个反转前2个,"abcd"->"bacd","efg"->"feg"while(index2 <= s.size()-1){reverse(s.begin()+index1,s.begin()+index2+1);index1 += 2*k;index2 += 2*k;}//最后一段小于k的全部反转reverse(s.begin()+index1,s.end());return s;}
};

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

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

相关文章

【瑞吉外卖】Git部分学习

Git简介 Git是一个分布式版本控制工具&#xff0c;通常用来对软件开发过程中的源代码文件进行管理。通过Git仓库来存储和管理这些文件&#xff0c;Git仓库分为两种&#xff1a; 本地仓库&#xff1a;开发人员自己电脑上的Git仓库 远程仓库&#xff1a;远程服务器上的Git仓库…

CVE漏洞复现-CVE-2021-3493 Linux 提权内核漏洞

CVE-2021-3493 Linux 提权内核漏洞 漏洞描述 CVE-2021-3493 用户漏洞是 Linux 内核中没有文件系统中的 layfs 中的 Ubuntu over 特定问题&#xff0c;在 Ubuntu 中正确验证有关名称空间文件系统的应用程序。buntu 内核代码允许低权限用户在使用 unshare() 函数创建的用户命名…

线上电影购票选座H5小程序源码开发

搭建一个线上电影购票选座H5小程序源码需要一些基本的技术和步骤。以下是一个大致的搭建过程&#xff0c;可以参考&#xff1a; 1. 确定需求和功能&#xff1a;首先要明确你想要的电影购票选座H5小程序的需求和功能&#xff0c;例如用户登录注册、电影列表展示、选座购票、订单…

【Java可执行命令】(二十一)线程快照生成工具 jstack:帮助开发人员分析和排查线程相关问题(死锁、死循环、线程阻塞...)

Java可执行命令之jstack 1️⃣ 概念2️⃣ 优势和缺点3️⃣ 使用3.1 语法格式3.2 使用步骤及技巧3.3 使用案例 4️⃣ 应用场景&#x1f33e; 总结 1️⃣ 概念 jstack 命令是 Java Development Kit&#xff08;JDK&#xff09;中提供的一项诊断工具&#xff0c;用于生成Java虚拟…

WHQL认证中HCK和HLK的区别

开发者或硬件制造商要通过WHQL认证获得微软数字签名或是Windows徽标的使用权限&#xff0c;就需要使用WHQL认证的测试工具&#xff08;HCK或HLK&#xff09;对硬件设备或驱动程序进行测试。HCK和HLK其实是一个系列的测试工具&#xff0c;HCK和HLK的主要区别是用于测试不同Windo…

pytest测试框架之fixture测试夹具详解

fixture的优势 ​ pytest框架的fixture测试夹具就相当于unittest框架的setup、teardown&#xff0c;但相对之下它的功能更加强大和灵活。 命名方式灵活&#xff0c;不限于unittest的setup、teardown可以实现数据共享&#xff0c;多个模块跨文件共享前置后置可以实现多个模块跨…

JAVA SpringBoot 项目 多线程、线程池的使用。

1.1 线程&#xff1a; 线程就是进程中的单个顺序控制流&#xff0c;也可以理解成是一条执行路径 单线程&#xff1a;一个进程中包含一个顺序控制流&#xff08;一条执行路径&#xff09; 多线程&#xff1a;一个进程中包含多个顺序控制流&#xff08;多条执行路径&#xff0…

天津农商银行智能加密锁管理工具常见问题

天津农商银行智能加密锁管理工具&#xff0c;在使用过程中&#xff0c;可能出现一些莫名的错误&#xff0c;针对亲身遇到的坑&#xff0c;分享给大家&#xff0c;以备不时之需。 一、转账业务导入文件中文汉字出现乱码&#xff0c;如下图。 原因是文件编码不正确&#xff0c;…

Java项目作业~ 创建基于Maven的Java项目,连接数据库,实现对站点信息的管理,即实现对站点的新增,修改,删除,查询操作

需求&#xff1a; 创建基于Maven的Java项目&#xff0c;连接数据库&#xff0c;实现对站点信息的管理&#xff0c;即实现对站点的新增&#xff0c;修改&#xff0c;删除&#xff0c;查询操作。 以下是站点表的建表语句&#xff1a; CREATE TABLE websites (id int(11) NOT N…

收钱吧与火山引擎VeDI合作一年后 有了哪些新变化?

更多技术交流、求职机会&#xff0c;欢迎关注字节跳动数据平台微信公众号&#xff0c;回复【1】进入官方交流群 收钱吧正在和火山引擎数智平台&#xff08;VeDI&#xff09;跑出一条业务提效新通路。 相关数据显示&#xff0c;收钱吧的日服务人次就近5000万&#xff0c;累计服务…

测评HTTP代理的透明匿名?

在我们日常的网络冒险中&#xff0c;你是否曾听说过HTTP代理的透明匿名特性&#xff1f;这些神秘的工具就像是网络世界中的隐身斗士&#xff0c;让我们能够在互联网的迷雾中保护自己的身份和隐私。那么&#xff0c;让我们一起揭开HTTP代理的面纱&#xff0c;探索其中的奥秘吧&a…

el-table实现指定列合并

table传入span-method方法可以实现合并行或列&#xff0c;方法的参数是一个对象&#xff0c;里面包含当前行row、当前列column、当前行号rowIndex、当前列号columnIndex四个属性。该函数可以返回一个包含两个元素的数组&#xff0c;第一个元素代表rowspan&#xff0c;第二个元素…

Qt多线程编程

本章介绍Qt多线程编程。 1.方法 Qt多线程编程通常有2种方法&#xff1a; 1)通过继承QThread类&#xff0c;实现run()方法。 2)采用QObject::moveToThread()方法。 方法2是Qt官方推荐的方法&#xff0c;本文介绍第2种。 2.步骤 1)创建Worker类 这里的Worker类就是我们需要…

数学·包含学科简介

数学包含学科简介 14 逻辑与基础 ▪ 1410:演绎逻辑学 ▪ 1420:证明论 ▪ 1430:递归论 ▪ 1440:模型论 ▪ 1450:公理集合论 ▪ 1460:数学基础 ▪ 1499:数理逻辑与数学基础其他学科 17 数论 ▪ 1710:初等数论 ▪ 1720:解析数论 ▪ 1730:代数数论 ▪ 1740:超越数论 ▪ 1750:丢…

FPGA开发:音乐播放器

FPGA开发板上的蜂鸣器可以用来播放音乐&#xff0c;只需要控制蜂鸣器信号的方波频率、占空比和持续时间即可。 1、简谱原理 简谱上的4/4表示该简谱以4分音符为一拍&#xff0c;每小节4拍&#xff0c;简谱上应该也会标注每分钟多少拍。音符时值对照表如下图所示&#xff0c;这表…

大模型老是胡说八道怎么办?哈佛大学提出推理干预ITI技术有效缓解模型幻觉现象

论文链接&#xff1a;https://arxiv.org/abs/2306.03341 代码仓库&#xff1a;https://github.com/likenneth/honest_llama 近来与ChatGPT有关的大模型的话题仍然处于风口浪尖&#xff0c;但是大家讨论的方向已经逐渐向大语言模型的实际应用、安全、部署等方面靠近。虽然大模型…

Gartner发布《2023年全球RPA魔力象限》:90%RPA厂商,将提供生成式AI自动化

8月3日&#xff0c;全球著名咨询调查机构Gartner发布了《2023年全球RPA魔力象限》&#xff0c;通过产品能力、技术创新、市场影响力等维度&#xff0c;对全球16家卓越RPA厂商进行了深度评估。 弘玑Cyclone&#xff08;Cyclone Robotics&#xff09;、来也&#xff08;Laiye&am…

(九)人工智能应用--深度学习原理与实战--前馈神经网络实现MNST手写数字识别

目标: 识别手写体的数字,如图所示: 学习内容: 1、掌握MNIST数据集的加载和查看方法 2、熟练掌握Keras建立前馈神经网络的步骤【重点】 3、掌握模型的编译及拟合方法的使用,理解参数含义【重点】 4、掌握模型的评估方法 5、掌握模型的预测方法 6、掌握自定义图片的处理与预测 …

Modelsim恢复编辑器的解决方案——只能将外部编辑器删除后,重新匹配编辑器

Modelsim恢复编辑器的解决方案——只能将外部编辑器删除后&#xff0c;重新匹配编辑器 1&#xff0c;Modelsim和Questasim是相互兼容的&#xff0c;配置的编辑器变成了sublime&#xff0c;且更换不了编辑器2&#xff0c;解决问题的方案&#xff0c;还是没得到解决3&#xff0c;…

Rpc原理

dubbo原理 1、RPC原理 一次完整的RPC调用流程&#xff08;同步调用&#xff0c;异步另说&#xff09;如下&#xff1a; 1&#xff09;服务消费方&#xff08;client&#xff09;调用以本地调用方式调用服务&#xff1b; 2&#xff09;client stub接收到调用后负责将方法、参数…