c++学习之mystring的简单封装

news2025/2/24 9:34:49

我们经常利用string类实例化对象来对字符串进行各种操作,string类是一个实用的类,那么对于string类的一些基本操作是如何实现的呢?我们简单的实现一下mystring的封装。

目录

1.常用的字符串函数

2.构造函数的创建

1.无参构造

2.有参构造

3.拷贝构造

析构

3.运算符的重载

1.重载输出运算符

2.重载输入运算符

3.重载+运算符

4.重载赋值运算符

5.重载比较运算符

重载>运算符

重载<运算符

重载==运算符


首先我们给出类模板:

其中主要的操作有:1,构造函数的实现 2,运算符的重载 。

对于string类的基本实现,我们知道string类是对字符串的操作,因此私有变量是字符指针和字符串的大小这两个成员,用来表示字符。其次就是对于字符指针,在这里我们为字符指针是专门开辟一片空间用来存放字符串的。

class mystring
{
	friend::ostream& operator<<(ostream& out, mystring  a);
	friend::istream& operator>>(istream& in, mystring &a);
public:
	mystring();//默认构造
	mystring(char* arr);//有参构造
	mystring(const mystring& p);//拷贝构造
	~mystring();
   int getsize()
	   {
		   return  size;
	   }//获取大小
	//实现对字符串的访问,重载[]
   //这里将返回值进行引用,之后可以改变原本身的元素
   char &operator[](int index)
   {
	   //判断位置是否合法
	   if (index > 0 && index < size)
	   {
		   return arr[index];
	   }
	   else
	   {
		   cout << "下标越界" << endl;
		   exit(-1);
	   }
	   
   }
//成员函数实现
   mystring operator+(mystring&a);
   mystring operator+ (char* str);
   mystring operator=(mystring a);
   mystring operator=(char* str);
   bool operator>(mystring a);
   bool operator<(mystring a);
   bool operator==(mystring a);
private:
	char* arr;
	int size;
};

其次对于成员函数我们在函数未定义,对于全局函数,例如输入输出我们需要设置为友元函数来实现对类中成员的访问。

1.常用的字符串函数

strcpy

常用的字符串拷贝函数,将右边的const char*的字符串赋值给左边的字符串。

strcat

 

字符串追加函数,将右边的字符串追加给左边字符串的末尾,也就是连接两个字符串。

 

memset函数

将该字符串中的前多少元素初始化为什莫,比如我们将实现对申请的一片字符指针arr的空间初始化为0,memset(arr,0,strlen(arr)+1),将arr中的所有字符初始化为0.

2.构造函数的创建

1.无参构造

无参构造主要是将字符指针初始化为空,大小为零。

mystring::mystring()
{
    arr = NULL;
    size=0;
}

2.有参构造

有参构造传递字符串以实现初始化类中的字符指针,以及对大小的确定。

mystring::mystring( char* arr)
{
	this->arr = new char[strlen(arr)+1];//申请空间
	memset(this->arr, 0, strlen(arr)+1);//初始化全设置为0
	strcpy(this->arr, arr);//实现拷贝
	size = (int)strlen(arr) ;
}

注意这里是给指针专门开辟空间,所以对于指针在析构时,我们需要释放空间。

3.拷贝构造

拷贝原类改变为新类

mystring::mystring(const mystring& p)
{
	
	size = p.size;
	this->arr = new char[size+ 1];
	memset(arr, 0, strlen(p.arr) + 1);//初始化全设置为0
	strcpy(this->arr,p.arr);//实现拷贝
	
}

拷贝构造实现形式与构造函数的形式一样。

析构

mystring ::~mystring()
{
	if (arr != NULL)
	{
		delete[]arr;
		arr = NULL;
	}
}

 因为是对指针开辟空间,对应要释放空间。

3.运算符的重载

1.重载输出运算符

//重载输出运算符(全局重载)
   ostream& operator<<( ostream&out,mystring  a)
  {
	   out << a.arr ;
	   return out;
  }

与之前学习到的重载输出运算符一样,返回类型为输出流,操作对象是mystring类。

注意对于输入与输出运算符的重载,我们都需要将返回值引用,实现对输入输出的所有操作。

2.重载输入运算符

重载输入运算符需要注意,原类中的字符指针是否为空,不为空要置空,然后再创建一个mystring作为媒介实现输入,之后再赋值,反回输入流。

