string类的模拟实现以及oj题

news2024/11/15 12:08:25

前言

上篇博客实现了string类的begin()、end()、构造函数、析构函数、c_str、size()、clear()、capacity()、[ ]、reserve()、push_back、append()、insert()、+=。这篇博客实现剩下的一些重要功能。

string类的模拟实现

string.h

#include<iostream>
#include<string>
#include<assert.h>
#include<string.h>

using namespace std;

namespace stringbyself
{
	class string
	{
	public:
		typedef char* iterator;
		typedef const char* const_iterator;

		//编译器开始
		iterator begin()
		{
			return _str;
		}
		//编译器结束
		iterator end()
		{
			return _str + _size;
		}

		const_iterator begin() const
		{
			return _str;
		}

		const_iterator end() const
		{
			return _str+_size;
		}

		//构造函数
		string(const char* str = "")
		{
			_size = strlen(str);
			_capacity = _size;
			_str = new char(_size + 1);
			strcpy(_str, str);
		}

		//析构
		~string()
		{
			if (_str)
			{
				delete[] _str;
				_str = nullptr;
				_size = _capacity = 0;
			}
		}

		//c_str
		const char* c_str() const
		{
			return _str;
		}

		//clear
		void clear()
		{
			_str[0] = '\0';
			_size = 0;
		}

		//size
		size_t size() const
		{
			return _size;
		}

		//capacity
		size_t capacity() const
		{
			return _capacity;
		}

		//[]
		char& operator[](size_t pos)
		{
			assert(pos < _size);
			return _str[pos];
		}

		const char& operator[](size_t pos) const
		{
			assert(pos < _size);
			return _str[pos];
		}

		void reserve(size_t n);
		void push_back(char ch);
		string& operator+=(char ch);
		string& operator+=(const char* str);
		void append(const char* str);
		void insert(size_t pos, char ch);
		void insert(size_t pos, const char* str);
		void erase(size_t pos, size_t len = npos);

		size_t find(char ch, size_t pos = 0);
		size_t find(const char* str, size_t pos = 0);
		string substr(size_t pos = 0, size_t len = npos);

	private:
		char* _str = nullptr;
		size_t _size = 0;
		size_t _capacity = 0;
		static const size_t npos;
	};

	bool operator<(const string& s1, const string& s2);
	bool operator<=(const string& s1, const string& s2);
	bool operator>(const string& s1, const string& s2);
	bool operator>=(const string& s1, const string& s2);
	bool operator==(const string& s1, const string& s2);
	bool operator!=(const string& s1, const string& s2);

	ostream& operator<<(ostream& out, const string& s);
	istream& operator>>(istream& in, string& s);
}

string.cpp

主要实现的函数:

  1. erase——删除字符串。首先判断删除的字符串长度是否会超出pos位置开始的原先的字符串长度,若超出则改变len的大小,将pos位置的值改为‘\0’;若未超出长度,接着将需要删除字符串用后面的字符串进行覆盖,改变——size的大小即可。
  2. find——查找字符和字符串。字符从头到尾进行遍历,查找相同字符,记录位置即可;字符串则利用strstr进行查找。
  3. substr——字符串截取。首先判断从pos开始的长度是否会超出原先字符串的长度,接着从pos位置开始遍历,并将字符串进行复制即可。
  4. <、<=、>、>=、==、!=的判断。只需完成两个函数,其他的函数便可用这两个函数实现。判断只需使用strcmp即可进行判断。
  5. <<、>>——流输出和流输入。流输出只需用范围for即可快速进行判断;流输入注意使用get(),即可在遇到空格时不会停下。
#include"string.h"

namespace stringbyself
{
	const size_t string::npos = -1;
	void string::reserve(size_t n)
	{
		if (n > _capacity)
		{
			char* tmp = new char[n + 1];//给'\0'多开辟一个空间
			strcpy(tmp,_str);
			delete[] _str;
			_str = tmp;
			_capacity = n;
		}
	}

