当前位置:网站首页>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
边栏推荐
- Development of a horse tourism website (realization of login, registration and exit function)
- Play sonar
- 【obs】官方是配置USE_GPU_PRIORITY 效果为TRUE的
- fabulous! How does idea open multiple projects in a single window?
- 基于人脸识别实现课堂抬头率检测
- 【愚公系列】2022年7月 Go教学课程 006-自动推导类型和输入输出
- Cause analysis and solution of too laggy page of [test interview questions]
- 去了字节跳动,才知道年薪 40w 的测试工程师有这么多?
- 深潜Kotlin协程(二十三 完结篇):SharedFlow 和 StateFlow
- DNS series (I): why does the updated DNS record not take effect?
猜你喜欢
Codeforces Round #804 (Div. 2)(A~D)
1293_ Implementation analysis of xtask resumeall() interface in FreeRTOS
Application practice | the efficiency of the data warehouse system has been comprehensively improved! Data warehouse construction based on Apache Doris in Tongcheng digital Department
Qt不同类之间建立信号槽,并传递参数
浪潮云溪分布式数据库 Tracing(二)—— 源码解析
Deep dive kotlin synergy (XXII): flow treatment
C # generics and performance comparison
3年经验,面试测试岗20K都拿不到了吗?这么坑?
CVE-2022-28346:Django SQL注入漏洞
玩轉Sonar
随机推荐
Solution to the problem of unserialize3 in the advanced web area of the attack and defense world
Summary of weidongshan phase II course content
Hotel
快速上手使用本地测试工具postman
攻防演练中沙盘推演的4个阶段
德总理称乌不会获得“北约式”安全保障
Deep dive kotlin collaboration (the end of 23): sharedflow and stateflow
[C language] objective questions - knowledge points
丸子官网小程序配置教程来了(附详细步骤)
Course of causality, taught by Jonas Peters, University of Copenhagen
Experience of autumn recruitment in 22 years
Service mesh introduction, istio overview
C # generics and performance comparison
Huawei switch s5735s-l24t4s-qa2 cannot be remotely accessed by telnet
Is it safe to open an account on the official website of Huatai Securities?
Development of a horse tourism website (realization of login, registration and exit function)
牛客基础语法必刷100题之基本类型
jemter分布式
语义分割模型库segmentation_models_pytorch的详细使用介绍
Jouer sonar