//重载输入运算符
   istream& operator>>(istream&in, mystring &a)
   {

	   char buffer[100];
	   in >> buffer;
	   //判断是否为空
	   if (a.arr != NULL)
	   {
		   delete[]a.arr;
		   a.arr = NULL;
	   }
	   a.size =(int)strlen(buffer);
	   a.arr = new char[a.size+1];
	   //置空
	   memset(a.arr, 0, a.size + 1);//注意这里不能用strlen(a.arr),在这里是未知访问
	   strcpy(a.arr, buffer);
	   return in;
   }

3.重载+运算符

+运算符在string类中的操作是字符串的连接。

这里需要注意的是,我们是对字符串类的对象与字符串类+重载的实现,字符串类的对象与字符串+重载也是需要实现的,因为字符串类实例化的对象我们是将他当作字符串用的。

字符串类对象间的重载与字符指针的重载是类似的,主要是对其中的字符串的实现。

 //字符串与类对象+的重载
   mystring mystring::operator+(char* str)
   {
	   mystring str1;
	   str1.size = (int)strlen(str)+this->size;
	   str1.arr = new char[str1.size + 1];
	   memset(str1.arr, 0, str1.size);
	   strcpy(str1.arr, this->arr);
	   strcat(str1.arr, str);
	   return str1;
   } 
  //重载加法运算符  类与类之间+重载
  mystring mystring:: operator+(mystring& a)
   {
	   mystring str1;//作为媒介
	   str1.size = this->size+a.size;
	   str1.arr = new char[str1.size+1];
	   memset(str1.arr, 0, str1.size);
	   strcpy(str1.arr, this->arr);
	   strcat(str1.arr, a.arr);
	   return str1;
   }

两者的重载都是创建第三个类作为媒介,用来作为连接字符串后的字符串的载体,也是所返回的对象。因此在开辟空间的时候,需要注意空间的大小。

4.重载赋值运算符

string类中赋值运算符的作用就是字符串拷贝,但是是深度拷贝,所以我们需要开辟一片空间,对于类原this中所指向的空间实现地址的交换,即空间的交换。

还需要注意的是,这里的操作对象可以是类的对象值之间,也可以是类的对象直接与字符串直接的运算。

重载赋值运算符(只有指针成员时,需要深拷贝)
  mystring mystring:: operator=(mystring a)
  {
	  //先判断是否为空
	  if (this->arr != NULL)
	  {
		  delete[]arr;
		  arr = NULL;
	  }
	  if (this->arr != NULL)
	  {
		  delete[]arr;
		  arr = NULL;
	  }
	  //这里是深拷贝,即地址之间的交换
	  this->size = a.size;
	  this->arr = new char[a.size+1];
	  memset(this->arr, 0, a.size);
	  strcpy(this->arr, a.arr);
	 
	  return *this;
  }

这里在赋值时,我们还是需要判断一下这里的原this中的指针是否为空,不为空,我们要将它置空之后再进行拷贝。

mystring mystring::operator=(char* str)
  {
	  if (this->arr != NULL)
	  {
		  delete[]arr;
		  arr = NULL;
	  }
	  //这里是深拷贝,即空间之间的交换
	  this->arr = new char[strlen(str)+1];
	  memset(this->arr, 0, strlen(str));
	  strcpy(this->arr, str);
	  this->size = strlen(str);
	  return *this;
	  
  }

5.重载比较运算符

重载比较运算符是比较简单的,即>  < ==,显然他们的返回值都布尔型的。

重载>运算符

//重载>运算符
  bool mystring:: operator>(mystring a)
  {
	  if (this->size > a.size)
	  {
		  return true;
	  }
	  else
	  {
		  return false;
	  }
  }

重载<运算符

//重载<运算符
  bool mystring:: operator<(mystring a)
  {
	  if (this->size < a.size)
	  {
		  return true;
	  }
	  else
	  {
		  return false;
	  }
  }

重载==运算符

//重载==运算符
  bool mystring:: operator==(mystring a)
  {
	  if (this->size == a.size)
	  {
		  return true;
	  }
	  else
	  {
		  return false;
	  }
  }

 如下是我所给出的操作用例,