	void string::push_back(char ch)
	{
		if (_size == _capacity)
		{
			reserve(_capacity == 0 ? 4 : _capacity * 2);
		}
		_str[_size] = ch;
		_size++;
		_str[_size] = '\0';
	}

	string& string::operator+=(char ch)
	{
		push_back(ch);
		return *this;
	}

	string& string::operator+=(const char* str)
	{
		append(str);
		return *this;
	}

	void string::append(const char* str)
	{
		size_t len = strlen(str);
		if (_size + len > _capacity)
		{
			reserve(_size + len > _capacity * 2 ? _size + len : _capacity * 2);
		}
		strcpy(_str + _size, str);
		_size = _size + len;
	}

	void string::insert(size_t pos, char ch)
	{
		assert(pos <= _size);
		if (_size == _capacity)
		{
			reserve(_capacity == 0 ? 4 : _capacity * 2);
		}
		size_t end = _size + 1;
		while (end > pos)
		{
			_str[end] = _str[end - 1];
			--end;
		}
		_str[pos] = ch;
		_size++;
	}

	void string::insert(size_t pos, const char* str)
	{
		assert(pos <= _size);
		size_t len = strlen(str);
		if (_size + len > _capacity)
		{
			reserve(_size + len > _capacity * 2 ? _size + len : _capacity * 2);
		}
		size_t end = _size + len;
		while (end > pos + len - 1)
		{
			_str[end] = _str[end - len];
			--end;
		}
		for (size_t i = 0; i < len; i++)
		{
			_str[pos + i] = str[i];
		}
		_size += len;
	}

	void string::erase(size_t pos, size_t len)
	{
		assert(pos < _size);
		if (len >= _size - pos)
		{
			_str[pos] = '\0';
			_size = pos;
		}
		else
		{
			for (int i = 0; i < len; i++)
			{
				_str[pos] = _str[pos + len];
			}
			_size -= len;
		}
	}

	size_t string::find(char ch, size_t pos)
	{
		assert(pos < _size);

		for (int i = 0; i < _size; i++)
		{
			if (ch == _str[i])
				return i;
		}
		return npos;
	}

	size_t string::find(const char* str, size_t pos)
	{
		assert(pos < _size);
		const char* ptr = strstr(_str + pos, str);
		if (ptr == nullptr)
		{
			return npos;
		}
		else
		{
			return ptr - _str;
		}

	}
	string string::substr(size_t pos, size_t len)
	{
		assert(pos < _size);

		if (len > _size - pos)
		{
			len = _size - pos;
		}
		string str;
		str.reserve(len);
		for (int i = 0; i < len; i++)
		{
			str += _str[pos + i];
		}
		return str;
	}

	bool operator<(const string& s1, const string& s2)
	{
		return strcmp(s1.c_str(), s2.c_str()) < 0;
	}

	bool operator<=(const string& s1, const string& s2)
	{
		return s1 < s2 || s1 == s2;
	}

	bool operator>(const string& s1, const string& s2)
	{
		return !(s1 < s2 || s1 == s2);
	}

	bool operator>=(const string& s1, const string& s2)
	{
		return !(s1 < s2);
	}

	bool operator==(const string& s1, const string& s2)
	{
		return strcmp(s1.c_str(), s2.c_str()) == 0;
	}

	bool operator!=(const string& s1, const string& s2)
	{
		return !(s1 == s2);
	}


	ostream& operator<<(ostream& out, const string& s)
	{
		for (auto ch : s)
		{
			out << ch<<" ";
		}

		return out;
	}

	istream& operator>>(istream& in, string& s)
	{
		s.clear();

		const int n = 256;
		char buff[n];
		int i = 0;
		char ch = in.get();
		while (ch != '\0' && ch != '\n')
		{
			buff[i++] = ch;
			if (i == n-1)
			{
				buff[i] = '\0';
				s += ch;
				i = 0;
			}
			ch = in.get();
		}
		if (i > 0)
		{
			buff[i] = '\0';
			s += buff;
		}
		return in;
	}
}

