当前位置:网站首页>STL -- common function replication of string class
STL -- common function replication of string class
2022-07-08 00:49:00 【New Young】
List of articles
Preface :
string First knowledge of class
- string The essence is basic_string Rename the instantiated template class , It contains many member functions that handle strings : Replanted [],= etc.
typedef basic_string<char> string;
Namespace
I'm copying string Class time , because string Class is a built-in type in the standard library , To avoid naming pollution , You can name your own namespace
// complete string Add, delete, check, modify, duplicate
namespace My_Str // To prevent pollution std Namespace
{
class string
{
private:
char* _str;
int _size;// Number of valid characters
int _capacity;// The capacity of valid characters , It doesn't contain '\0', But because when opening up space, open up one more ,
// Therefore, one is reserved by default '\0', Easy to carry out C function
......
};
Data member
Here we use array form , Convenient operation
namespace My_Str // To prevent pollution std Namespace
{
class string
{
private:
char* _str;
int _size;// Number of valid characters
int _capacity;// The capacity of valid characters , It doesn't contain '\0', But because when opening up space, open up one more ,
// Therefore, one is reserved by default '\0', Easy to carry out C function
Constructors
string The standard cannot use a single character in initialization , You can only use strings or existing objects .
It is recommended to use Modern writing , It makes use of the automatic destruction of local variables after the frame of function stack and the flexible reuse of code
Custom constructors
- All default constructors , For empty strings ,_size by 0, Pay attention to when expanding
// All default constructors , For empty strings ,_size by 0, Pay attention to when expanding
//string(const char* str="");
My_Str::string::string(const char* str)
:_size(strlen(str)), _capacity( _size)
{
_str = new char[_capacity+1];//+1 It's for \0 Reserve space , prevent
strcpy(_str, str);
}
copy constructor
- Without reference , The transfer of arguments to formal parameters is also a copy
- When there are members who need dynamic management , Prevent shallow copy from causing multiple attacks on the same space delete problem
- Modern writing , The essence is the reuse of code and the post frame destruction of local variable function stack
// Copy structure , Be careful
// 1. Without reference , The transfer of arguments to formal parameters is also a copy
// 2. When there are members who need dynamic management , Prevent shallow copy from causing multiple attacks on the same space delete problem
My_Str::string::string(const string& s)
{
General writing
//_str = new char[strlen(s._str) + 1];
//strcpy(_str, s._str);
//_size = s._size;
//_capacity = s._capacity;
Modern writing , The essence is the reuse of code and the post frame destruction of local variable function stack
string tmp(s._str);// A custom constructor was called
_str = nullptr;// This step must have , Otherwise, the random values are delete
swap(tmp);//string Under the swap function
//std::swap(_str,tmp._str);// Under the standard library swap template function
_size = tmp._size;
_capacity = tmp._capacity;
}
Assignment operator
Generally, we need to consider the problem of self assignment
Modern writing , Because the address of the copied object is different , Therefore, there is no need to consider the problem of self assignment and releasing the same space multiple times
My_Str::string& My_Str::string::operator=(const My_Str::string& s)
{
// Assignment of itself
//if (&s != this)
//{
// // General writing :
// char *tmp = new char[s._size + 1];// Prevent application failure ,C++ Of new Would throw exceptions , Not learned
// strcpy(tmp, s._str);
// delete[]_str;// Release the original space
// _str = tmp;// After the local variable is destroyed , Heap space still exists .
// _size = s._size;
// _capacity = s._capacity;
//}
// Modern writing , There is no need to consider the problem of self assignment and releasing the same space multiple times
string tmp(s);//
std::swap(_str, tmp._str);
_size = tmp._size;
_capacity = tmp._capacity;
return *this;
}
Destructor
My_Str::string::~string()// Destructor
{
delete[]_str;
_str = nullptr;
_size =_capacity= 0;
}
c_str()
const char* My_Str::string::c_str()
{
return _str;
}
const char* My_Str::string::c_str()const
{
return _str;
}
clear()
void My_Str::string::clear()
{
_size = 0;
}
size()
size_t My_Str::string::size()
{
return _size;
}
size_t My_Str::string::size()const
{
return _size;
}
The operator []
char& My_Str::string::operator[](size_t pos)
{
assert(pos < _size);
return _str[pos];
}
const char& My_Str::string::operator[](size_t pos)const
{
assert(pos < _size);
return _str[pos];
}
iterator
iterator , For the time being, the pointer
typedef char* iterator;
typedef const char* const_iterator;
My_Str::string::iterator My_Str::string::begin()
{
return _str;
}
My_Str::string::iterator My_Str::string::end()
{
return _str + _size ;
}
My_Str::string::const_iterator My_Str::string::begin()const
{
return _str;
}
My_Str::string::const_iterator My_Str::string::end()const
{
return _str + _size;
}
Expansion function
reserve()
Scaling down is not supported , So just think about n>_capacity The situation of
void My_Str::string::reserve(size_t n)
{
if(n > _capacity)
{
char* tmp = new char[n+1];
strcpy(tmp,_str);
delete[]_str;
_str = tmp;
_capacity = n;
}
}
resize()
Support shrinking and expanding , So we need to size As a boundary , Consideration
void My_Str::string::resize(size_t n, char ch)
{
//resize Scaling down is not supported _capacity;
if (n <= _size)
{
_str[n] = '\0';
_size = n;
}
else
{
if (n > _capacity)
{
reserve(n);
}
memset(_str + _size, ch, n - _size);
_str[_size] = '\0';
}
}
Insert
Tail insertion
- Single character , Just expand the capacity according to the situation 2 Times ,
- But for Strings , Its number cannot be empty , Therefore, the expansion depends on the situation .
- It is more recommended to use +=;
push_back()
void My_Str::string::push_back(char ch)
{
if (_size == _capacity)
{
reserve(_capacity==0?4:_capacity*2);
}
_str[_size] = ch;
++_size;
_str[_size] = '\0';
}
append()
void My_Str::string::append(const char* str)
{
size_t len = strlen(str);
if ((len + _size) > _capacity)
{
reserve(len + _size);
}
strcpy(_str + _size, str);
}
The operator +=
My_Str::string& My_Str::string::operator +=(const char ch)
{
push_back(ch);
return *this;
}
My_Str::string& My_Str::string::operator +=(const char* str)
{
append(str);
return *this;
}
Head insertion
insert()
Head insertion , It is generally not recommended to use , Low efficiency
My_Str::string& My_Str::string::insert(size_t pos, const char ch)
{
assert(pos <= _size);
if (_size == _capacity)
{
reserve(_capacity == 0 ? 4 : _capacity * 2);
}
// Because it is an unsigned integer , In the subtraction operation, we should pay attention to the problem of dead circulation
size_t end = _size+1;
while (end > pos)
{
_str[end] = _str[end - 1];
--end;
}
_str[pos] = ch;
return *this;
}
My_Str::string& My_Str::string::insert(size_t pos, const char* str)
{
assert(pos <= _size);
size_t len = strlen(str);
if (_size + len > _capacity)
{
reserve(_size + len);
}
size_t end = _size + len;
while (end > pos+len)
{
_str[end] = _str[end - len];
--end;
}
strncpy(_str + pos, str,len);
//strcpy Will '\0 Add in '
return *this;
}
check
find()
size_t My_Str::string::find(char ch)
{
for (size_t i = 0; i < _size; ++i)
{
if (ch == _str[i])
{
return i;
}
}
return npos;
}
size_t My_Str::string::find(const char* str, size_t pos)
{
assert(pos < _size&& strlen(str)<_size);
const char* ret = strstr(_str, str);
if (ret != nullptr)
{
return ret - _str;
}
return npos;
}
Delete
erase()
My_Str::string& My_Str::string::erase(size_t pos , size_t len )
{
assert(pos < _size);
if (len == npos || len >= (_size - pos))// Delete all
{
_str[pos] = '\0';
_size = pos;
}
else
{
strcpy(_str + pos, _str + pos + len);
_size -= len;
}
return *this;
}
I / O function
operator<<()
std::ostream& operator<<(std::ostream& out, const My_Str::string& s)
{
for (int i = 0; i < s.size(); ++i)// Finite cycles , You can avoid strings containing '\0' The situation of
{
out << s[i];
}
//cout<<s.c_str();
return out;
}
operator>>()
std::istream& operator >> (std::istream& in, My_Str::string& s)
{
char ch = 0;
//ch = getchar();
//while (ch != ' '&&ch!='\n')
//{
// s += ch;
// ch = getchar();
//}
s.clear();
ch = in.get();
while (ch != ' '&&ch!='\n')
{
s += ch;
ch = in.get();
}
return in;
}
Comparison function
because string There are a lot of interfaces for , Here, overloaded functions are defined as global functions
operator<()
//"abcd" "abcd" false
//"abcd" "abcde"true
//"abcde" "abcd"false
bool operator<(const My_Str::string& s1, const My_Str::string& s2)
{
size_t i1 = 0;
size_t i2 = 0;
while ( i1< s1.size()&& i2<s2.size())
{
if (s1[i1] < s2[i2])
{
return false;
}
++i1;
++i2;
}
return i1 < s1.size() ? false : true;
}
operator==()
bool operator==(const My_Str::string& s1, const My_Str::string& s2)
{
size_t i1 = 0;
size_t i2 = 0;
while (i1 < s1.size() && i2 < s2.size())
{
if (s1[i1] != s2[i2])
{
return false;
}
++i1;
++i2;
}
return i1 == s1.size() && i2 == s2.size() ? true : false;
}
operator!=()
bool operator!=(const My_Str::string& s1, const My_Str::string& s2)
{
return !(s1 == s2);
}
operator<=()
bool operator<=(const My_Str::string& s1, const My_Str::string& s2)
{
return s1 < s2 || s1 == s2;
}
operator>()
bool operator>(const My_Str::string& s1, const My_Str::string& s2)
{
return !(s1 <= s2);
}
operator>=()
bool operator>=(const My_Str::string& s1, const My_Str::string& s2)
{
return !(s1 < s2);
}
All the code
String.h
#pragma once
#include<iostream>
#include<string>
#include<assert.h>
// complete string Add, delete, check, modify, duplicate
namespace My_Str // To prevent pollution std Namespace
{
class string
{
private:
char* _str;
int _size;// Number of valid characters
int _capacity;// The capacity of valid characters , It doesn't contain '\0', But because when opening up space, open up one more ,
// Therefore, one is reserved by default '\0', Easy to carry out C function
public:
static const size_t npos;
// All default constructors , Cannot assign with null pointer , There will be a wild pointer problem
string(const char* str="");
// Custom copy construction ,
// 1. Without reference , The transfer of arguments to formal parameters is also a copy
// 2. The default copy structure is shallow copy , When there are members who need dynamic management , Prevent shallow copy from causing multiple attacks on the same space delete problem
// This is also the reason for modern writing
string(const string& s);
// Destructor
~string();
void swap(string& s);
// Assignment operator
string& operator=(const string& s);
// The first address of the character .
const char* c_str();
const char* c_str()const;
size_t size();
size_t size()const ;
char& operator[](size_t pos);
const char& operator[](size_t pos)const;
// iterator , For the time being, the pointer
// Ordinary objects overlap
typedef char* iterator;
iterator begin();
iterator end();
// Regular object
typedef const char* const_iterator;
const_iterator begin()const;
const_iterator end()const;
// Capacity expansion
void reserve(size_t n);// Scaling down is not supported
void resize(size_t n, char ch='\0');// Support shrinking and expanding
// Insert , It's more about use +=
// Head insertion , It is generally not recommended to use , Low efficiency
string& insert(size_t pos, const char ch);
string& insert(size_t pos, const char *str);
// Tail insertion ,
// Single character , Just expand the capacity according to the situation 2 Times ,
// But for Strings , Its number cannot be empty , Therefore, the expansion depends on the situation .
//
void push_back(char ch);
void append( const char* str);
string& operator +=(const char ch);
string& operator +=(const char* str);
// Delete
string& erase(size_t pos = 0, size_t len = npos);
// check
size_t find(char ch);
size_t find(const char* str, size_t pos = 0);
};
}
std::ostream &operator<<(std::ostream& out, const My_Str::string& s);
std::istream& operator >> (std::istream& in, My_Str::string& s);
bool operator<(const My_Str::string& s1, const My_Str::string& s2);
bool operator==(const My_Str::string& s1, const My_Str::string& s2);
bool operator!=(const My_Str::string& s1, const My_Str::string& s2);
bool operator<=(const My_Str::string& s1, const My_Str::string& s2);
bool operator>(const My_Str::string& s1, const My_Str::string& s2);
bool operator>=(const My_Str::string& s1, const My_Str::string& s2);
String.cpp
#define _CRT_SECURE_NO_WARNINGS
#include"String.h"
const size_t My_Str::string::npos=-1;
// All default constructors , For empty strings ,_size by 0, Pay attention to when expanding
My_Str::string::string(const char* str)
:_size(strlen(str)), _capacity( _size)
{
_str = new char[_capacity+1];
strcpy(_str, str);
}
// Copy structure , Be careful
// 1. Without reference , The transfer of arguments to formal parameters is also a copy
// 2. When there are members who need dynamic management , Prevent shallow copy from causing multiple attacks on the same space delete problem
// 3. This is also the reason for modern writing
My_Str::string::string(const string& s)
{
General writing
//_str = new char[strlen(s._str) + 1];
//strcpy(_str, s._str);
//_size = s._size;
//_capacity = s._capacity;
Modern writing , The essence is the reuse of code and the post frame destruction of local variable function stack
string tmp(s._str);// A custom constructor was called
_str = nullptr;// This step must have , Otherwise, the random values are delete
swap(tmp);//string Under the swap function
//std::swap(_str,tmp._str);// Under the standard library swap template function
_size = tmp._size;
_capacity = tmp._capacity;
}
My_Str::string::~string()// Destructor
{
delete[]_str;
_str = nullptr;
_size =_capacity= 0;
}
void My_Str::string::swap(string& s)
{
std::swap(_str, s._str);
std::swap(_size, s._size);
std::swap(_capacity, s._capacity);
}
My_Str::string& My_Str::string::operator=(const My_Str::string& s)
{
// Assignment of itself
//if (&s != this)
//{
// // General writing :
// char *tmp = new char[s._size + 1];// Prevent application failure ,C++ Of new Would throw exceptions , Not learned
// strcpy(tmp, s._str);
// delete[]_str;// Release the original space
// _str = tmp;// After the local variable is destroyed , Heap space still exists .
// _size = s._size;
// _capacity = s._capacity;
//}
// Modern writing , There is no need to consider the problem of self assignment and releasing the same space multiple times
string tmp(s);//
std::swap(_str, tmp._str);
_size = tmp._size;
_capacity = tmp._capacity;
return *this;
}
// The first address of the character .
const char* My_Str::string::c_str()
{
return _str;
}
const char* My_Str::string::c_str()const
{
return _str;
}
size_t My_Str::string::size()
{
return _size;
}
size_t My_Str::string::size()const
{
return _size;
}
char& My_Str::string::operator[](size_t pos)
{
assert(pos < _size);
return _str[pos];
}
const char& My_Str::string::operator[](size_t pos)const
{
assert(pos < _size);
return _str[pos];
}
My_Str::string::iterator My_Str::string::begin()
{
return _str;
}
My_Str::string::iterator My_Str::string::end()
{
return _str + _size ;
}
My_Str::string::const_iterator My_Str::string::begin()const
{
return _str;
}
My_Str::string::const_iterator My_Str::string::end()const
{
return _str + _size;
}
void My_Str::string::reserve(size_t n)
{
if(n > _capacity)
{
char* tmp = new char[n+1];
strcpy(tmp,_str);
delete[]_str;
_str = tmp;
_capacity = n;
}
}
void My_Str::string::resize(size_t n, char ch)
{
//resize Scaling down is not supported _capacity;
if (n <= _size)
{
_str[n] = '\0';
_size = n;
}
else
{
if (n > _capacity)
{
reserve(n);
}
memset(_str + _size, ch, n - _size);
_str[_size] = '\0';
}
}
void My_Str::string::push_back(char ch)
{
if (_size == _capacity)
{
reserve(_capacity==0?4:_capacity*2);
}
_str[_size] = ch;
++_size;
_str[_size] = '\0';
}
void My_Str::string::append(const char* str)
{
size_t len = strlen(str);
if ((len + _size) > _capacity)
{
reserve(len + _size);
}
strcpy(_str + _size, str);
}
My_Str::string& My_Str::string::operator +=(const char ch)
{
push_back(ch);
return *this;
}
My_Str::string& My_Str::string::operator +=(const char* str)
{
append(str);
return *this;
}
size_t My_Str::string::find(char ch)
{
for (size_t i = 0; i < _size; ++i)
{
if (ch == _str[i])
{
return i;
}
}
return npos;
}
size_t My_Str::string::find(const char* str, size_t pos)
{
assert(pos < _size&& strlen(str)<_size);
const char* ret = strstr(_str, str);
if (ret != nullptr)
{
return ret - _str;
}
return npos;
}
My_Str::string& My_Str::string::insert(size_t pos, const char ch)
{
assert(pos <= _size);
if (_size == _capacity)
{
reserve(_capacity == 0 ? 4 : _capacity * 2);
}
// Because it is an unsigned integer , In the subtraction operation, we should pay attention to the problem of dead circulation
size_t end = _size+1;
while (end > pos)
{
_str[end] = _str[end - 1];
--end;
}
_str[pos] = ch;
return *this;
}
My_Str::string& My_Str::string::insert(size_t pos, const char* str)
{
assert(pos <= _size);
size_t len = strlen(str);
if (_size + len > _capacity)
{
reserve(_size + len);
}
size_t end = _size + len;
while (end > pos+len)
{
_str[end] = _str[end - len];
--end;
}
strncpy(_str + pos, str,len);
//strcpy Will '\0 Add in '
return *this;
}
My_Str::string& My_Str::string::erase(size_t pos , size_t len )
{
assert(pos < _size);
if (len == npos || len >= (_size - pos))// Delete all
{
_str[pos] = '\0';
_size = pos;
}
else
{
strcpy(_str + pos, _str + pos + len);
_size -= len;
}
return *this;
}
//
//"abcd" "abcd" false
//"abcd" "abcde"true
//"abcde" "abcd"false
bool operator<(const My_Str::string& s1, const My_Str::string& s2)
{
size_t i1 = 0;
size_t i2 = 0;
while ( i1< s1.size()&& i2<s2.size())
{
if (s1[i1] < s2[i2])
{
return false;
}
++i1;
++i2;
}
return i1 < s1.size() ? false : true;
}
bool operator==(const My_Str::string& s1, const My_Str::string& s2)
{
size_t i1 = 0;
size_t i2 = 0;
while (i1 < s1.size() && i2 < s2.size())
{
if (s1[i1] != s2[i2])
{
return false;
}
++i1;
++i2;
}
return i1 == s1.size() && i2 == s2.size() ? true : false;
}
bool operator!=(const My_Str::string& s1, const My_Str::string& s2)
{
return !(s1 == s2);
}
bool operator<=(const My_Str::string& s1, const My_Str::string& s2)
{
return s1 < s2 || s1 == s2;
}
bool operator>(const My_Str::string& s1, const My_Str::string& s2)
{
return !(s1 <= s2);
}
bool operator>=(const My_Str::string& s1, const My_Str::string& s2)
{
return !(s1 < s2);
}
std::ostream& operator<<(std::ostream& out, const My_Str::string& s)
{
for (int i = 0; i < s.size(); ++i)// Finite cycles , You can avoid strings containing '\0' The situation of
{
out << s[i];
}
//cout<<s.c_str();
return out;
}
std::istream& operator >> (std::istream& in, My_Str::string& s)
{
char ch = 0;
//ch = getchar();
//while (ch != ' '&&ch!='\n')
//{
// s += ch;
// ch = getchar();
//}
ch = in.get();
while (ch != ' '&&ch!='\n')
{
s += ch;
ch = in.get();
}
return in;
}
summary
Dealing with boundary problems , Be careful , Otherwise, the program may CREASH
边栏推荐
- Jouer sonar
- 华泰证券官方网站开户安全吗?
- v-for遍历元素样式失效
- 51 communicates with the Bluetooth module, and 51 drives the Bluetooth app to light up
- Development of a horse tourism website (optimization of servlet)
- 5G NR 系统消息
- RPA云电脑,让RPA开箱即用算力无限?
- What is load balancing? How does DNS achieve load balancing?
- Qt不同类之间建立信号槽,并传递参数
- Prompt configure: error: required tool not found: libtool solution when configuring and installing crosstool ng tool
猜你喜欢
接口测试进阶接口脚本使用—apipost(预/后执行脚本)
Langchao Yunxi distributed database tracing (II) -- source code analysis
NVIDIA Jetson测试安装yolox过程记录
国外众测之密码找回漏洞
After going to ByteDance, I learned that there are so many test engineers with an annual salary of 40W?
测试流程不完善,又遇到不积极的开发怎么办?
3年经验,面试测试岗20K都拿不到了吗?这么坑?
Application practice | the efficiency of the data warehouse system has been comprehensively improved! Data warehouse construction based on Apache Doris in Tongcheng digital Department
paddle一个由三个卷积层组成的网络完成cifar10数据集的图像分类任务
【GO记录】从零开始GO语言——用GO语言做一个示波器(一)GO语言基础
随机推荐
Codeforces Round #804 (Div. 2)(A~D)
"An excellent programmer is worth five ordinary programmers", and the gap lies in these seven key points
他们齐聚 2022 ECUG Con,只为「中国技术力量」
Summary of weidongshan phase II course content
Lecture 1: the entry node of the link in the linked list
新库上线 | CnOpenData中华老字号企业名录
Stock account opening is free of charge. Is it safe to open an account on your mobile phone
FOFA-攻防挑战记录
Tencent security released the white paper on BOT Management | interpreting BOT attacks and exploring ways to protect
浪潮云溪分布式数据库 Tracing(二)—— 源码解析
Solution to prompt configure: error: curses library not found when configuring and installing crosstool ng tool
Binder核心API
华泰证券官方网站开户安全吗?
Four stages of sand table deduction in attack and defense drill
Installation and configuration of sublime Text3
How does the markdown editor of CSDN input mathematical formulas--- Latex syntax summary
ABAP ALV LVC template
Cascade-LSTM: A Tree-Structured Neural Classifier for Detecting Misinformation Cascades(KDD20)
商品的设计等整个生命周期,都可以将其纳入到产业互联网的范畴内
C # generics and performance comparison