string的模擬實現
文章目錄
- string的模擬實現
- 一、淺拷貝和深拷貝
- 1.淺拷貝
- 2.深拷貝
- 3.寫時拷貝
- 二、定義string的成員變量
- 三、string的接口實現
- 1.string的默認成員函數
- (1)構造函數實現
- (2)析構函數實現
- (3)拷貝構造函數
- (4)賦值運算符重載
- 2.string的迭代器實現
- 3.string的容量操作函數
- 4.string的訪問操作函數
- 5.string的修改操作函數
- 6.string的查找函數
- 7.string的c_str和substr
- 8.string的< <= > >= == !=
- 9.string的operator>>
- 四、源代碼總結
- 1.String.h
- 2.String.cpp
一、淺拷貝和深拷貝
1.淺拷貝
2.深拷貝
如果一個類中涉及到資源的管理,其拷貝構造函數、賦值運算符重載以及析構函數必須要顯式給出
一般情況都是按照 深拷貝 提供
3.寫時拷貝
二、定義string的成員變量
三、string的接口實現
1.string的默認成員函數
(1)構造函數實現
這種短小頻繁調用的函數,可以直接定義到類里面,默認是 inline
(2)析構函數實現
這里要注意一下判斷 str是否為空
(3)拷貝構造函數
(4)賦值運算符重載
2.string的迭代器實現
string中迭代器iterator就是一個指針。所以我們直接使用typedef實現
begin()和end() 本質上都是 指針
3.string的容量操作函數
size()、capacity()、clear()、empty()都很簡單!一看就懂!
接下來是reserve(),只要新容量大于舊容量就發生擴容。
4.string的訪問操作函數
這部分較為簡單,其實就是 數組的下表訪問[ ] 和 front()與back()
5.string的修改操作函數
兩個常用的修改函數: push_back()與append()
+=就是在push_back和append的應用!
insert有兩種類型,第一種類似于頭插,第二種類似于任意位置插入
二者都需要挪動數據和檢驗數組的擴容問題
pop_back函數較為簡單!
字符串的刪除函數erase函數類似于尾刪,也可以任意位置刪除
將pos位置后所有字符往前移動len個單位,如果為字符len=1,否則len=字符串長度
6.string的查找函數
find函數既可以查找字符,也可以查找字符串(用strstr函數)
7.string的c_str和substr
8.string的< <= > >= == !=
9.string的operator>>
注意普通istream對象無法提前空格與\n。這是我們就需要一個函數get()來提取
四、源代碼總結
1.String.h
代碼如下(示例):
#define _CRT_SECURE_NO_WARNINGS 1
#pragma once
#include<iostream>
#include<string>
#include<assert.h>
using namespace std;
namespace bit
{class string{public:typedef char* iterator;typedef const char* const_iterator;iterator begin(){return _str;}iterator end(){return _str + _size;}const_iterator begin() const{return _str;}const_iterator end() const{return _str + _size;}/*string():_str(new char[1]{'\0'}),_size(0),_capacity(0){}*/// 短小頻繁調用的函數,可以直接定義到類里面,默認是inlinestring(const char* str = ""){_size = strlen(str);// _capacity不包含\0_capacity = _size;_str = new char[_capacity + 1];strcpy(_str, str);}// 深拷貝問題// s2(s1)/*string(const string& s){_str = new char[s._capacity + 1];strcpy(_str, s._str);_size = s._size;_capacity = s._capacity;}*/void swap(string& s){std::swap(_str, s._str);std::swap(_size, s._size);std::swap(_capacity, s._capacity);}// s2(s1)// 現代寫法string(const string& s){string tmp(s._str);swap(tmp);}// s2 = s1// s1 = s1/*string& operator=(const string& s){if (this != &s){delete[] _str;_str = new char[s._capacity + 1];strcpy(_str, s._str);_size = s._size;_capacity = s._capacity;}return *this;}*/// s1 = s3;//string& operator=(const string& s)//{// if (this != &s)// {// //string tmp(s._str);// string tmp(s);// swap(tmp);// }// return *this;//}// s1 = s3;string& operator=(string tmp){swap(tmp);return *this;}~string(){if (_str){delete[] _str;_str = nullptr;_size = _capacity = 0;}}const char* c_str() const{return _str;}void clear(){_str[0] = '\0';_size = 0;}bool empty() const{return _size == 0;}size_t size() const{return _size;}size_t capacity() const{return _capacity;}// 可讀可寫char& front(){return _str[0];}char& back(){return _str[_size - 1];}// 可讀不可寫const char& front()const{return _str[0];}const char& back()const{return _str[_size - 1];}char& operator[](size_t pos){assert(pos < _size);return _str[pos];}const char& operator[](size_t pos) const{assert(pos < _size);return _str[pos];}/*void copy_on_write(){if (count > 1){深拷貝}}*/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, size_t len = npos);size_t find(char ch, size_t pos = 0);size_t find(const char* str, size_t pos = 0);string substr(size_t pos = 0, size_t len = npos);private://char _buff[16];char* _str = nullptr;size_t _size = 0;size_t _capacity = 0;//static const size_t npos = -1;static const size_t npos;/*static const int N = 10;int buff[N];*/};bool operator<(const string& s1, const string& s2);bool operator<=(const string& s1, const string& s2);bool operator>(const string& s1, const string& s2);bool operator>=(const string& s1, const string& s2);bool operator==(const string& s1, const string& s2);bool operator!=(const string& s1, const string& s2);ostream& operator<<(ostream& out, const string& s);istream& operator>>(istream& in, string& s);
}
2.String.cpp
代碼如下(示例):
#include"string.h"namespace bit
{const size_t string::npos = -1;void string::reserve(size_t n){if (n > _capacity){//cout << "reserve:" << n << endl;char* tmp = new char[n + 1];strcpy(tmp, _str);delete[] _str;_str = tmp;_capacity = n;}}void string::push_back(char ch){if (_size == _capacity){reserve(_capacity == 0 ? 4 : _capacity * 2);}_str[_size] = ch;++_size;_str[_size] = '\0';}string& string::operator+=(char ch){push_back(ch);return *this;}void string::append(const char* str){size_t len = strlen(str);if (_size + len > _capacity){// 大于2倍,需要多少開多少,小于2倍按2倍擴reserve(_size + len > 2 * _capacity ? _size + len : 2 * _capacity);}strcpy(_str + _size, str);_size += len;}string& string::operator+=(const char* str){append(str);return *this;}void string::insert(size_t pos, char ch){assert(pos <= _size);if (_size == _capacity){reserve(_capacity == 0 ? 4 : _capacity * 2);}// 挪動數據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* s){assert(pos <= _size);size_t len = strlen(s);if (_size + len > _capacity){// 大于2倍,需要多少開多少,小于2倍按2倍擴reserve(_size + len > 2 * _capacity ? _size + len : 2 * _capacity);}size_t end = _size + len;while (end > pos + len - 1){_str[end] = _str[end - len];--end;}for (size_t i = 0; i < len; i++){_str[pos + i] = s[i];}_size += len;}void string::erase(size_t pos, size_t len){assert(pos < _size);if (len >= _size - pos){_str[pos] = '\0';_size = pos;}else{for (size_t i = pos + len; i <= _size; i++){_str[i - len] = _str[i];}_size -= len;}}size_t string::find(char ch, size_t pos){assert(pos < _size);for (size_t i = pos; i < _size; i++){if (_str[i] == ch){return i;}}return npos;}size_t string::find(const char* str, size_t pos){assert(pos < _size);const char* ptr = strstr(_str + pos, str);if (ptr == nullptr){return npos;}else{return ptr - _str;}}string string::substr(size_t pos, size_t len){assert(pos < _size);// len大于剩余字符長度,更新一下lenif (len > _size - pos){len = _size - pos;}string sub;sub.reserve(len);for (size_t i = 0; i < len; i++){sub += _str[pos + i];}return sub;}bool operator<(const string& s1, const string& s2){return strcmp(s1.c_str(), s2.c_str()) < 0;}bool operator<=(const string& s1, const string& s2){return s1 < s2 || s1 == s2;}bool operator>(const string& s1, const string& s2){return !(s1 <= s2);}bool operator>=(const string& s1, const string& s2){return !(s1 < s2);}bool operator==(const string& s1, const string& s2){return strcmp(s1.c_str(), s2.c_str()) == 0;}bool operator!=(const string& s1, const string& s2){return !(s1 == s2);}ostream& operator<<(ostream& out, const string& s){for (auto ch : s){out << ch;}return out;}// 17:16繼續istream& operator>>(istream& in, string& s){s.clear();const int N = 256;char buff[N];int i = 0;char ch;//in >> ch;ch = in.get();while (ch != ' ' && ch != '\n'){buff[i++] = ch;if (i == N - 1){buff[i] = '\0';s += buff;i = 0;}//in >> ch;ch = in.get();}if (i > 0){buff[i] = '\0';s += buff;}return in;}
}