test.cpp

#include"string.h"

int main()
{
	string s("hello world");
	cout << s << endl;

	s.erase(2, 2);
	cout << s << endl;

	int pos = s.find(' ');
	s[pos] = '$';
	cout << s << endl;

	pos = s.find("rl");
	s[pos] = '$';
	cout << s << endl;

	string ss;
	ss = s.substr(2,5);
	cout << ss << endl;

	cout << (s > ss) << endl;
	cout << (s <= ss) << endl;
	cout << (s == ss) << endl;
	cout << (s != ss) << endl;
	return 0;
}

在这里插入图片描述

oj题

字符串相加

字符串相加-力扣
在这里插入图片描述
思路:从后往前将字符转化为数字进行相加(注意是否需要进位),写入新的字符串,最后再将字符串进行反转即可

class Solution {
public:
    string addStrings(string num1, string num2) {
    int len1=num1.size()-1;
    int len2=num2.size()-1;
    string num3;
    int value1 = 0, value2 = 0, next = 0;
    while(len1 >= 0 || len2 >= 0)
    {
        if(len1 >= 0)
            value1=num1[len1--]-'0';
        else
            value1=0;
        if(len2 >= 0)
            value2=num2[len2--]-'0';
        else
            value2=0;
        int sum=value1+value2+next;
        if(sum > 9)
        {
            sum-=10;
            next=1;
        }
        else
            next=0;
        num3+=(sum+'0');
    }
    if(next == 1)
        num3+='1';
    reverse(num3.begin(),num3.end());
    return num3;
    }
};

在这里插入图片描述

验证回文串

验证回文串-力扣
在这里插入图片描述
思路:

  1. 将字符串都转化为小写
  2. 当左右都为字母时,则进行比较,若不为字母则++或–直到为字母为止,直到左边和右边相等
class Solution {
public:
     bool isLetterOrNumber(char ch)
    {
        return (ch >= '0' && ch <= '9')
        || (ch >= 'a' && ch <= 'z')
        || (ch >= 'A' && ch <= 'Z');
    }
    bool isPalindrome(string s) {
    if(s == " ")
        return true;
    for(auto& ch:s)
    {
        if(ch >= 'A' && ch <='Z')
            ch+=32;
    }
    int left=0;
    int right=s.size()-1;
    while(left < right)
    {
        while(left < right && !isLetterOrNumber(s[left]))
        {
            left++;
        }
        while(left < right && !isLetterOrNumber(s[right]))
        {
            right--;
        }
        if(s[left] == s[right])
        {
            left++;
            right--;
        }
        else
        {
            return false;
        }
    }
    return true;
    }
};

在这里插入图片描述

反转字符串 II

反转字符串 II-力扣
在这里插入图片描述
思路:

  1. 判断待反转字符是否小于设定值,若小于设定值,直接将右端点设定为最后即可,否则,则将右端点设定为左端点+设定值-1
  2. 当左端点小于字符串长度时进入循环,将设定值长度的字符进行反转,然后将左端点加上两倍的设定值,将右端点设定为左端点+设定值-1,判断右端点是否超出字符串的范围,若超出则赋值为最后一位
class Solution {
public:
    string reverseStr(string s, int k) {
    if(k == 1)
        return s;
    int left=0;
    int right=left+k-1;
    if(k >= s.size())
    {
        right=s.size()-1;
    }
    while(left < s.size())
    {
        int len1=left;
        int len2=right;
        while(len1<len2)
        {
            swap(s[len1++],s[len2--]);
        }
        left+=2*k;
        right=left+k-1;
        if(right >= s.size())
        {
            right=s.size()-1;
        }
    }
    return s;
    }
};

在这里插入图片描述

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

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

相关文章

稳了,搭建Docker国内源图文教程

