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

【C++】string类中常用函数的模拟实现

【C++】string类中常用函数的模拟实现

  • 1. string.h
  • 2. Text.cpp

1. string.h

#include<assert.h>

namespace wch
{
	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 str;
		string(const char* str = "")//string(const char* str = "\0")
		{
			_size = strlen(str);
			_capacity = _size;
			_str = new char[_capacity + 1];
			strcpy(_str, str);
		}

		string(const string& s)//构造函数有参对象初始化 string str("abc");
		{
			_str = new char[s._capacity + 1];
			strcpy(_str, s._str);
			_size = s._size;
			_capacity = s._capacity;
		}

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

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

		size_t size() const
		{
			return _size;
		}

		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)
		{
		//要加判断条件,因为当n <= _capacity时不做任何处理
			if (n > _capacity)
			{
				char* tmp = new char[n + 1];
				strcpy(tmp, _str);
				delete[] _str;
				_str = tmp;
				_capacity = n;
			}
		}

		void push_back(char ch)
		{
			if (_size == _capacity)
			{
				// 2倍扩容
				reserve(_capacity == 0 ? 4 : _capacity * 2);
			}

			_str[_size] = ch;

			++_size;
			_str[_size] = '\0';
		}

		void append(const char* str)
		{
			size_t len = strlen(str);
			if (_size + len > _capacity)
			{
				// 至少扩容到_size + len
				reserve(_size + len);
			}

			strcpy(_str + _size, str);
			_size += len;
		}

		string& operator+=(char ch)//末尾添加字符
		{
			push_back(ch);
			return *this;
		}

		string& operator+=(const char* str)//末尾添加字符串
		{
			append(str);
			return *this;
		}

		void insert(size_t pos, size_t n, char ch)//从下标pos位置开始向后插入n个字符ch
		{
			assert(pos <= _size);

			if (_size + n > _capacity)
			{
				// 至少扩容到_size + n
				reserve(_size + n);
			}

			// 挪动数据
			/*int end = _size;
			while (end >= (int)pos)//整型提升有符号向无符号提升
			{
				_str[end + n] = _str[end];
				--end;
			}*/

			// 挪动数据
			size_t end = _size;
			while (end >= pos && end != npos)
			{
				_str[end + n] = _str[end];
				--end;
			}

			for (size_t i = 0; i < n; i++)
			{
				_str[pos + i] = ch;
			}

			_size += n;
		}

		void insert(size_t pos, const char* str)
		{
			assert(pos <= _size);

			size_t len = strlen(str);
			if (_size + len > _capacity)
			{
				// 至少扩容到_size + len
				reserve(_size + len);
			}

			size_t end = _size;
			while (end >= pos && end != npos)
			{
				_str[end + len] = _str[end];
				--end;
			}

			for (size_t i = 0; i < len; i++)
			{
				_str[pos + i] = str[i];
			}

			_size += len;
		}

		void erase(size_t pos, size_t len = npos)
		{
			assert(pos <= _size);

			if (len == npos || pos + len >= _size)//将pos后面的数据删完
			{
				_str[pos] = '\0';
				_size = pos;
			}
			else//删除pos到结尾的部分连续数据
			{
				size_t end = pos + len;
				while (end <= _size)
				{
					_str[pos++] = _str[end++];
				}
				_size -= len;
			}
		}

		size_t find(char ch, size_t pos = 0)//找字符下标
		{
			assert(pos < _size);

			for (size_t i = pos; i < _size; i++)
			{
				if (_str[i] == ch)
				{
					return i;
				}
			}

			return npos;
		}

		size_t find(const char* str, size_t pos = 0)//找字符串下标
		{
			assert(pos < _size);

			const char* ptr = strstr(_str + pos, str);
			if (ptr)
			{
				return ptr - _str;
			}
			else
			{
				return npos;
			}
		}

		string substr(size_t pos = 0, size_t len = npos)
		{
			assert(pos < _size);

			size_t n = len;
			if (len == npos || pos + len > _size)
			{
				n = _size - pos;
			}

			string tmp;
			tmp.reserve(n);
			for (size_t i = pos; i < pos + n; i++)
			{
				tmp += _str[i];
			}

			return tmp;
		}

	private:
		size_t _size;
		size_t _capacity;
		char* _str;

	public:
		//const static size_t npos = -1; // 虽然可以这样用,但是不建议
		const static size_t npos;

		//const static double x = 1.1;//不支持除了int以外其他const static类型在类内定义并初始化
	};

	const size_t string::npos = -1;
	//const double string::x = 1.1;
};

2. Text.cpp

#define  _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
#include<string>
using namespace std;

#include"string.h"

