欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 财经 > 产业 > 【C++】string的模拟实现

【C++】string的模拟实现

2025/5/18 1:29:07 来源:https://blog.csdn.net/2303_80187476/article/details/144763719  浏览:    关键词:【C++】string的模拟实现

1. string的成员变量

string类似于一个可动态扩容的字符数组,这里我们就用一个字符指针来实现其大致的结构

namespace yidai
{class string {public://...private:char* _str;//字符指针,指向存储字符串,可动态扩容size_t _size;//string中有效字符的个数,不包含‘\0’size_t _capacity;//当前开辟的空间大小};
}

2. string的成员函数

(说明:以下成员函数为声明和定义分离实现,所以需要声明类域)

2.1 string的初始化、赋值和销毁

  1. string的构造函数
	string::string(const char* str = “”)//缺省参数,防止缺少默认构造函数:_size(strlen(str)){_str = new char[_size + 1];_capacity = _size;strcpy(_str, str);}
  1. string的拷贝构造函数

2.1 传统写法

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

2.2现代写法

	//拷贝构造 现代写法string::string(const string& s){string tmp(s._str);swap(tmp);}

string类中的swap函数

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

2.3 传统写法和现代写法的区别:
传统写法和现代写法在作用上没有什么区别,唯一的区别就是现代写法更简洁,通过构造函数构造临时对象tmp,在调用string中的swap函数将两个对象的数据进行交换,函数结束,临时对象tmp的数据就会被析构

  1. 赋值运算符重载函数

传统写法

	string& string::operator=(const string& s){if (this != &s){char* tmp = new char[s.size() + 1]{'\0'};strcpy(tmp, s._str);delete[] _str;_str = tmp;_capacity = s._capacity;_size = s._size;}return *this;}

现代写法

	string& string::operator=(const string& s){if (this != &s){string tmp(s._str);swap(tmp);}return *this;}

更加简洁的现代写法

	string& string::operator=(string tmp)//更绝的赋值重载现代写法{swap(tmp);return *this;}

这里tmp也是一个临时对象,函数结束时就销毁

  1. 析构函数
	string::~string(){delete[] _str;_str = nullptr;_capacity = _size = 0;}

2.2 string 的迭代器

用typedef来实现普通迭代器和常量迭代器

	typedef char* iterator;//普通迭代器typedef const char* const_iterator;//常量迭代器

普通迭代器的实现

	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;}

在这里插入图片描述

2.3string的容量操作

  1. 字符串判空
	bool string::empty() const{return _size == 0;}
  1. 字符串清空
	void string::clear(){_str[0] = '\0';_size = 0;}
  1. 字符串扩容
void string::reserve(size_t n){if(_capacity < n){char* tmp = new char[n + 1];strcpy(tmp, _str);delete[] _str;_str = tmp;_capacity = n;}}

2.4 string的修改操作

  1. 字符串的添加

1.1 void push_back(char ch);

	void string::push_back(char ch){if (_capacity == _size){size_t newcapacity = _capacity == 0 ? 4 : _capacity * 2;reserve(newcapacity);}_str[_size] = ch;_str[_size + 1] = '\0';++_size;}

2.2 void append(const char* str);

	void string::append(const char* str){size_t len = strlen(str);if (_size + len > _capacity){reserve(_size + len);}strcpy(_str + _size, str);_size += len;}

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

operator+=复用push_back进行操作

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

2.4 void insert(size_t pos, char ch);
void insert(size_t pos, const char* str);