大家好&#xff0c;之前分享了我的开源作品 Cloudflare Workers Proxy&#xff0c;它的作用是代理被屏蔽的地址&#xff0c;理论上支持代理任何被屏蔽的域名&#xff0c;使用方式也很简单&#xff0c;只需要设置环境变量 PROXY_HOSTNAME 为被屏蔽的域名&#xff0c;最后通过你的…

强化信息安全:密码机密钥管理的策略与实践

强化信息安全&#xff1a;密码机密钥管理的策略与实践 随着信息技术的飞速发展&#xff0c;信息安全已成为企业和社会关注的焦点。密码机作为加密通信和数据保护的关键设备&#xff0c;其密钥管理直接关系到整个信息系统的安全性。本文旨在探讨密码机密钥管理的策略与实践&…

如何根据协议请求去捕捉在个文件中发出去的

场景&#xff1a;随着业务越来越复杂&#xff0c;一个“触发”可能发出去N个协议&#xff0c;此时有某一个协议发生了报错&#xff0c;需要去找这个协议&#xff0c;去文件中走读逻辑&#xff0c;去找该协议&#xff0c;效率很慢&#xff0c;业务极其复杂的情况下&#xff0c;很…

渐变色代码主题你受得了吗

分享一个vscode编辑器的渐变色主题 效果图如下 vscode扩展搜索 gradient theme安装即可。

毕业设计选题:基于springboot+vue+uniapp的驾校报名小程序

开发语言&#xff1a;Java框架&#xff1a;springbootuniappJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包&#…

二级C语言2023-9易错题

1 二叉树结点数计算&#xff1a; 一棵二叉树有10个度为1的结点&#xff0c;7个度为2的结点&#xff0c;则该二叉树共有____个结点。 解&#xff1a; 2 指针&#xff1a; 有以下程序 #inctude<stdio.h> #include<stdlib.h> main() { int *a&#xff0c;*b&…

OpenHarmony(鸿蒙南向开发)——小型系统内核(LiteOS-A)【扩展组件】上

往期知识点记录&#xff1a; 鸿蒙&#xff08;HarmonyOS&#xff09;应用层开发&#xff08;北向&#xff09;知识点汇总 鸿蒙&#xff08;OpenHarmony&#xff09;南向开发保姆级知识点汇总~ 子系统开发内核 轻量系统内核&#xff08;LiteOS-M&#xff09; 轻量系统内核&#…

CSS01-语法规范、基础选择器

一、CSS语法规范 示例&#xff1a; 二、CSS的基础选择器 选择器(选择符)就是根据不同需求把不同的标签选出来这就是选择器的作用。 简单来说&#xff0c;就是选择标签用的。 选择器的分类&#xff1a; 1、标签选择器 2、类选择器&#xff08;开发最常用&#xff09; 长字符命名…

本地搭建我的世界服务器(JAVA)简单记录

网上参考教程挺多的&#xff0c;踩了不少坑&#xff0c;简单记录一下&#xff0c;我做的是一个私人服务器&#xff0c;就是和朋友3、4个人玩。 笨蛋 MC 开服教程 先放一个比较系统和完整的教程&#xff0c;萌新可用&#xff0c;这个教程很详细&#xff0c;我只是记录一下自己的…

相亲交友系统源码 连接你我,不再孤单

在这个数字时代&#xff0c;人们的生活方式已经发生了巨大的变化。随着工作压力增大和社会竞争激烈化&#xff0c;很多人发现自己很难有时间和机会去结识新的朋友&#xff0c;更不用说找到适合自己的伴侣了。相亲交友系统正是在这种背景下应运而生&#xff0c;它不仅简化了交友…

操作系统 | 学习笔记 | | 王道 | 5.2 设备独立软件