void test_string1()
{
	wch::string s1("hello world");
	cout << s1.c_str() << endl;

	wch::string s2;
	cout << s2.c_str() << endl;

	for (size_t i = 0; i < s1.size(); i++)
	{
		s1[i]++;
	}

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

	const wch::string s3("hello world");
	s3[0];

	//wch::string::const_iterator cit = s3.begin();
	auto cit = s3.begin();
	while (cit != s3.end())
	{
		//*cit += 1;

		cout << *cit << " ";
		++cit;
	}
	cout << endl;

	wch::string::iterator it = s1.begin();
	while (it != s1.end())
	{
		*it += 1;

		cout << *it << " ";
		++it;
	}
	cout << endl;

	for (auto ch : s1)
	{
		cout << ch << " ";
	}
	cout << endl;
}

void test_string2()
{

	wch::string s1("hello world");
	cout << s1.c_str() << endl;

	s1.push_back(' ');
	s1.push_back('#');
	s1.append("hello world");
	cout << s1.c_str() << endl;

	wch::string s2("hello world");
	cout << s2.c_str() << endl;

	s2 += ' ';
	s2 += '#';
	s2 += "hello world";
	cout << s2.c_str() << endl;
}

void test_string3()
{
	wch::string s1("helloworld");
	cout << s1.c_str() << endl;

	s1.insert(5, 3, '#');
	cout << s1.c_str() << endl;

	s1.insert(0, 3, '#');
	cout << s1.c_str() << endl;


	wch::string s2("helloworld");
	s2.insert(5, "%%%%%");
	cout << s2.c_str() << endl;
}

void test_string4()
{
	wch::string s1("helloworld");
	cout << s1.c_str() << endl;

	s1.erase(5, 3);
	cout << s1.c_str() << endl;

	s1.erase(5, 30);
	cout << s1.c_str() << endl;

	s1.erase(2);
	cout << s1.c_str() << endl;
}

void test_string5()
{
	// 2118
	wch::string url = "ftp://www.baidu.com/?tn=65081411_1_oem_dg";

	size_t pos1 = url.find("://");
	cout << pos1 << endl;
	if (pos1 != wch::string::npos)
	{
		wch::string protocol = url.substr(0, pos1);
		cout << protocol.c_str() << endl;
	}

	size_t pos2 = url.find('/', pos1 + 3);
	cout << pos2 << endl;
	if (pos2 != wch::string::npos)
	{
		wch::string domain = url.substr(pos1 + 3, pos2 - (pos1 + 3));
		wch::string uri = url.substr(pos2 + 1);

		cout << domain.c_str() << endl;
		cout << uri.c_str() << endl;
	}
}

int main()
{
	//test_string1();
	//test_string2();
	//test_string3();
	//test_string4();
	test_string5();
	return 0;
}

http://www.kler.cn/news/305110.html

相关文章:

  • 【信奥赛模拟题中的选择题】
  • 合资油车断崖式崩盘,买车的千万慎重了
  • SAP自动化-AS02修改资产信息
  • NASA数据集:ASTER L2 地表辐射率 VNIR 和 SWIR V003
  • 上门按摩小程序APP系统源码开发搭建
  • yolov5明厨亮灶检测系统,厨师帽-口罩检测,带pyqt界面-可检测图片和视频,支持中文标签,检测接口已封装好并优化,代码可读性强!
  • ​招​银​网​络​​大​疆​​元​象​一​面​
  • 河海大学《2020年+2021年827自动控制原理真题》 (完整版)
  • Netty权威指南:Netty总结-Netty线程模型与架构剖析
  • 如何正确使用MMPI量表进行测试?
  • 关于 -fsanitize=address 的使用注意事项
  • 链路聚合(Link Aggregation)
  • 分享一个爬虫数据挖掘 农村产权交易数据可视化平台 数据分析大数据 Java、python双版(源码、调试、LW、开题、PPT)
  • Linux内核编译并移植至ARM平台
  • 【数据结构和算法实践-树-LeetCode113-路径总和Ⅱ】
  • 【数据结构】6——图1,概念
  • 【nginx】ngx_http_proxy_connect_module 正向代理
  • 『功能项目』C#拓展 - 优化冗余脚本【36】
  • unity3d入门教程五
  • 【FastAPI】实现服务器向客户端发送SSE(Server-Sent Events)广播
  • [C#][IIS]framework4.0注册到IIS
  • 密码学---常见的其他密码
  • 第十一周:机器学习笔记
  • python 实现euclidean distance欧式距离算法
  • 分享JavaScript中直接调用CSS中的类名
  • 56 - I. 数组中数字出现的次数
  • CAN总线-STM32上CAN外设
  • ansible_find模块
  • 计算机四级数据库原理考试大纲.md
  • 37. MyBatis-Plus是什么?它与MyBatis的主要区别是什么?