C++的string

string类

string支持流插入和流提取

string初始化

赋值符的重载

遍历string

string的大小:

两个长度没有任何不同

第一种

(写两个函数重载是为了防止字符串为const)

使用引用返回就可以修改得到的变量的值

第二种:迭代器

迭代器iterator

迭代器是一个类似于指针的东西(不一定是指针)

begin返回第一个位置的指针,end返回最后一个字符的下一个位置的指针

遍历方式

迭代器相比于下标访问的优越性

不是所有东西都支持下标访问,但是都支持迭代器

迭代器是一个主流的通用的方法

第三种:范围for

所有结构都支持范围for,因为他的底层就是迭代器

auto后加&可以就可以遍历修改数据了

范围for遍历自动取数据,自动++,自动判断结束

但是,如果类型是const string,就不能用上述遍历修改了

begin存在两种返回数据

反向迭代器

反向迭代器存在rbegin和rend

他的目的是反向遍历

他的++和--是相反的,

++向后走,--向前走

算法:数据排序

参数:起始和结束位置,左闭右开(即传入最后一个的下一个位置)

插入和修改

1.

单个字符

2.

字符串

3.

assign的本质是一种变相的赋值

insert

insert是插入

insert应该慎用,因为效率不高(O(N))

erase

erase是删除

同样慎用,效率不高

如果结束位置较大或不传,则全部删完后停止

但是注意第一个参数pos不能越界

replace

replace的作用是替换

string的部分接口

string的扩容

起初是存在临时数组buf中,buf空间不够,数据会转移到堆中

在vs下的扩容

可以是1.5倍扩容,也可以是两倍扩容

在Linux下的扩容

对于字符串的存储,如果字符串大小小于16

会存储在临时生成的一个数组buf中

如果字符串大于16

就不会存储在buf中,转而存储在堆中

resize和reserve

resize影响size和capacity

reserve只影响capacity

reserve

reserve的作用是扩容

vs下

可以看到申请扩容100,但是实际上扩容了111

linux下

而linux下则是正常的100

同时reserve不仅可以用于扩容,还可以用于缩容

(小于15就会缩,大于等于16,不缩)

但是Linux会缩容

注意,reserve只是扩容(改变capacity),不改变size,导致不能直接用下标访问

resize

resize会改变size

eg.

如果改变后的size大于capacity,则扩容

改变size后会删除多余的字符串

缩容

由于空间不能分段释放,所以缩容的本质是开辟一块更小的空间,然后将数据拷贝

是时间换空间

at

访问pos位置的字符

string operations

c_str

获取指向字符串的指针(首元素的地址)

可以和c语言更好的兼容

find和rfind

find是正着找,rfind是反着找

获取子串

find_first_of

查找aeiou中的任意一个字符

时间复杂度是m*n

operator + 

模拟实现

#pragma once
#include <iostream>
#include<assert.h>
using namespace std;
namespace bit 
{
	class string
	{
	public:
		//迭代器
		typedef char* iterator;//封装,屏蔽了底层实现的细节
		typedef const char* const_iterator;
		//const防止数据被修改
		//提供了一种简单通用的访问容器的方式

		iterator begin();
		iterator end();

		const_iterator begin() const;
		const_iterator end() const;
		//MyString();
		string(const char* str = "");//给缺省值,减少无参数构造
		~string();
		/*string& operator=(const string& s);*/
		string& operator=(string tmp);
		string(const string& s);
		const char* c_str() const;

		size_t size() const;
		char& operator[](size_t pos);

		const char& operator[](size_t pos) const;

		void reserve(size_t n);
		void push_back(char ch);
		void append(const char* str);

		string& operator+=(char ch);
		string& operator+=(const char* str);

		void insert(size_t pos, char ch);
		void insert(size_t pos, const char* str);
	
		void erase(size_t pos = 0, size_t len = npos);
		
		size_t find(char ch, size_t pos = 0);
		size_t find(const char* str, size_t pos = 0);
	
		void swap(string& s);
		string substr(size_t pos = 0, size_t len = npos);
		
		bool operator<(const string& s) const;
		bool operator>(const string& s) const;
		bool operator<=(const string& s) const;
		bool operator>=(const string& s) const;
		bool operator==(const string& s) const;
		bool operator!=(const string& s) const;

		void clear();
	private:
		char* _str;
		size_t _size;
		size_t _capacity;
		const static size_t npos;
		//静态成员变量,属于整个类
	};
	istream& operator>> (istream& is, string& str);
	ostream& operator<< (ostream& os, const string& str);
}
#include "MyString.h"
//MyString::MyString()
//{
//	_str = new char[1] {'\0'};
//	_size = 0;
//	_capacity = 0;
//}
namespace bit
{
	const static size_t npos = -1;

	string::string(const char* str)
		:_size(strlen(str))
		//初始化列表,类尽量在初始化列表中初始化
		//由于strlen效率较低,因此尽量避免函数的重复使用
		//可以将初始化列表和函数体结合使用
	{
		_str = new char[_size + 1];
		_capacity = _size;
		strcpy(_str, str);
	}

