C++容器--string

string

string为C++STL中的重要容器,是表示字符串的字符串类
其中有一些用来操作字符串的接口
不能操作多字节或者变长字符的序列

常用接口

构造:

string();	// 构造空串
string(const char* s);	// 用C-string构造string类对象
string(size_t n, char c);	// string类对象中包含n个字符c
string(const string& s);	// 拷贝构造
string(const string& s, size_t n);	// 用s的前n个字符构造

容量:

size_t size() const;	// 返回字符串有效长度
size_t length() const;	// 返回字符串有效长度
size_t capacity() const; // 返回容量大小
bool empty() const;		// 检测是否为空串
void clear();		// 清空有效字符
void resize(size_t n, char c); // 将有效字符改为n个,多余用c填充
void resize(size_t n);	// 将有效字符改为n个,多余用0填充
void reserve(size_t res_arg = 0);	// 增容

  1. size()与length()底层实现原理相同,size()与其他容器的接口保持一致
  2. clear()只清空有效数据,不改变底层空间大小
  3. reserve()为string预留空间,不改变有效空间的大小,当reserve的参数小于底层空间大小时,不改变容量

访问

char& operator[](size_t pos);	//返回pos位置字符
const char& operator[](size_t pos) const;	// const接口 

修改

void push_back(char c);	// 尾插字符c
string& append(const char* s);	// 追加字符串
string& operator+=(const string& str);	// 追加str对象
// +=重载了追加 字符、字符串、字符串对象
const char* c_str() const;	// 返回c格式字符串
size_t find(char c, size_t pos = 0);	// 在字符串pos开始找c,返回该字符的下标
size_t rfind(char c, size_t pos = npos);
string substr(size_t pos = 0, size_t n = npos);// 从pos位置开始,截取n个字符,返回为新string对象

string类非成员函数

operator+();	// 效率较低
operator>>();	// 输入运算符重载
operator<<();	// 输出运算符重载
getline();		// 获取一行字符,以'\n'作为结束

深浅拷贝

浅拷贝(值拷贝):只拷贝数值,不拷贝资源
深拷贝:拷贝数据,拷贝资源

浅拷贝带来的问题:二次释放

手写一个string类

// 传统写法
#include <iostream>
#include <string.h>

class String
{
public:
	String(const char* str = "")
		:_size(0)
	{
		if (str == nullptr)
		{
			_str = "";
			return;
		}
		_size = strlen(str);
		_str = new char[_size + 1];
		strcpy(_str, str);
	}
	String(const String& s)
	{
		_str = new char[s.Size() + 1];
		strcpy(_str, s._str);
		_size = s.Size();
	}
	~String()
	{
		if (_str != nullptr)
		{
			delete[] _str;
			_str = nullptr;
			_size = -1;
		}
	}
	String& operator=(String& s)
	{

		if (this != &s)
		{
			char* pstr = new char[s.Size() + 1];
			strcpy(pstr, s._str);
			delete[] _str;
			_str = pstr;
			_size = s.Size();
		}
		return *this;
	}
	const int Size() const
	{
		return _size;
	}

public:
	// 可不写,为了验证深拷贝的正确性
	friend std::ostream& operator<<(std::ostream& _cout, const String& s);
	friend std::istream& operator>>(std::istream& _cin, String& s);
private:
	char* _str;
	int _size;
};

std::ostream& operator<<(std::ostream& _cout, const String& s)
{
	_cout << s._str << std::endl;
	return _cout;
}

std::istream& operator>>(std::istream& _cin, String& s)
{
	_cin >> s._str;
	return _cin;
}

// 现代写法
class String {
public:
	String(char* str = "") :_str(nullptr) {
		if (_str == nullptr)
		{
			_str = "";
		}
		_str = new char[strlen(str) + 1];
		strcpy(_str, str);
	}
	String(const String& s) :_str(nullptr) {
		String tmp(s._str);
		std::swap(_str, tmp._str);
	}
	~String() {
		if (_str != nullptr)
		{
			delete[] _str;
			_str = nullptr;
		}
	}
	String& operator=(String s) {
		std::swap(_str, s._str);
		return *this;
	}
private:
	friend std::ostream& operator<<(std::ostream& _cout, const String& s);
	friend std::istream& operator>>(std::istream& _cin, String& s);
private:
	char* _str;
};

std::ostream& operator<<(std::ostream& _cout, const String& s)
{
	_cout << s._str << std::endl;
	return _cout;
}

std::istream& operator>>(std::istream& _cin, String& s)
{
	_cin >> s._str;
	return _cin;
}

string类的模拟实现

// 直接贴代码了,可以找具体的接口看实现
// 没有讲的必要,会用就行

#include <string.h>
#include <assert.h>
#include <string>
#include <iostream>

