模拟String基本函数/深浅拷贝/柔性数组

1.首先我们先关注一下ASCII:

记住常用每一个字符对应的ascii码值!

2.string函数的相关操作函数代码:

大多数小疑问都已经写在注释里面!

cpp 复制代码
#pragma once
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<assert.h>
using namespace std;

namespace hush
{
	class string
	{
	public:
		//strlen函数的参数类型要求是const char*
		string(const char* str="") :_size(strlen(str)), _capacity(_size)
		{
			_str = new char[_capacity + 1];//+1目的是为动态分配的数组,增加额外空间存储'/0'
			strcpy(_str, str);

		}

		//拷贝构造是用一个已知的对象去初始化另一个新的对象--浅拷贝析构函数调用两次
		string(const char&str):_str(nullptr),_size(0),_capacity(0)
		{
			//c++并不会对类置类型进行一个初始化,所以以防编译器版本问题,所以建议进行一个初始化列表
		}
		string& operator=(const string& s)
		{
			if (this != &s)
			{
				char* tmp = new char[s._capacity + 1];
				strcpy(tmp, _str);
				delete[] _str;
				_str = tmp;
				_size = s._size;
				_capacity = s._capacity;
			}
			return *this;
		}
		
		流插入
		//ostream& operator<<(ostream& out, const string& s)
		//{
		//	for (auto ch : s)
		//	{
		//		out << ch;
		//	}

		//	return out;
		//}

		流提取
		//istream& operator>>(ostream& in, const string& s)
		//{
		//	s.clear();
		//	char ch;
		//	/*in >> ch;*/
		//	ch = in.get();
		//	s.reserve(100);
		//	while (ch != ' ' && ch != '/n')
		//	{
		//		s += ch;
		//		/*in >> ch;*/
		//		ch = in.get();
		//	}

		//	return in;
		// }
		
		//这里是迭代器的板块
		typedef char* iterator;
		iterator begin()
		{
			return _str;
		}
		iterator end()
		{
			return _str + _size;
		}


		char& operator[](size_t pos)//减少性能开销  如果不加引用,返回时会把返回的数组值重新拷贝一份给临时对象,临时对象再拷贝返回给原数组
		{
			assert(pos < _size);
			return _str[pos];
		}

		size_t capacity() const//这样的函数既可以被类的非 const 对象调用,也可以被 const 对象调用。
			//例如上述的 obj.capacity() 和 constObj.capacity() 都可以正常调用。
		{
			return _capacity;
		}

		//reserve函数扩容
		void reserve(size_t n)
		{
			if (n > _capacity)
			{
				char* tmp = new char[n + 1];
				strcpy(tmp, _str);
				delete[] _str;
				_str = tmp;
				_capacity = n;
			}
		}

		void push_back(char ch)//这是尾插,一次插一个
		{
			if (_capacity == _size)
			{
				reserve(_capacity * 2);
			}

			_str[_size] = ch;
			++_size;
			_str[_size] = '/0';
		}

		//append 函数的参数是 char* s,它表示一个指向字符数组(C 风格字符串)的指针,
		// 意味着函数期望接收一个字符串,然后对字符串进行处理并追加到类内部存储的字符串 _str 后面。
		// 而 char& s 表示一个字符的引用,它只是单个字符,和原本接收字符串的意图不匹配。
		void append(const char* s)
		{
			size_t len = strlen(s);
			if (_size + len > _capacity)
			{
				reserve(_size + len);
			}

			strcpy(_str + _size, s);
			_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,char* str)
		{
			size_t len = strlen(str);
			if (_size + len > _capacity) {
				reserve(_size + len);
			}
			// 挪动数据
			size_t end = _size;
			while (end >= pos) {
				_str[end + len] = _str[end];
				--end;
			}
			strncpy(_str + pos, str, len);
			_size += len;
		}
		
		void insert(size_t pos, char ch)
		{
			assert(pos <= _size);
			if (_size == _capacity)
			{
				reserve(_capacity == 0 ? 4 : _capacity * 2);
			}//扩容

			size_t end = _size;
			while (end >= pos)
			{
				_str[end + 1] = _str[end];
				--end;
			}//这是挪动数据

			_str[pos] = ch;
			_size++;
		}

		void erase(size_t pos, size_t len = npos) {
			assert(pos < _size);
			if (len == npos || pos + len >= _size) {
				_str[pos] = '\0';
				_size = pos;
			}
			else {
				size_t begin = pos + len;
				while (begin <= _size) {
					_str[begin - len] = _str[begin];
					++begin;
				}
				_size -= len;
			}
		}

