作文目的
本文是为了加深对string底层函数的一点理解(请勿与底层源码混为一谈),下面从模拟与注意项出发。
一.string 功能化模拟
1.迭代器模拟
迭代器,为实现简单便理解故使用指针的方式(非说明迭代器使用该方法实现)。其中的begin、end都是为了给迭代器提供范围。迭代器也只认该俩函数(不可使用其他名称)。
typedef char* iterator;
typedef const char* const_iterator;
const_iterator begin()const {
return _str;
}
const_iterator end()const {
return _str + _size;
}
iterator begin(){
return _str;
}
iterator end(){
return _str + _size;
}
char& operator[](size_t pos)const{
assert(pos<_size);
return _str[pos];
}
const char operator[](size_t pos)const{
assert(pos<_size);
return _str[pos];
}
2.reserve模拟
该模拟块的实现在于空间的扩展,该处的空间扩展方案并不受限制 可自行选择。切记释放空间,防止空间浪费(好习惯)。
void reserve(size_t sub){
if(sub>_capacity){
char* ret=new char[sub+1];
delete []_str;
_str=ret;
_capacity=sub;
}
}
3.resize模拟实现块
该模块的实现需要分清情况,他是要扩大有效值范围,还是缩小范围,如果扩大是否有填充值,最大空间是否能够容纳,如:在不定义填充值时补充缺省值 \0,即不改变数据也扩大了空间,也能在需要时不必重构函数接口。
void resize(size_t size,char ch='\0'){
if(size<_size){
_str[size]='\0';
}
else{
//可省略判断
if(size>_capacity){
reserve(size);
}
for(int i =_size;i<size;i++)
{
_str[i]=ch;
}
_str[size]='\0';
}
_size=size;
}
4.insert 模拟实现块
在insert接口,不仅仅要实现单字符的插入,还要可插入字符串的能力;同时不管_str中是否有值
都要追加值,但是如果指定插入点超出实际有效值长时,也必须处理。其次空间不足时也得先扩充空间,不然会出现错误访问。
void insert(size_t pos, char ch) {
assert(pos <= _size);
if (_size == _capacity) {
reserve(_capacity == 0 ? 4 : 2 * _capacity);
}
//腾出一块空间,将pos之后的数据后移
size_t end = _size + 1;
while (end > pos) {
_str[end] = _str[end - 1];
end--;
}
_str[pos] = ch;
_size++;
}
void insert(size_t pos, const char* str) {
assert(pos <= _size);
int size = strlen(str);
if (size + _size > _capacity) {
reserve(size + _size);
}
int end = _size + size;
//下标
while (end > _size + size-1) {
_str[end] = _str[end - size];
end--;
}
//在pos位置开始拷贝插入size个
strncpy(_str + pos, str,size);
_size += size;
}
5.erase模拟实现块
该接口主在优化,当len大于_size,则一定是全删,不必浪费时间去处理,只有有值得有效调动是 才前移数据。
void erase (size_t pos = 0, size_t len = npos)
{
assert (pos <_size);
if(len>=_size-pos){
_str[pos]='\0';
}
else{
while (_size>pos+len)
{
_str[pos]=_str[pos+len];
pos++;
}
}
_size-=pos
}
6.find模拟实现块
find查找函数,与平时写的查找函数没什么区别,无非就是别越界。
size_t find (char c, size_t pos = 0) const;
{
assert(pos<_size);
for(int i=pos;i<_size;i++){
if(_s[i]==c){
return i;
}
}
return npos;
}
size_t find (const char* c, size_t pos = 0) const;
{
assert(pos<_size);
const char*p=strstr(_str+pos,c);
if(p)
return p-_str;
else
return npos;
}
7.substr模拟实现块
截取函数,顾名思义就是截取指定长度中有的效数据,当指定截取范围远大于有效范围是就只截取有效范围内的数据。
string substr (size_t pos = 0, size_t len = npos) const
{
assert(pos<_size);
string st="";
if(len>=_size-pos)
{
for(int i=pos;i<_size;i++)
{
st+=_str[i];
}
}
else{
for(int i=pos;i<pos+len;i++)
{
st+=_str[i];
}
}
return st;
}
8.输入流
第一个代码并非有错误,但是他不太胜任这份工作,他对接口的调用太过于频繁,产生极大且不必要的浪费,故代码二采用模拟缓冲区的办法减轻对接口的调用浪费。
ps: in.get()是输入流提供的一个接收缓冲区单字符的接口,弥补cin不能读储空字符与换行符的缺点
ps: clear每次插入数据,都是一个新值,故清空空间。
/*istream& operator>> (istream& is, string& str)
{
str.clear();
char ch;
ch=is.get();
while(ch!=' '&&ch!='\n'){
ch=is.get();
str+=ch;
}
return str;
}
*/
istream& operator>> (istream& is, string& str)
{
str.clear();
int i=0;char ch;
char buff[128]="";
ch=is.get();
while(ch!=' '&&ch!='\n'){
buff[i]=ch;
i++;
if(i==127)
{
buff[127]='\0';
i=0;
str+=buff;
}
ch=is.get();
}
buff[i]='\0';
str+=buff;
return is;
}
istream& getlien(istream& is, string& str)
{
str.clear();
int i=0;char ch;
char buff[128]="";
ch=is.get();
while(ch!='\n'){
buff[i]=ch;
i++;
if(i==127)
{
buff[127]='\0';
i=0;
str+=buff;
}
ch=is.get();
}
buff[i]='\0';
str+=buff;
return is;
}
9.拷贝函数
两种方法都是按同一个方向指向,仅方法实现不同。
// s2(s1)
/*string(const string& s)
{
_str = new char[s._capacity + 1];
strcpy(_str, s._str);
_size = s._size;
_capacity = s._capacity;
}*/
// s1 = s3;
/*string& operator=(const string& s)
{
char* tmp = new char[s._capacity + 1];
strcpy(tmp, s._str);
delete[] _str;
_str = tmp;
_size = s._size;
_capacity = s._capacity;
return *this;
}*/
string(string &str){
string tmp(str);
swap(str);
}
string& operator+(string str){
swap(str);
return *this;
}
二.完整版
#pragma once
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<assert.h>
using namespace std;
namespace bit {
class string {
public:
typedef char* iterator;
typedef const char* const_iterator;
const_iterator begin()const {
return _str;
}
const_iterator end()const {
return _str + _size;
}
iterator begin() {
return _str;
}
iterator end() {
return _str + _size;
}
string(const char* str = " ")
:_size(strlen(str))
{
_str = new char[_size + 1];
strcpy(_str, str);
_capacity = _size;
}
string(const string &str)
{
string tmp(str._str);
swap(tmp);
}
string& operator=( string str)
{
swap(str);
return *this;
}
~string(){
delete[] _str;
_str= nullptr;
_size = _capacity = 0;
}
size_t size()const {
return _size;
}
const char* c_str()const {
return _str;
}
size_t capacity() {
return _capacity;
}
void clear() {
_str[0] = '\0';
_size = 0;
}
const char& operator[](size_t i)const {
assert(i < _size);
return _str[i];
}
char& operator[](size_t i) {
assert(i < _size);
return _str[i];
}
void reserve(size_t sub) {
if (sub > _capacity) {
char* ret = new char[sub + 1];
strcpy(ret, _str);
delete[] _str;
_str = ret;
_capacity = sub;
}
}
void resize(size_t size, char ch = '\0') {
if (size <= _size) {
_str[size] = '\0';
_size = size;
}
else {
if (size > _capacity) {
reserve(size);
}
for (int i = _size; i < size; i++)
{
_str[i] = ch;
}
_str[size] = '\0';
_size = size;
}
}
void insert(size_t pos, char ch) {
assert(pos <= _size);
if (_size == _capacity) {
reserve(_capacity == 0 ? 4 : 2 * _capacity);
}
size_t end = _size + 1;
while (end > pos) {
_str[end] = _str[end - 1];
end--;
}
_str[pos] = ch;
_size++;
}
void insert(size_t pos, const char* str) {
assert(pos <= _size);
int size = strlen(str);
if (size + _size > _capacity) {
reserve(size + _size);
}
int end = _size + size;
while (end > pos+size-1) {
_str[end] = _str[end - size];
end--;
}
strncpy(_str + pos, str, size);
_size += size;
}
void append(const char* str) {
insert(_size, str);
}
void push_back(const char ch) {
insert(_size, ch);
}
string& operator+= (const char* s) {
append(s);
return *this;
}
string& operator+= (const char s) {
push_back(s);
return *this;
}
void erase(size_t pos = 0, size_t len = npos) {
assert(pos < _size);
if (len >= _size) {
_str[pos]= '\0';
}
else {
while (_size > pos + len)
{
_str[pos]=_str[pos + len];
pos++;
}
_str[pos]= '\0';
}
_size -= pos;
}
void swap(string& str) {
std::swap(_str, str._str);
std::swap(_size, str._size);
std::swap(_capacity, str._capacity);
}
size_t find(char c,size_t pos=0)const
{
assert(pos < _size);
for (int i = pos; i < _size; i++) {
if (_str[i]== c) {
return i;
}
}
return npos;
}
size_t find(const char* c, size_t pos = 0) const
{
assert(pos <= _size);
const char* p = strstr(_str + pos, c);
if (p)
return p - _str;
else
return npos;
}
string substr(size_t pos = 0, size_t len = npos) const
{
string st = " ";
assert(pos <= _size);
if (len >= _size- pos)
{
for (size_t i = pos; i< _size;i++)
{
st+=_str[i];
}
}
else{
for (size_t i = pos; i< pos + len;i++)
{
st+=_str[i];
}
}
return st;
}
static const int npos;
private:
char* _str = nullptr;
size_t _size = 0;
size_t _capacity = 0;
};
const int string::npos = -1;
void swap(string& rhs, string& lhs) {
rhs.swap(lhs);
}
bool operator==(const string& rhs, const string& lhs) {
return !strcmp(rhs.c_str(), lhs.c_str());
}
bool operator!=(const string& rhs, const string& lhs) {
return !(rhs == lhs);
}
bool operator>(const string& rhs, const string& lhs) {
return strcmp(rhs.c_str(), lhs.c_str());
}
bool operator>=(const string& rhs, const string& lhs) {
return rhs == lhs || rhs > lhs;
}
bool operator<(const string& rhs, const string& lhs) {
return !(rhs >= lhs);
}
bool operator<=(const string& rhs, const string& lhs) {
return (rhs == lhs) || (rhs < lhs);
}
ostream& operator<<(ostream& os, const string& str)
{
for (auto ret :str)
{
os << ret;
}
return os;
}
istream& operator>> (istream& is, string& str)
{
str.clear();
int i = 0; char ch;
char buff[128] = "";
ch = is.get();
while (ch != ' ' && ch != '\n') {
buff[i]=ch;
i++;
if (i == 127)
{
buff[128]='\0';
i = 0;
str+=buff;
}
ch = is.get();
}
buff[i]= '\0';
str+=buff;
return is;
}
istream& getline(istream& is, string& str)
{
str.clear();
size_t i = 0; char ch;
char buff[128] = "";
ch = is.get();
while (ch != '\n') {
buff[i] = ch;
i++;
if (i == 127)
{
buff[127] = '\0';
str += buff;
i = 0;
}
ch = is.get();
}if (i > 0) {
buff[i] = '\0';
str += buff;
}
return is;
}
}
本文多在理解,感谢观看!