【C++】STL之string类源码剖析

目录

概述

源码

MyString.h

test.cpp


概述

string是字符串类,出现早于STL,不过string完全符合STL标准库的语法规则,故将string类也归于STL中

string类实现的功能有字符串元素的随机访问、迭代器遍历、字符串追加/删减/查找、字符串随机插入、字符串扩容与修改长度、重载输入/输出运算符

算法设计:利用构造临时对象、自定义swap函数,完成string对象的拷贝、赋值构造,简化代码

源码

MyString.h

#pragma once

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

class String
{
public:
	//迭代器
	typedef char* iterator;
	iterator begin()
	{
		return _str;
	}
	iterator end()
	{
		return _str + _size;
	}

	//构造
	void swap(String& str)
	{
		std::swap(_str, str._str);
		std::swap(_size, str._size);
		std::swap(_capacity, str._capacity);
	}
	String(const char* str = "")
	{
		_size = strlen(str);
		_capacity = _size;
		_str = new char[_capacity + 1];
		strcpy(_str, str);
	}
	String(const String& str)		//拷贝构造
		: _str(nullptr)
	{
		String tmp(str._str);
		swap(tmp);
	}
	String& operator=(String str)	//赋值构造
	{
		swap(str);
		return *this;
	}

	//析构
	~String()
	{
		delete[] _str;
		_str = nullptr;
		_size = _capacity = 0;
	}

	//返回char*字符串
	char* c_str()
	{
		return _str;
	}

	//长度与容量
	size_t size()
	{
		return _size;
	}
	size_t capacity()
	{
		return _capacity;
	}
	void reserve(size_t n)					//扩容
	{
		if (n > _capacity)
		{
			char* tmp = new char[n + 1];
			strcpy(tmp, _str);
			delete[] _str;
			_str = tmp;
			_capacity = n;
		}
	}
	void resize(size_t n, char ch = '\0')	//修改长度
	{
		if (n > _size)
		{
			reserve(n);
			for (size_t i = strlen(_str); i < n; ++i)
			{
				_str[i] = ch;
			}
			_str[n] = '\0';
		}
		else
		{
			_str[n] = '\0';
		}
		_size = n;
	}

	//下标取值
	char& operator[](size_t pos)const
	{
		assert(pos < _size);
		return _str[pos];
	}

	//后插字符
	void push_back(char ch)
	{
		if (_size == _capacity)
		{
			size_t newCapacity = (_capacity == 0 ? 4 : 2 * _capacity);
			reserve(newCapacity);
		}
		_str[_size] = ch;
		++_size;
		_str[_size] = '\0';
	}
	String& operator+=(char ch)
	{
		push_back(ch);
		return *this;
	}

	//追加字符串
	void append(const char* str)
	{
		size_t len = strlen(str);
		if (_size + len >= _capacity)
		{
			reserve(_size + len);
		}
		strcpy(_str + _size, str);
		_size += len;
	}
	String& operator+=(const char* str)
	{
		append(str);
		return *this;
	}

	//按下标插入
	String& insert(size_t pos, char ch)
	{
		assert(pos <= _size);
		if (_size == _capacity)
		{
			size_t newCapacity = (_capacity == 0 ? 4 : 2 * _capacity);
			reserve(newCapacity);
		}
		size_t end = _size + 1;
		while (end > pos)
		{
			_str[end] = _str[end - 1];
			--end;
		}
		_str[end] = ch;
		++_size;
		return *this;
	}
	String& insert(size_t pos, const char* str)
	{
		assert(pos <= _size);
		int 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;
		}
		strncpy(_str + pos, str, len);
		_size += len;
		return *this;
	}

	//删除
	String& erase(size_t pos, size_t len = npos)
	{
		assert(pos < _size);
		if (len == npos || pos + len >= _size)
		{
			_str[pos] = '\0';
			_size = pos;
		}
		else
		{
			strcpy(_str + pos, _str + pos + len);
			_size -= len;
		}
		return *this;
	}

	//查找
	size_t find(const char ch, size_t pos = 0)const
	{
		assert(pos < _size);
		while (pos < _size)
		{
			if (_str[pos] == ch)
			{
				return pos;
			}
			++pos;
		}
		return npos;
	}
	size_t find(const char* str, size_t pos = 0)const
	{
		assert(pos < _size);
		const char* ptr = strstr(_str + pos, str);
		if (ptr == nullptr)
		{
			return npos;
		}
		else
		{
			return ptr - _str;
		}
	}

	//清空
	void clear()
	{
		_size = 0;
		_str[0] = '\0';
	}
	
	//输入输出重载
	friend std::ostream& operator<<(std::ostream& os, String& str);
	friend std::istream& operator>>(std::istream& is, String& str);

private:
	char* _str;
	size_t _size;
	size_t _capacity;
	const static size_t npos = -1;	//仅支持整型这样初始化
};

std::ostream& operator<<(std::ostream& os, String& str)
{
	for (size_t i = 0; i < str.size(); ++i)
	{
		os << str[i];
	}
	return os;
}

std::istream& operator>>(std::istream& is, String& str)
{
	str.clear();
	char buffer[128] = { '\0' };
	size_t i = 0;
	char ch = is.get();
	while (ch != ' ' && ch != '\n')
	{
		if (i == 127)
		{
			str += buffer;
			i = 0;
		}
		buffer[i++] = ch;
		ch = is.get();
	}
	if (i > 0)
	{
		buffer[i] = '\0';
		str += buffer;
	}
	return is;
}

test.cpp

#include "MyString.h"
using namespace std;

int main()
{
	String str1("hello world");
	cout << str1.c_str() << endl;
	cout << str1 << endl;

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

	String::iterator it = str1.begin();
	while (it != str1.end())
	{
		(*it)--;
		++it;
	}
	cout << str1 << endl;

	str1.push_back(' ');
	str1 += '!';
	cout << str1 << endl;

	str1.insert(13, '~');
	str1.insert(0, "~~~");
	cout << str1 << endl;

	str1.erase(8, 1);
	str1.erase(0, 2);
	cout << str1 << endl;

	str1.resize(20);
	cout << str1 << endl;
	str1.resize(25, 'x');
	cout << str1 << endl;
	cout << str1.c_str() << endl;

	String str2;
	cin >> str2;
	cout << str2 << endl;

	String str3(str2);
	cout << str3.c_str() << endl;
	String str4 = str3;
	cout << str4 << endl;

	return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

AllinTome

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值