class String {
public:
	typedef char* Iterator;
public:
	// 构造
	String(const char* str = "")
	{            
		// 构造string类对象时,如果传递nullptr指针,认为程序非法,此处断言下  
		if (nullptr == str) 
		{ 
			assert(false);
			return;   
		}

		_size = strlen(str); 
		if (_size == 0)
			_capacity = 1;
		else
			_capacity = _size;
		
		_str = new char[_capacity + 1];     
		strcpy(_str, str);
	}
	String(const String& s) 
		: _str(new char[s._capacity])
		, _capacity(s._capacity)
		, _size(s._size)
	{
		strcpy(_str, s._str);
	}
	~String() {
		if (_str != nullptr)
		{
			// delete[] _str;
			_str = nullptr;
			_size = 0;
		}
	}
	String& operator= (String s) {
		if (this != &s)
		{
			std::swap(_str, s._str);
			std::swap(_size, s._size);
			std::swap(_capacity, s._capacity);
		}
		return *this;
	}

	// 迭代器 Iterator
	Iterator begin() {
		return _str;
	}
	Iterator end() {
		return _str + _size;
	}
	const Iterator begin() const {
		return _str;
	}
	const Iterator end() const {
		return _str + _size;
	}

	// modify
	void push_back(char c) {
		if (_size == _capacity)
		{
			reserve(_capacity * 2);
		}
		_str[_size] = c;
		_str[++_size] = '\0';
	}
	void append(char c, size_t n) {
		for (size_t i = 0; i < n; ++i)
		{
			push_back(c);
		}
	}
	String& operator+=(char c) {
		push_back(c);
		return *this;
	}
	void append(const char* str) {
		for (size_t i = 0; i < strlen(str); ++i)
		{
			push_back(*(str + i));
		}
		push_back('\0');
	}
	String& operator+= (const char* str) {
		append(str);
		return *this;
	}
	String& operator+= (const String& s) {
		append(s._str);
		return *this;
	}
	// 增容
	void reserve(size_t new_capacity) {
		if (new_capacity > _capacity)
		{
			char* new_str = new char[new_capacity + 1];
			strcpy(new_str, _str);
			
			delete[] _str;
			_str = new_str;
			_capacity = new_capacity;
		}
	}

	// capacity
	int size() const {
		return _size;
	}
	size_t capacity() const {
		return _capacity;
	}
	bool empty() const {
		return _size == 0 ? true : false;
	}
	void Resize(size_t newSize, char c = char()) {
		if (newSize > _size)
		{
			if (newSize > _capacity)
			{
				reserve(newSize);
			}
			memset(_str + _size, c, newSize - _size);
		}
		_size = newSize;
		_str[newSize] = '\0';
	}

	void clear()
	{
		_size = 0;
		_str[_size] = '\0';
	}
	const char* c_str() const
	{
		return _str;
	}
	void Swap(String& s)
	{
		std::swap(_str, s._str);
		std::swap(_size, s._size);
		std::swap(_capacity, s._capacity);
	}

	// access
	char& operator[] (size_t index) {
		return _str[index];
	}
	const char& operator[] (size_t index) const {
		return _str[index];
	}

	bool operator<(const String& s) {
		int i = 0;
		for (auto& e : s)
		{
			if (_str[i] < e)
			{
				return true;
			}
			else if (_str[i] > e)
			{
				return false;
			}
			++i;
		}
		return false;
	}
	bool operator<=(const String& s) {
		return (*this == s) || (*this < s);
	}
	bool operator>(const String& s) {
		return !(*this <= s);
	}
	bool operator>=(const String& s) {
		return !(*this < s);
	}
	bool operator==(const String& s) {
		int i = 0;
		for (auto& e : s)
		{
			if (_str[i] != e)
			{
				return false;
			}
		}
		return true;
	}
	bool operator!=(const String& s) {
		return !(*this == s);
	}

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

	String substr(size_t pos, size_t n) {
		String tmp;
		for (size_t i = 0; i < n; ++i)
		{
			tmp.push_back(_str[pos + i]);
		}
		tmp[pos + n] = '\0';
		return tmp;
	}

	String& insert(size_t pos, char c) {

		//pos的位置需要有效
		if (_size == _capacity)
		{
			reserve(_capacity * 2);
		}
		
		for (size_t i = _size; i > pos; --i)
		{
			_str[i] = _str[i - 1];
		}
		++_size;
		_str[pos] = c;

		// 需要将最后一个元素设置为'\0',否则会越界
		_str[_size] = '\0';
		return *this;
	}
	String& insert(size_t pos, const char* str) {
		size_t len = strlen(str);
		if ((len + _size) >= _capacity)
		{
			reserve((_capacity + len) * 2);
		}

		for (size_t i = pos; i < pos + len; ++i)
		{
			_str[i + len] = _str[i];
		}
		for (size_t i = pos; i < pos + len; ++i)
		{
			_str[i] = str[i - pos];
		}
		_size += len;
		return *this;
	}

	String& erase(size_t pos, size_t len) {
		for (size_t i = pos; i < pos + len; ++i)
		{
			_str[i] = _str[i + len];
		}
		_size -= len;
		return *this;
	}



private:
	friend std::ostream& operator<< (std::ostream& _cout, const String& s);
	friend std::istream& operator>> (std::istream& _cin, String& s);
private:
	char* _str;
	size_t _size;
	size_t _capacity;
	static int nops;
};

int String::nops = -1;

std::ostream& operator<< (std::ostream& _cout, const String& s) {
	_cout << s._str << std::endl;
	return _cout;
}
std::istream& operator>> (std::istream& _cin, String& s) {
	_cin >> s._str;
	return _cin;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值