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

string类的模拟实现以及oj题

前言

上篇博客实现了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.kler.cn/news/314428.html

相关文章:

  • Linux·权限与工具-git与gdb
  • Puppet 部署应用(Puppet deployment application)
  • 《他们的奇妙时光》圆满收官,葛秋谷新型霸总获好评
  • 初始Vitis——ZYNQ学习笔记1
  • 探索微软Copilot Agents:如何通过Wave 2 AI彻底改变工作方式
  • 伊犁linux 创建yum 源过程
  • Java面向对象编程
  • Ubuntu设置笔记本电脑合盖时不挂起
  • el-select组件:选择某个选项触发查询
  • 基于R语言的统计分析基础:使用键盘输入数据
  • charles抓包flutter
  • 数据结构之线性表——LeetCode:328. 奇偶链表,86. 分隔链表,24. 两两交换链表中的节点
  • 基于React+JsonServer+Antddesign的读书笔记管理系统
  • 4.使用 VSCode 过程中的英语积累 - View 菜单(每一次重点积累 5 个单词)
  • 微软AI核电计划
  • SpringBoot 项目启动时指定外部配置文件
  • 【Android 13源码分析】WindowContainer窗口层级-4-Layer树
  • Android通知显示framework流程解析
  • Python中的魔法:栈与队列的奇妙之旅
  • 大语言模型的发展-OPENBMB
  • ICM20948 DMP代码详解(34)
  • 欧美游戏市场的差异
  • 漏洞复现_永恒之蓝
  • AI助力低代码平台:从智能化到高效交付的全新变革
  • 山体滑坡检测系统源码分享
  • STM32 通过 SPI 驱动 W25Q128
  • 【JS】垃圾回收机制与内存泄漏
  • mxnet 的显存分配机制
  • Gitlab学习(009 gitlab冲突提交)
  • 小程序与APP的区别