1. 什么是string
string
是标准模板库(STL)中的一类用来管理字符串数据的数据结构。
2. 模拟实现
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <assert.h>
#include <string>
#include <cstring>
using namespace std;
namespace lzh {
//string正向迭代器
template<class TP>
struct cPtr {
cPtr(TP* ptr) :_ptr(ptr)
{}
cPtr(const cPtr<TP>& p) :_ptr(p._ptr)
{}
bool operator!=(const cPtr<TP>& p) const {
return _ptr != p._ptr;
}
TP& operator*() const {
return *_ptr;
}
cPtr<TP>& operator++() {
++_ptr;
return *this;
}
cPtr<TP> operator++(int) {
cPtr<TP> tmp(*this);
++_ptr;
return tmp;
}
private:
TP* _ptr;
};
//string反向迭代器
template<class TP>
struct rPtr {
rPtr(TP* ptr) :_ptr(ptr)
{}
rPtr(const rPtr<TP>& p) :_ptr(p._ptr)
{}
bool operator!=(const rPtr<TP>& p) const {
return _ptr != p._ptr;
}
TP& operator*() const {
return _ptr[-1];
}
rPtr<TP>& operator++() {
--_ptr;
return *this;
}
rPtr<TP> operator++(int) {
rPtr<TP> tmp(*this);
--_ptr;
return tmp;
}
private:
TP* _ptr;
};
class string {
public:
typedef cPtr<char> iterator;
typedef cPtr<const char> const_iterator;
typedef rPtr<char> reverse_iterator;
typedef rPtr<const char> const_reverse_iterator;
//构造
string(const char* str = "")
:_size(strlen(str)), _capacity(_size + 1) {
_str = new char[_capacity + 1];
memcpy(_str, str, (_size + 1) * sizeof(char));
}
//拷贝构造
string(const string& s)
:_size(strlen(s._str)), _capacity(s._capacity) {
_str = new char[_capacity + 1];
memcpy(_str, s._str, (_size + 1) * sizeof(char));
}
//赋值重载
//1.普通写法
/*string& operator=(const string& s) {
if (this != &s) {
delete[] _str;
_str = new char[s._capacity];
memcpy(_str, s._str, s._capacity * sizeof(char));
_size = s._size;
_capacity = s._capacity;
}
return *this;
}*/
//2.牛b写法
void swap(string& s) {
std::swap(_str, s._str);
std::swap(_size, s._size);
std::swap(_capacity, s._capacity);
}
string& operator=(string s) {
swap(s);
return *this;
}
//析构
~string() {
delete[] _str;
_str = nullptr;
}
iterator begin() {
return cPtr<char>(_str);
}
iterator end() {
return cPtr<char>(_str + _size);
}
const_iterator begin() const {
return cPtr<const char>(_str);
}
const_iterator end() const {
return cPtr<const char>(_str + _size);
}
reverse_iterator rbegin() {
return rPtr<char>(_str + _size);
}
reverse_iterator rend() {
return rPtr<char>(_str);
}
const_reverse_iterator rbegin() const {
return rPtr<const char>(_str + _size);
}
const_reverse_iterator rend() const {
return rPtr<const char>(_str);
}
// modify
//扩容直接开新空间然后拷贝,释放旧的
void reserve(size_t n) {
if (n > _capacity) {
char* temp = new char[n + 1];
memcpy(temp, _str, (_size + 1) * sizeof(char));
delete[] _str;
_str = temp;
_capacity = n;
}
}
void push_back(const char c) {
if (_size == _capacity) {
reserve(_capacity * 2);
}
_str[_size++] = c;
_str[_size] = 0;
}
string& operator+=(const char c) {
push_back(c);
return *this;
}
void append(const char* str) {
size_t len = strlen(str);
if (len + _size > _capacity) {
reserve(len + _size);
}
memcpy(_str + _size, str, len * sizeof(char));
_str[_size += len] = 0;
}
string& operator+=(const char* str) {
append(str);
return *this;
}
void clear() {
_str[_size = 0] = 0;
}
const char* c_str() const {
return _str;
}
// capacity
size_t size() const {
return _size;
}
size_t capacity() const {
return _capacity;
}
bool empty() const {
return _size == 0;
}
//n > size就依次插入
//否则n位置直接设为0,size=n
void resize(size_t n, const char c = '\0') {
while (_size < n) {
push_back(c);
}
_str[_size = n] = 0;
}
// access
char& operator[](size_t index) {
assert(index < _size);
return _str[index];
}
const char& operator[](size_t index) const {
assert(index < _size);
return _str[index];
}
//relational operators
bool operator<(const string& s) const {
int ret = memcmp(_str, s._str, _size < s._size ? _size : s._size);
return ret == 0 ? _size < s._size : ret < 0;
}
bool operator==(const string& s) const {
return _size == s._size && 0 == memcmp(_str, s._str, _size < s._size ? _size : s._size);
}
bool operator<=(const string& s) const {
return *this < s || *this == s;
}
bool operator>(const string& s) const {
return !(*this < s || *this == s);
}
bool operator>=(const string& s) const {
return !(*this < s);
}
bool operator!=(const string& s) const {
return !(*this == s);
}
// 返回c在string中第一次出现的位置
size_t find(char c, size_t pos = 0) const {
assert(pos < _size);
while (pos < _size) {
if (_str[pos++] == c) {
return pos;
}
}
return npos;
}
// 返回子串s在string中第一次出现的位置
size_t find(const char* s, size_t pos = 0) const {
assert(pos < _size);
const char* ptr = strstr(_str, s);
if (nullptr == ptr) {
return npos;
}
return ptr - _str;
}
// 在pos位置上插入字符c/字符串str,并返回该字符的位置
size_t insert(size_t pos, size_t n, const char c) {
if (_size + n > _capacity) {
reserve(_size + n);
}
size_t end = _size + n;
while (end > pos) {
_str[end] = _str[end - n];
--end;
}
for (size_t i = 0; i < n; ++i) {
_str[i + pos] = c;
}
_str[_size += n] = 0;
return pos;
}
size_t insert(size_t pos, const char* str) {
size_t len = strlen(str);
if (len + _size > _capacity) {
reserve(len + _size);
}
size_t end = _size + len;
while (end > pos) {
_str[end] = _str[end - len];
--end;
}
memcpy(_str + pos, str, len * sizeof(char));
_str[_size += len] = 0;
return pos;
}
// 删除pos位置上的元素,并返回该元素的下一个位置
size_t erase(size_t pos, size_t len = npos) {
if (len == npos || len + pos >= _size) {
_str[_size = pos] = 0;
return pos;
}
size_t end = pos + len;
while (end < _size) {
_str[end - len] = _str[end];
++end;
}
_str[_size -= len] = 0;
return pos;
}
string substr(size_t pos, size_t len = npos) {
assert(pos < _size);
string ret;
if (len == npos || pos + len >= _size) {
ret += _str + pos;
return ret;
}
for (size_t i = 0; i < len; ++i) {
ret += _str[i + pos];
}
return ret;
}
friend ostream& operator<<(ostream& _cout, const string& s);
friend istream& operator>>(istream& _cin, string& s);
static size_t npos;
private:
char* _str;
size_t _size;
size_t _capacity;
};
size_t string::npos = -1;
ostream& operator<<(ostream& out, const string& s) {
for (auto& c : s) {
out << c;
}
out << endl;
return out;
}
istream& operator>>(istream& in, string& s) {
//由于cin和scanf类似
//会把空格和换行认为是分割字符直接跳过
//因此若想拿到空格或者换行符需要用到
//对象in里的成员函数get()
char ch = in.get();
while (ch == ' ' || ch == '\n') {
ch = in.get();
}
//每次应该清空字符串
s.clear();
char buffer[128] = { 0 };
size_t i = 0;
while (ch != ' ' && ch != '\n') {
buffer[i++] = ch;
if (i == 126) {
buffer[i] = 0;
s += buffer;
i = 0;
}
ch = in.get();
}
if (i != 0) {
buffer[i] = 10;
s += buffer;
}
return in;
}
}