int main()
{
	mystring str=(char *)"hello world";
	//mystring str ((char*)"hello world");
	cout << str << endl;
	mystring str1 = (char*)"haha";
	cout << str+str1 << endl;
	cout << str + (char *)"haha" << endl;
	str = str1;
	cout << str << endl;
	str = (char*)"heiehi";
	cout << str << endl;
	if (str >str1)
	{
		cout << "str大与str1" << endl;
	}
	else
	{
		cout << "str小与str1" << endl;
	}

}

 好了,对于string的简单的实现就完成了,在此基础上我们还可以完成他的所有操作,在cplusplus上我们可以看到string所给出的定义string - C++ Reference (cplusplus.com)

STL中给出了string类的标准定义,以尽可能满足我们对字符串的某些操作,这些操作大家可以下去慢慢实现。

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

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

相关文章

Java面试知识点(全)- Java面试基础部分二

[Java面试知识点(全)(https://nanxiang.blog.csdn.net/article/details/130640392)&#xff1a; 导航&#xff1a; https://nanxiang.blog.csdn.net/article/details/130640392 注&#xff1a;随时更新 TPS&QPS TPS&#xff1a;是Transactions PerSecond的缩写&#xff0…

elment-ui/plus不定高度容器收缩折叠动画组件

文章目录 学习链接效果代码 学习链接 原生js手动实现一个多级菜单效果&#xff08;高度可过渡变化&#xff09; - 自己的链接 vue实现折叠展开收缩动画 - 自己的链接 效果 代码 在使用element-plus的折叠组件的时候&#xff0c;一般用的是<el-collapse>组件&#xff0…

Vector - CAPL - CANoe硬件配置函数 - 04

目录 getChipType -- 确定当前所用的CAN控制器类型 代码示例 setCanCabsMode -- 设置 CANcab 模式 代码示例 setOcr -- 设置输出寄存器 代码示例 setBtr -- 设置位时序寄存器BTR 代码示例 getChipType -- 确定当前所用的CAN控制器类型 功能&#xff1a;确定所用 CAN 控制…

身边不动点定理的有意思应用

最近读高观点下的数学这本书&#xff0c;对书中介绍的布劳威尔不动点定理的有趣性质印象很深&#xff0c;原因是这个定理的某些性质能够解释我们生活中的一些常见现象&#xff0c;这里结合一个例题&#xff0c;聊以记录。 从一个数学题讲起&#xff1a; f(x)是定义在[0,1]上的…

Netty 服务端开发及性能优化

Netty 是一个异步基于事件驱动的高性能网络通信框架&#xff0c;可以看做是对 NIO 和 BIO 的封装&#xff0c;并提供了简单易用的 API、Handler 和工具类等&#xff0c;用以快速开发高性能、高可靠性的网络服务端和客户端程序。 1. 创建服务端 服务端启动需要创建 ServerBoot…

面试官说,Java中的volatile关键字有什么作用?

在Java中&#xff0c;volatile是一个关键字&#xff0c;它用于标记变量&#xff0c;以指示该变量可能随时被多个线程访问并修改。从面试的角度来看&#xff0c;了解volatile关键字的作用和原理对于Java开发人员来说非常重要。在本文中&#xff0c;我将详细讲解volatile关键字的…

springboot+vue班级综合测评管理系统(源码+文档)

风定落花生&#xff0c;歌声逐流水&#xff0c;大家好我是风歌&#xff0c;混迹在java圈的辛苦码农。今天要和大家聊的是一款基于springboot的班级综合测评管理系统。项目源码以及部署相关请联系风歌&#xff0c;文末附上联系信息 。 &#x1f495;&#x1f495;作者&#xff1…

prometheus中通过node-exporter中的--collector.textfile.directory这一选项参数自定义监控指标

简述node-exporter中该选项参数的作用。 --collector.textfile.directory 是 Node Exporter 的一个命令行选项&#xff0c;用于指定从 textfile 收集器中收集数据的目录。 Node Exporter 会通过各种方式收集主机的度量值&#xff0c;并将这些度量值暴露给 Prometheus。其中之…

【嵌入式烧录刷写文件】-2.3-删除/修改Intel Hex文件中指定地址范围内的数据

案例背景&#xff08;共6页精讲&#xff09;&#xff1a; 有如下一段HEX文件&#xff0c;如何“自动”地完成地址范围0x9110-0x9113数据的删除或修改。 :2091000058595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F70717273747576775F :2091200078797A7B7C7D7E7F808182838485…

C++ STL之 list 基础

文章目录 前言STL之list基础知识1. list的介绍2. list的使用2.1 list的构造2.2 list iterator的使用2.3 空间相关2.4 元素访问2.5 相关函数2.6 list的迭代器失效 3. list与vector的对比 后记 前言 本篇将学习 list 的基础知识 &#x1f57a;作者&#xff1a; 迷茫的启明星 专栏…

网络安全从业人员职业发展和规划

1、为什么做这次分享&#xff1f; 2、人生周期三模型 3、职业生涯阶段划分 4、通用职业发展路径 5、当前安全行业前景如何&#xff1f; 6、安全就业行情如何&#xff1f; 7、安全行业就业市场岗位划分 8、什么是相对比较好的履历&#xff1f; 9、选择甲方还是选择乙方&#xf…

Prompt learning 教学[技巧篇]:通过增加示例、引导词、特殊符号指令等方式让chatgpt输出更好的答案

Prompt learning 教学[技巧篇]&#xff1a;通过增加示例、引导词、特殊符号指令等方式让chatgpt输出更好的答案 技巧1&#xff1a;To Do and Not To Do 在问答场景里&#xff0c;为了让 AI 回答更加准确&#xff0c;一般会在问题里加条件。比如让 AI 推荐一部电影给你 Recomme…

【高数+复变函数】傅里叶变换

文章目录 【高数复变函数】傅里叶变换3 傅里叶变换3.1 基本概念3.2 单位脉冲函数及其傅里叶变换3.3 非周期函数的频谱 上一节 【高数复变函数】傅里叶积分 【高数复变函数】傅里叶变换 3 傅里叶变换 3.1 基本概念 回顾&#xff1a;上一节中的Fourier积分公式 f ( t ) 1 2…

前端二进制流的关系

Blob 全称&#xff1a;binary large object&#xff0c;二进制大对象&#xff0c;是一个js对象&#xff0c;可以用来存储大量二进制编码格式的数据&#xff0c;Blob对象是不可修改的&#xff0c;读取内容的唯一方法是FileReader。 创建一个Blob对象&#xff1a; new Blob(ar…

SSM(Vue3+ElementPlus+Axios+SSM前后端分离)--后端实现

目录 SSM(Vue3ElementPlusAxiosSSM前后端分离)--后端实现 技术栈 实现功能04-添加家居信息 需求分析/图解 思路分析 代码实现 创建\service\FurnService.java 和\service\FurnServiceImpl.java, 增加添加方法 修改Furn.java , 当创建Furn 对象imgPath 为null 时, imgPa…

Java14-常用类:字符串,日期类,比较器

一&#xff1a;字符串&#xff1a;String 1.概述&#xff1a; String&#xff1a;字符串&#xff0c;使用一对""引起来表示。 1.String 声明 为final的&#xff0c;不可被继承 2.String 实现了Serializable接口&#xff1a;表示字符串是支持序列化的。 实现了Co…

多线程相关高频面试题

一、线程的基础知识 1、线程和进程的区别&#xff1f; 进程是正在运行程序的实例&#xff0c;进程中包含了线程&#xff0c;每个线程执行不同的任务。不同的进程使用不同的内存空间&#xff0c;在当前进程下的所有线程可以共享内存空间。线程更轻量&#xff0c;线程上下文切换…

GPIO口输出与输入模式的理解

问题&#xff1f;看GPIO的结构图&#xff0c;发现&#xff1a; 上拉输入电流是从引脚流入外部 下来输入电流是从引脚流进芯片内部 推挽输出推模式电流是从引脚流入外部 推挽输出挽模式电流是从外部流入内部 输入输出模式都有电流流入流出&#xff0c;为什么还要分为输入输出模…

K8s排错之浏览器打不开K8s Dashboard

一、问题 10.0.0.10 通常会使用加密技术来保护您的信息。Chrome 此次尝试连接到 10.0.0.10 时&#xff0c;该网站发回了异常的错误凭据。这可能是因为有攻击者在试图冒充 10.0.0.10&#xff0c;或者 Wi-Fi 登录屏幕中断了此次连接。请放心&#xff0c;您的信息仍然是安全的&am…

【饿了么UI】elementUI密码框图标实现睁眼和闭眼效果(阿里巴巴iconfront图标库vue项目本地引用)

elementUI中输入框的密码框属性&#xff0c; 默认是一个始终睁眼的图标&#xff0c;测试今天提bug要有闭眼效果&#xff08;无大语&#xff09;… 因为elementUI中的icon没有闭眼的&#xff0c;所以还要去iconfront下载引入 效果图&#xff1a; 点击后 一、下载图标 http…