	string::~string()
	{
		delete[] _str;
		_str = nullptr;
		_size = _capacity = 0;
	}
	//传统写法
	//string::string(const string& s)//拷贝构造
	//{
	//	_str = new char[s._capacity + 1];
	//	strcpy(_str, s._str);
	//	_size = s._size;
	//	_capacity = s._capacity;
	//}

	//现代写法
	string::string(const string& s)
	{
		string tmp(s._str);//利用构造函数构造一个一样的对象,然后交换
		//方法1
		/*std::swap(tmp._str, _str);
		std::swap(tmp._size, _size);
		std::swap(tmp._capacity, _capacity);*/
		//方法2
		swap(tmp);//调用自己的swap,默认的第一个参数是*this
	}

	//传统写法
	/*string& string::operator=(const string& s)
	{
		if (this != &s)
		{
			char* tmp = new char[s._capacity + 1];
			strcpy(tmp, s._str);
			delete[] _str;
			_str = tmp;
			_size = s._size;
			_capacity = s._capacity;
		}
		
	}*/

	//现代写法
	// 方法1
	//string& string::operator=(const string& s)
	//{
	//	if (this != &s)
	//	{
	//		string tmp(s._str);
	//		swap(tmp);
	//	}

	//	return *this;
	//}
	//方法2
	string& string::operator=(string tmp)//在参数中拷贝构造
	{
		swap(tmp);//和拷贝交换
		return *this;
	}

	const char* string::c_str() const
		//类的成员函数后面加 const,表明这个函数不会对这个类对象的数据成员(准确地说是非静态数据成员)作任何改变。
	{
		return _str;
	}

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

	string::iterator string::begin()
	{
		return _str;
	}

	string::iterator string::end()
	{
		return _str + _size;
	}

	string::const_iterator string::begin() const
	{
		return _str;
	}

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

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

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

			_capacity = n;
		}
	}

	void string::push_back(char ch)//插入单个字符
	{
		if (_size == _capacity)
		{
			size_t newcapacity = _capacity == 0 ? 4 : _capacity * 2;
			reserve(newcapacity);
		}

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

	void string::append(const char* str)//插入字符串
	{
		size_t len = strlen(str);
		if (_size + len > _capacity)
		{
			reserve(_size + len);
		}

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

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

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

	void string::insert(size_t pos, char ch)
	{
		if (_size == _capacity)
		{
			size_t newcapacity = _capacity == 0 ? 4 : _capacity * 2;
			reserve(newcapacity);
		}

		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)
	{
		size_t len = strlen(str);
		if (_size + len > _capacity)
		{
			reserve(_size + len);
		}

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

		memcpy(_str + pos, str, len);
		_size += len;
	}

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

		if (len >= _size - pos)
		{
			_str[pos] = '\0';
			_size = pos;
		}
		else
		{
			strcpy(_str + pos, _str + pos + len);
			_size -= len;
		}
	}

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

	size_t string::find(const char* sub, size_t pos)
	{
		const char* p = strstr(_str + pos, sub);//找到字串并返回下标
		return p - _str;
	}

	void string::swap(string& s)
	{
		std:: swap(_str, s._str);
		std::swap(_size, s._size);
		std::swap(_capacity, s._capacity);
	}

	//获取特定字串
	string string::substr(size_t pos, size_t len = npos)
	{
		if (len > _size - pos)
		{
			string sub(_str + pos);
			return sub;
		}
		else
		{
			string sub;
			sub.reserve(len);
			for (size_t i = 0; i < len; i++)
			{
				sub += _str[pos + i];
			}
			return sub;
		}

		
	}

	bool string::operator<(const string& s) const
	{
		return strcmp(_str, s._str) < 0;
	}
	bool string::operator>(const string& s) const
	{
		return !(*this <= s);
	}
	bool string::operator<=(const string& s) const
	{
		return *this < s || *this == s;
	}
	bool string::operator>=(const string& s) const
	{
		return !(*this < s);
	}
	bool string::operator==(const string& s) const
	{
		return strcmp(_str, s._str) == 0;
	}
	bool string::operator!=(const string& s) const
	{
		return !(*this == s);
	}

	istream& operator>> (istream& is, string& str)
	{
		//当输入一段很长的字符串时
		//由于ch是单个字符,不断+=就需要不断扩容,导致浪费
		//而提前reserve又可能会导致空间的大量浪费
		//方法1
		//str.clear();
		//char ch = is.get();
		//
		//while (ch != ' ' && ch != '\n')
		//{
		//	str += ch;
		//	ch = is.get();
		//}
		//return is;
		// 
		//方法2
		//临时数组
		str.clear();
		char buff[128];
		int i = 0;
		char ch = is.get();

		while (ch != ' ' && ch != '\n')
		{
			buff[i++] = ch;
			//0-126存有效字符
			if (i == 127)
			{
				buff[i] = '\0';
				str += buff;
				i = 0;
			}
			ch = is.get();
			if (i != 0)
			{
				buff[i] = '\0';
				str += buff;
			}
		}
		return is;
	}
	void string::clear()
	{
		_str[0] = '\0';
		_size = 0;
	}
	ostream& operator<< (ostream& os, const string& str)
	{
		for (size_t i = 0; i < str.size(); i++)
		{
			os << str[i];
		}
		return os;
	}

	

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值