5.2 设备独立性软件 IO核心子系统 磁盘IO也属于IO调度问题 5.2.1 与设备无关的软件 与设备无关的软件是I/O系统的最高层软件&#xff0c;它的下层是设备驱动程序。 设备保护&#xff1a; 操作系统需要实现文件保护功能&#xff0c;不同的用户对各个文件有不同的访问权限&am…

BUUCTF-MISC-隐藏的钥匙

下载题目文件&#xff0c;获得了一张格式为jpg的路飞图片 按照习惯&#xff0c;首先使用十六进制编译器打开文件&#xff0c;这里我使用winhex打开文件 首先考虑有没有flag直接隐写在文件中&#xff0c;按照图示步骤查找flag字段 我们查到了flag&#xff0c;通过经验和图中base…

[Python]案例驱动最佳入门:股票分析 Python数据分析与可视化实战

在股票市场中&#xff0c;价格波动和投资决策紧密相连。通过数据分析&#xff0c;投资者可以识别市场趋势、价格波动背后的规律&#xff0c;并做出明智的投资决策。Python凭借其强大的数据处理和可视化功能&#xff0c;在金融市场分析中被广泛应用。本文将通过一个假设的股票市…

java踩坑

1.mybatis在idea可以正常运行&#xff0c;但是打jar包后&#xff0c;就报链接超时&#xff0c;可能是参数设置有问题&#xff0c;但是idea自动忽略了。 出问题的配置&#xff1a;&#xff08;圈出来的地方乱码了&#xff0c;idea有纠错能力&#xff0c;它自动调整为正确的&…

three.js shader 实现天空中白云

three.js shader 实现天空中白云 预览&#xff1a; https://threehub.cn/#/codeMirror?navigationThreeJS&classifyshader&idwhiteCloud 更多案例 可见 预览&#xff1a; https://threehub.cn import * as THREE from "three"; import { OrbitControls …

web基础—dvwa靶场(十二)JavaScript Attacks

JavaScript Attacks (前端攻击) 本章节中的攻击旨在帮助您了解如何在浏览器中使用 JavaScript 以及如何对其进行操作&#xff0c;攻击可以通过分析网络流量来实现&#xff0c;但这不是本章节的重点而且可能要困难得多。 只需提交单词 “success” 即可攻击成功&#xff0c;显然…

开石开放式耳机怎么样?南卡、开石、声阔开放式耳机测评

​作为一名多年的数码博主&#xff0c;我本人也是个耳机发烧友&#xff0c;我最近注意到数码圈特别是蓝牙耳机圈中&#xff0c;有一种耳机特别火&#xff0c;叫开放式耳机&#xff0c;这类耳机的佩戴舒适度是非常高的&#xff0c;这也激起了我对这类耳机的兴趣&#xff0c;因此…

感知笔记4:YOLO 3D 物体定位

如何在 ROS 中使用 YOLO 如何在 2D 中检测人和大象如何在 3D 中检测人和大象 有许多可用的深度学习库。您可能听说过&#xff1a;Keras、TensorFlow 和 Darknet。 在这里我们将使用 Darknet&#xff0c;因为它实现了 YOLOv3&#xff0c;这是一个对象检测模型。它非常快&…

jdk版本更换以及遇到的问题略谈(以jdk1.8和jdk11为例)

目录 在我看来 遇到的问题 原因以及解决方法 方法一&#xff1a;禁止误改误删 方法二&#xff1a;bat文件驱动运行 方法三&#xff1a;cmd命令 方法四&#xff1a;修改注册表&#xff08;不推荐&#xff09; 最近在进行漏洞复现&#xff08;shiro550&#xff09;的时候&…

无人机如何突破高海拔高寒飞行环境?

无人机在突破高海拔高寒飞行环境方面&#xff0c;需要解决一系列技术难题和挑战。以下是一些主要的技术手段和策略&#xff1a; 1. 无人机平台设计与优化 增强机体结构&#xff1a;采用轻质高强度的材料&#xff0c;如碳纤维、复合材料等&#xff0c;减轻机身重量&#xff0c…