void string::insert(size_t pos, char ch){assert(pos <= _size);if (_size == _capacity){size_t newcapacity = _capacity == 0 ? 4 : _capacity * 2;reserve(newcapacity);}//int end = _size;//while (end >= (int)pos)//强转为int,防止end变为-1,与无符号进行比较时,有符号隐式类型转换为无符号,-1转换为无符号是一个很大的数字//{//	_str[end + 1] = _str[end];//	end--;//}int 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){assert(pos <= _size);size_t len = strlen(str);if (len + _size > _capacity){reserve(len + _size);}/*int end = _size;while (end >= (int)pos){_str[end + len] = _str[end];--end;}*/int end = _size + len;while (end > pos + len - 1){_str[end] = _str[end - len];end--;}memcpy(_str + pos, str, len);_size += len;}
  1. 字符串的删除
    2.1 void erase(size_t pos = 0, size_t len = npos);
    从pos位置开始删除len个字符,包含pos位置
	void string::erase(size_t pos, size_t len){assert(pos < _size);//if (len == npos || pos + len >= _size)if (pos + len >= _size)//len=npos时len就为一个非常大的值,因为为len的类型为size_t{_str[pos] = '\0';_size = pos;}else{//size_t end = pos + len;//while (end <= _size)//{//	_str[end - len] = _str[end];//	end++;//}strcpy(_str + pos, _str + pos + len);_size -= len;}}

npos说明:npos是一个无符号整数-1,表示string的类成员变量,表示一个很大的数

const static size_t npos;//类里面进行声明,类外进行定义
const size_t string::npos = -1;//类外定义

2.5 string的比较大小运算符重载

	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);}

2.6 string的其他操作

  1. 获取pos位置后的len个字符的字符串
string string::substr(size_t pos, size_t len){assert(pos < _size);if (pos + len > _size){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;}}
  1. 获取string对应的字符串
	const char* string::c_str() const {return _str;}
  1. 查找字符串,返回npos表示没有找到
	size_t string::find(char ch, size_t pos){for (size_t i = 0; i < _size; i++){if (_str[i] == ch)return i;}return npos;}

string的非成员函数重载(流提取和流插入)

	//流提取istream& yidai::operator>> (istream& is, string& str){str.clear();//char ch;//is >> ch; //不可以这样,这个会忽略掉空格和'\n'char ch = is.get();char buff[128];int i = 0;while (ch != ' ' && ch != '\n'){//str += ch;//没有buff数组的话不断进行+=就回造成大量的扩容buff[i++] = ch;if (i == 127){buff[i] = '\0';str += buff;i = 0;}ch = is.get();}if (i != 0){buff[i] = '\0';str += buff;}return is;}//流插入ostream& yidai::operator<< (ostream& os, const string& str){for (size_t i = 0; i < str.size(); i++){os << str[i];}return os;}

源码

  1. string.h