		void resize(size_t n, char ch = '/0')
		{
			if (n < _size)
			{
				_str[n] = ch;
				_size = n;
			}
			else
			{
				reserve(n);
				while (n > _size)
				{
					_str[_size] = ch;
					++_size;
				}

				_str[_size] = '/0';
			}
		}

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

			return npos;

		}

		size_t find(char* ch, size_t pos = npos)
		{
			char*p= strstr(_str, ch);//用于在一个字符串中查找另一个字符串首次出现的位置
			if (p)
			{
				return p - _str;
			}
			else
			{
				return pos;
			}
		}



		bool operator<(const string& s) const
		{
			return strcmp(_str, s._str) < 0;
		}
		bool operator==(const string& s) const
		{
			return strcmp(_str, s._str) == 0;
		}

		bool operator<=(const string& s) const
		{
			return *this < s || *this == s;
		}

		bool operator>(const string& s) const
		{
			return !(*this <= s);
		}

		bool operator !=(const string& s) const
		{
			return !(*this == s);
		}

		void clear()
		{
			_str[0] = '/n';
			_size = 0;
		}
		~string()
		{
			delete[]_str;
			_str = nullptr;
			_capacity = _size = 0;
		}



	private:
		char* _str;
		size_t _size;
		size_t _capacity;
		const static size_t npos;
		//静态成员变量要在类外面定义,但是这个其实也是一个特例const +static+ 整型 的可以直接在这一行加缺省值
	};

	const  size_t string::npos = -1;
}
//深拷贝:你的数据不是在你的对象里面的,而是指向的一个空间里面
//浅拷贝:就是数据存在对象里面,例如日期类

3.深浅拷贝:

**浅拷贝:**在编程里,浅拷贝复制的是对象的 "表面" 信息。如果对象里有指向其他数据的指针,浅拷贝只会复制指针的值(也就是内存地址),而不会复制指针所指向的数据。这就好比你复制了一个指向宝藏地点的地图,但地图指向的还是同一个宝藏。要是有人去宝藏地点拿走了东西,两份地图指向的宝藏都没了。

**深拷贝:**在编程里,深拷贝会递归地复制对象及其所有嵌套的对象。也就是说,它不仅复制对象本身,还会复制对象所指向的所有数据,创建出一个完全独立的副本。

4.c++里面柔性数组:

cpp 复制代码
#include <cstdlib>
//柔性数组
struct Buffer {
	int length;
	char data[];//一定要保证它是最后一个成员
};

int main() {
	// 为结构体和柔性数组分配内存
	int bufferLength = 10;
	struct Buffer* buf = (struct Buffer*)malloc(sizeof(struct Buffer) + bufferLength * sizeof(char));
	if (buf == NULL) {
		perror("Memory allocation failed");
		return 1;

	}
	// 设置长度
	buf->length = bufferLength;

	// 释放内存
	free(buf);

	return 0;
}

注意事项

  • 必须是结构体的最后一个成员:柔性数组只能作为结构体的最后一个成员,并且结构体中至少要有一个其他成员。
  • 内存管理:使用柔性数组时,需要手动进行内存分配和释放,要确保在不再使用时及时释放内存,避免内存泄漏。
相关推荐
m0_555762904 分钟前
qt style-sheet样式不起作用问答
开发语言·qt
啊吧怪不啊吧7 分钟前
C++相关基础概念之入门讲解(上)
c语言·开发语言·c++
破刺不会编程8 分钟前
Linux中的权限
linux·运维·服务器·开发语言
最好的药物是乌梅10 分钟前
【蓝桥杯速成】| 3.数据结构
数据结构·算法·蓝桥杯
灏瀚星空11 分钟前
Python JSON模块详解:从入门到高级应用
开发语言·经验分享·笔记·python·json
azaz_plus14 分钟前
C++ priority_queue 堆
开发语言·c++·stl··priority_queue
*.✧屠苏隐遥(ノ◕ヮ◕)ノ*.✧15 分钟前
C语言_数据结构总结10:二叉树的递归/非递归遍历
c语言·数据结构·b树·算法·链表·visualstudio·visual studio
上官美丽15 分钟前
单一责任原则在Java设计模式中的深度解析
java·开发语言·设计模式
uhakadotcom16 分钟前
MCP协议详解:让AI更懂你的数据
算法·面试·github
橙序研工坊19 分钟前
Java基础语法练习42(基本绘图-基本的事件处理机制-小坦克的绘制-键盘控制坦克移动)
java·开发语言