c++ (六、string类的模拟实现)

1、 C语言中的字符串

C语言中,字符串是以’\0’结尾的一些字符的集合,为了操作方便,C标准库中提供了一些str系列的库函数, 但是这些库函数与字符串是分离开的,不太符合OOP的思想,而且底层空间需要用户自己管理,稍不留神可 能还会越界访问

  1. 字符串是表示字符序列的类
  2. 标准的字符串类提供了对此类对象的支持,其接口类似于标准字符容器的接口,但添加了专门用于操作 单字节字符字符串的设计特性。
  3. .string类是使用char(即作为它的字符类型,使用它的默认char_traits和分配器类型(关于模板的更多信 息,请参阅basic_string)。
  4. string类是basic_string模板类的一个实例,它使用char来实例化basic_string模板类,并用char_traits 和allocator作为basic_string的默认参数(根于更多的模板信息请参考basic_string)。
  5. 注意,这个类独立于所使用的编码来处理字节:如果用来处理多字节或变长字符(如UTF-8)的序列,这个 类的所有成员(如长度或大小)以及它的迭代器,将仍然按照字节(而不是实际编码的字符)来操作。
    总结:
  6. string是表示字符串的字符串类
  7. 该类的接口与常规容器的接口基本相同,再添加了一些专门用来操作string的常规操作
  8. string在底层实际是:basic_string模板类的别名,typedef basic_string<char, char_traits, allocator> string;
  9. 不能操作多字节或者变长字符的序列。 在使用string类时,必须包含#include头文件以及using namespace std;

#include <assert.h>

namespace bite
{
class string
{
public:
typedef char* iterator;

public:
	string(const char* str = "")// const char* 使因为 调用strcpy 第二个参数为 const
	{
		if (nullptr == str)
			str = "";

		// 当前对象开辟空间
		_size = strlen(str);
		_capacity = _size;
		_str = new char[_capacity+1];
		
		// 拷贝元素
		strcpy(_str, str);
	}

	string(size_t n, char ch)
		: _size(n) 
		, _capacity(n) //string 类底层
		, _str(new char[n+1])
	{
		memset(_str, ch, n);//
		_str[n] = '\0'; // 将最后一个字符设置为'\0'
	}

	// [begin, end)   区间拷贝
	//  如何体现出 左闭右开?
	// _size = end - begin; 此时从 begin 往后 _size 个位置,就不包括 end
	// 由于是左闭右开区间,因此 _str[_size]
	string(char* begin, char* end)
	{
		_size = end - begin; //_size为从 begin ---end 的元素个数,不包括end,
		_capacity = _size;
		_str = new char[_size + 1];
		strncpy(_str, begin, _size);  
		_str[_size] = '\0';  //第size+1个元素 ,从0 -- size-1 ,完成拷贝
	}

	string(const string& s) // 不能修改应用的内容
		: _size(s._size)
		, _capacity(s._size)
	{
		_str = new char[_capacity+1];
		strcpy(_str, s._str);
	}

//运算符重载
	string& operator=(const string& s)
	{
		if (this != &s) //检测是否有对自己赋值,避免自己给自己赋值
		{

			int len = strlen(s._str);
			//申请新空间
			char* p = new char[len+1];
			//拷贝旧空间
			strcpy(p, s._str);
			// 释放旧空间
			delete[] _str;
			// 指向新空间
			_str = p;
			_size = len; // 重置
			_capacity = len;// 重置
		}

		return *this;
	}


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

	/
	// capacity
	size_t size()const   // 不需要修改 _size _capacity属性 所以用 const 
	{
		return _size;
	}

	size_t capacity()const
	{
		return _capacity;
	}

	bool empty()const
	{
		return 0 == _size;
	}

	void resize(size_t newsize, char ch)
	{
		size_t oldsize = size();
		if (newsize > oldsize)
		{
			// 有效元素个数增多
			// 多出的元素在空余空间中能否放的下
			if (newsize > _capacity)
			{
				reserve(newsize);
			}

			memset(_str + _size, ch, newsize - oldsize);
		}

		_size = newsize;
		_str[_size] = '\0';
	}
	void reserve(size_t newcapacity)
	{
		size_t oldcapacity = capacity();
		if (newcapacity > oldcapacity)
		{
			// 申请新空间
			char* temp = new char[newcapacity + 1];

			// 拷贝元素
			strcpy(temp, _str); //也有将'\0'赋值

			// 释放旧空间
			delete[] _str;
			_str = temp;
			_capacity = newcapacity;
		}
	}
	/
	// access
	char& operator[](size_t index)
	{
		assert(index < _size);
		return _str[index];
	}

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

/
// modify

	void push_back(char ch) //尾插
	{
		if (_size == _capacity)
			reserve(_capacity*2);

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

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

	string& operator+=(const char* str);
	string& operator+=(const string& s);
	bool operator==(const string& s);
	bool operator!=(const string& s);
	bool operator>(const string& s);
	bool operator>=(const string& s);
	bool operator<(const string& s);
	bool operator<=(const string& s);
	
	friend ostream& operator<<(ostream& _cout, const bite::string& s)
	{
		_cout << s.c_str();
		return _cout;
	}

	friend istream& operator<<(istream& _cout, string& s);
	/
	// 特殊操作
	size_t find(char ch, size_t pos = 0)
	{
		for (size_t i = pos; i < _size; ++i)
		{
			if (ch == _str[i])
				return i;
		}

		return npos; //未找到 ch
	}

	
	// size_t  npos = -1  ----- 是一个非常大的数字
	size_t rfind(char ch, size_t pos = npos)
	{
		if (pos == npos)
			pos = _size - 1;// 默认情况从最后一个位置查找

		for (int i = pos; i >= 0; i--)
		{
			if (ch == _str[i])
				return i;
		}

		return npos;
	}

	string substr(size_t pos = 0, size_t n = npos)
	{
		if (n == npos) 
			n = _size;// 默认情况为最后位置

		string temp(_str + pos, _str + pos + n);
		return temp;
	}

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

	/
	// iterator

	iterator begin()
	{
		return _str;
	}

	iterator end()
	{
		return _str + _size;
	}

private:
	char* _str;
	size_t _size;
	size_t _capacity;
	static size_t npos; // npos是一个无符号整数 值为-1
};

size_t string::npos = -1;

}

void TestString1()
{
bite::string s1;
bite::string s2(“hello”);
bite::string s3(s2);
bite::string s4(10, ‘$’);
bite::string s5(s2.begin(), s2.end());

for (auto e : s2)
	cout << e;
cout << endl;

for (size_t i = 0; i < s3.size(); ++i)
	cout << s3[i];
cout << endl;

//bite::string::iterator it = s4.begin();
auto it = s4.begin();
while (it != s4.end())
{
	cout << *it;
	++it;
}
cout << endl;

}

void TestString2()
{
bite::string s(“hello”);
cout << s.size() << endl;
cout << s.capacity() << endl;

s.push_back('!');
cout << s.size() << endl;
cout << s.capacity() << endl;

s.resize(15, '$');
cout << s.size() << endl;
cout << s.capacity() << endl;

s.resize(10, '&');
cout << s.size() << endl;
cout << s.capacity() << endl;

}

void TestString3()
{
bite::string s(“hello”);

size_t pos1 = s.find('l');
cout << pos1 << endl;

size_t pos2 = s.rfind('l');
cout << pos2 << endl;

cout<<s.substr(pos1, 2)<<endl;

}

int main()
{
//TestString1();
//TestString2();
TestString3();
return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值