#define  _CRT_SECURE_NO_WARNINGS 1
#include <iostream>
#include <assert.h>
#include <typeinfo>
using namespace std;
namespace yidai
{class string{public:typedef char* iterator;typedef const char* const_iterator;//string()string(const char* str = "");string(const string& s);~string();//string& operator=(const string& s);//赋值重载传统写法//string& operator=(const string& s);//赋值重载现代写法string& operator=(string tmp);//更绝的赋值重载现代写法iterator begin();iterator end();const_iterator begin() const;const_iterator end() const;const char*  c_str() const;size_t size() const;char& operator[](size_t pos);const char& operator[](size_t pos) const;bool empty() const;void reserve(size_t n = 0);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);//库中的swap函数,T为string消耗比较大,需要进行一次拷贝构造,两次赋值运算//template <class T> void swap(T& a, T& b)//{//	T c(a); a = b; b = c;//}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 buff[16];char* _str;size_t _size;size_t _capacity;//const static int npos = -1;只支持整形是一个特例//const static double npos = -1;不可以const static size_t npos;//类里面进行声明,类外进行定义};istream& operator>> (istream& is, string& str);ostream& operator<< (ostream& os, const string& str);
}
  1. string.cpp
#define  _CRT_SECURE_NO_WARNINGS 1
#include"string.h"namespace yidai
{const size_t string::npos = -1;//const static size_t npos = -1;//string::string()//{//	_str = new char('\0');//	_capacity = 0;//	_size = 0;//}string::string(const char* str):_size(strlen(str)){_str = new char[_size + 1];_capacity = _size;strcpy(_str, str);}//拷贝构造 传统写法//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);swap(tmp);}string::~string(){delete[] _str;_str = nullptr;_capacity = _size = 0;}bool string::empty() const{return _size == 0;}size_t string::size() const{return _size;}string::iterator string::begin(){return _str;}string::iterator string::end(){return _str + _size;}const char* string::c_str() const {return _str;}string::const_iterator string::begin() const{return _str;}string::const_iterator string::end() const{return _str + _size;}char& string::operator[](size_t pos){assert(pos < _size);return _str[pos];}const char& string::operator[](size_t pos) const{assert(pos < _size);return _str[pos];}//传统写法//string& string::operator=(const string& s)//{//	if (this != &s)//	{//		char* tmp = new char[s.size() + 1]{'\0'};//		strcpy(tmp, s._str);//		delete[] _str;//		_str = tmp;//		_capacity = s._capacity;//		_size = s._size;//	}//	return *this;//}//现代写法//string& string::operator=(const string& s)//{//	if (this != &s)//	{//		string tmp(s._str);//		swap(tmp);//	}//	return *this;//}string& string::operator=(string tmp)//更绝的赋值重载现代写法{swap(tmp);return *this;}void string::reserve(size_t n){if(_capacity < n){char* tmp = new char[n + 1];strcpy(tmp, _str);delete[] _str;_str = tmp;_capacity = n;}}void string::push_back(char ch){if (_capacity == _size){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){assert(pos <= _size);if (_size == _capacity){size_t newcapacity = _capacity == 0 ? 4 : _capacity * 2;reserve(newcapacity);}//int end = _size;//while (end >= (int)pos)//强转为int,防止end变为-1,与无符号进行比较时,有符号隐式类型转换为无符号,-1转换为无符号是一个很大的数字//{//	_str[end + 1] = _str[end];//	end--;//}int 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){assert(pos <= _size);size_t len = strlen(str);if (len + _size > _capacity){reserve(len + _size);}/*int end = _size;while (end >= (int)pos){_str[end + len] = _str[end];--end;}*/int 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){assert(pos < _size);//if (len == npos || pos + len >= _size)if (pos + len >= _size)//len=npos时len就为一个非常大的值,以为len的类型为size_t{_str[pos] = '\0';_size = pos;}else{//size_t end = pos + len;//while (end <= _size)//{//	_str[end - len] = _str[end];//	end++;//}strcpy(_str + pos, _str + pos + len);_size -= len;}}size_t string::find(char ch, size_t pos){for (size_t i = 0; i < _size; i++){if (_str[i] == ch)return i;}return npos;}size_t string::find(const char* str, size_t pos){char* p = strstr(_str + pos, str);if (p == nullptr)return npos;return p - _str;}void string::swap(string& s){std::swap(_str,s._str);std::swap(_capacity, s._capacity);std::swap(_size, s._size);}//交换两字符串--非成员函数版void swap(string& s1, string& s2){s1.swap(s2);}string string::substr(size_t pos, size_t len){assert(pos < _size);if (pos + len > _size){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);}void string::clear(){_str[0] = '\0';_size = 0;}istream& yidai::operator>> (istream& is, string& str){str.clear();//char ch;//is >> ch; //不可以这样,这个会忽略掉空格和'\n'char ch = is.get();char buff[128];int i = 0;while (ch != ' ' && ch != '\n'){//str += ch;//没有buff数组的话不断进行+=就回造成大量的扩容buff[i++] = ch;if (i == 127){buff[i] = '\0';str += buff;i = 0;}ch = is.get();}if (i != 0){buff[i] = '\0';str += buff;}return is;}ostream& yidai::operator<< (ostream& os, const string& str){for (size_t i = 0; i < str.size(); i++){os << str[i];}return os;}}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词