The six major components of stl for entry into C++--Simulation implementation of String library functions

Article directory

Preface

1. Simulation implementation of String class

1.Construction

1) No-parameter construction

2) Parametric structure

2.Copy construction

3. Assignment operator overloading

3. Destruction

4. Operator overloading

1)operator[  ]

2)operator>

3)operator==

3)operator>=

4)operator<

5)operator<=

6)operator!=

5. Some interface implementations

1)resize

2)reverse

3)begin+end

4)pushback

5)append

6)operator+=

7)insert

8)swap

9)c_str

10)find

11)clear

12)erase

6. Stream insertion and stream extraction

1)operator<<

2)operator>>

Summarize


Preface

In order to gain an in-depth understanding of the underlying principles of the string class, this chapter uses the idea of ​​data structure to manage resources and simulate the implementation of some interfaces of the string class. Specifically, 1. Variables can be defined like int types and support assignment and assignment. 2. Can be used as the parameter type and return type of the function. 3. The element type that can be used as a standard library container, that is, the value_type of vector/list/deque. (Excerpted from coolshell)


1. Simulation implementation of String class

The previous chapter mainly gave a brief introduction to the string class and interface. In many interviews, the interviewer asked students to simulate the implementation of the string class, mainly implementing the construction, copy construction, operator overloading and destructor of the string class. This chapter will introduce them one by one. ideas and implementation methods.

First of all, it must be clear that the string class is encapsulated and constructed from a string. To implement additions, deletions, and modifications in this class, you need the same size and capacity as the sequence table, which respectively represent the number of valid strings and the capacity of this block. the size of.

class string
{
    pubilc:
        //实现一些方法
    private:
        //成员变量
        char * _str;
        size_t _size;   //存多少个有效字符
        size_t _capacity;  //这段空间的大小
}

1. Shallow copy

Also called bit copy, the compiler just copies the value in the object. If the object manages resources, it will eventually lead to multiple objects sharing a resource. When an object is destroyed, the resource will be released, and At this time, other objects do not know that the resource has been released, thinking that it is still valid, so an access violation will occur when continuing to operate on this resource.

2. Deep copy

If a class involves resource management, its copy constructor, assignment operator overloading, and destructor must be shown explicitly. Deep copy can be used to solve the problem of shallow copy, that is, each object has an independent resource and is not shared with other objects.

1.Construction

1) No-parameter construction

Purpose: Construct an empty string class object, that is, an empty string

string s1; //无参初始化 

Implementation idea: Using parameterless construction is to pass in an empty string. In the construction list, if a nullptr is passed to str, when we use c_str() // to return the str string, the null pointer will be accessed. ,cout cannot be printed.

string()
    :_str(new char[1])   // 这里 new char 也是一个 加[]是和析构delete[]匹配
    ,_size(0)
    ,_capacity(0)
{
    _str[0] = '\0';    //字符串里只有一个\0
}
    

2) Parametric structure

string s2("hello world");
string(const char * str)
     //如果这里直接使用初始化列表new出来,就需要不停的扩容
    //:_str(str)    //如果这里直接用const str给了str 后面要对str进行修改 则不能修改
    //,
    _size(strlen(str)) //初始化顺序得按声明顺序来,为了避免这种,只初始化一个
    //,_capacity(strlen(str)+1)
{
    _capacity = _size;
    _str = new char[_capacity+1]; //new出char类型的capacity+1个大小的字节  +1是给\0
    strcpy(str,str); //按字节拷贝过来
}

private:
    char * str;
    size_t _size;
    size_t _capacity;


void test()
{
    string s1("hello world");
}

2.Copy construction

Copy construction, that is, the new object must have the same size and capacity as the old object. You can assign values ​​directly in the construction list and use strcpy to copy the string.

string(const string&s)
    :_size(s._size)
    ,_capacity(s._capacity)
{
    _str = new char[s._capacity+1];  //_str 是一个字符数组 new capacity个空间
    strcpy(_str,s._str);
}

3. Assignment operator overloading

It is written separately here to compare with the copy structure.

The parameter type uses a reference, and the return value also uses a reference to support continuous assignment. At the same time, check whether you have assigned a value to yourself and return *this. There is a problem here: the capacity of the assigned object and the assigned object may be different, and may be greater than, less than, or equal to, and there may be situations where space needs to be opened again. The compiler's processing method is: first open a temporary space that is the same as the copied object, then copy the string in, then destroy the original space of the assigned object, and assign the str copied by the temporary object to the assigned object. The reason for opening a temporary space here is that it is necessary to create a section of memory and copy the contents of the incoming object. In order to prevent the same section of memory from being released repeatedly during destruction, causing the program to crash.

string& operator=(const string&s)
{
    //防止自己赋值给自己
    if(*this!= &s)
    {
        //先开空间,成功了再拷贝
        char * tmp = new char[s._capacity+1];
        strcpy(tmp,s._str);
    
        //释放掉原来的空间
        delete[] _str;
        //再拷贝给_str;
        _str = tmp;
        _size = s._size;
        _capacity = s._capacity;
    }
    
    return * this;
}

3. Destruction

Destruction mainly completes the cleanup of resources. Note that _str here should point to a Nullptr.

~string()
		{
			delete[] _str;
			_str = nullptr;
			_size = _capacity = 0;
		}

4. Operator overloading

1)operator[  ]

Function: Return the character at pos position

const size_t & operator[](size_t pos) const   //传入的this不能修改
{
    return _str[pos];
}


char & operator[](size_t pos)
{
    assert(pos<_size);
    return _str[pos];
}

2)operator>

Function: Compare the size of two strings. The comparison here is the ascii code. Use the strcmp function.

bool operator>(string&s)const
{
    return strcmp(_str,s._str)  >0 ;
}

3)operator==

bool operator==(string& s) const
{
    return strcmp(str,s._str) == 0;
}

3)operator>=

bool operator>=(string& s) const
{
    return *this>s || *this ==s;
}

4)operator<

bool operator<(const string* s) const
{

    return !(this>=s);
}

5)operator<=

bool operator<=(const string&s) const
{
    return *this < s || *this == s;
}

6)operator!=

bool operator!=(const string &s) const
{
    return !(*this ==s);
}

5. Some interface implementations

1)resize

Function: 1. Change the valid characters in str to n, and fill the extra space with character c (open space + initialization)

void resize(size_t n,char ch= '\0')
{
 if(n<=_size)
    {
        _str[n] = '\0';
        _size = n;
    }
  else
    {
        if(n> _capacity)
        {
           reserve(n);
        }

        size_t i = _size;
        while(i<n)
        {
            _str[i] = ch;
            ++i;
        }
        _size = n;
        _str[_size] = '\0';
    
       }
}

2)reverse

Function: Reserve space for a string, and use \0 to occupy the new space. First create a temporary space with new, copy the string from the original space into it, then release the original space, and assign the new space to _str. If the space is smaller than the original space, it will not be reduced.

void reserve(size_t n,char ch='\0')
{
    char * tmp = new char[n+1];
    strcpy(tmp,_str);
    delete[] str;
    _srt = tmp;
    
    _capacity = n;
}

3)begin+end

Function: Use iterator, begin to get the first character, end to get the next position of the last character

char* begin()
{
    return _str;
}

char* end()
{
    return _str+_size;
}

4)pushback

Function: Add a character after the string. To add a character, you need to determine whether the capacity is enough. If not, expand the capacity by 2 times, and then place the character at the _size position.

void pushback(char ch)
{
    if(_size+1 >_capacity)
    {
        reserve(2*_capacity);
    }
    
    _str[size] = ch;
    ++size;

    _str[_size] = '\0'; //注意这里有\0
}

5)append

Function: add a string after the string

void append(const char * str)
{
    size len = strlen(str);
    if(_size+len>_capacity)
    {
        reverse(2*capacity);
    }

   strcpy(_str+_size,str);

    _size+= len;
}

6)operator+=

1. Add a character after the original string

2. Add a string after the original string

string& operator+=(char ch)
{
    push_back(ch);
    retrun *this;
}

string& operator+=(const char * str)
{
    append(str);
    return *this;
}

7)insert

1. Function: Add a character at any position in the string

2. Function: Add a string at any position of the string

string& insert(size_t pos,const char ch)
{
    assert(pos<_size);
    //插入要检查容量
    int len = strlen(str);
    if(1+_size >_capacity)
        reverse(2*_capacity);
    //开始插入 先要挪动数据 插入一个字符 就挪动一个位置
    //现在要插入len个字符,就要挪动len个位置
    size_t _end = _size;
    while(pos < end)
    {
        _str[end+1] = _str[end]
        --end;
    }
    //放上数据
      _str[pos] = ch;
      ++size;
   
    return *this;
}
string& insert(size_t pos, const char * str)
{
    assert(pos<_size);
    int len = strlen(str);
    if(_size+len >_capacity)
    {
        reverse(2*_capacity);
    }
    
    size_t end = _size;
    //挪动数据
    while(end>pos)
    {
        _str[end+len] = _str[end];
        --end;
    }

    strnpy(_str+pos,_str,len);
    return * this;
}

8)swap

Function: Exchange strings in two string classes, and size and capacity also participate in the exchange.

void swap(string &s)
{
    std::swap(_str,s._str);
    std::swap(_capacity,s._capacity);
    std::swap(_size,s._size);
}

9)c_str

Return the string in the string class object, just return it directly

char& c_str(string& s)
{
    return s._str;
}

 

10)find

1. Function: Find the character c starting from the npos position and return the position of the character in the string.

2. Function: Search the string starting from the npos position and return the position of the character in the string.

size_t find(char ch,size_t pos = 0)
{
    assert(pos<_size);
    for(int i =0; i<_size;++i)
    {
        if(_str[i] == ch)
            return i;
    }

    return npos;
}
size_t find(char * str,pos = 0)
{
    assert(pos<_size);
    
    //strstr(const char* str1, const char*str2) 在str1中寻找是否存在str2,如果存在返回str2的地址,不存在返回null
    char * p = strstr(_str+pos,str);
    if( p == nullptr)
        return npos;
    else
        return p- _ str; 
}

11)clear

Function function: Set all values ​​in _str to blank, the valid character is 0, and the capacity remains unchanged

void clear()
{
    _str[0] = '\0';
    _size = 0;
}

12)erase

Function: Delete len characters at pos position. If len>strlen(_str), delete as many characters as there are at pos position.

//比如现在有一段字符串 1234567890  10个字符 删除pos = 5位置的两个字符
或者删除pos位置的10个字符 或者删除npos个字符(全删除)
// pos = 5 ;len = 2  1234890 890三个数字挪动到pos = 5的位置 
// pos = 5 ; len = 10 pos = 5的位置开始删除 _str[pos] = '\0'; 
//这两种都只改变_size,不用改变_capacity 
string& eraser(size_t pos,size_t len= npos)
{
    assert(pos<_size);
    
    //注意这里 npos = -1 pos+len 就溢出了 所以需要单独判断
    if(len == npos || pos+len >= _size)
    {
        _str[pos] = '\0';
        _size = pos;
    }

    else
    {
        strcpy(_str+pos,_str+pos+len);
        _size -=len;
    }

    return *this;
}

6. Stream insertion and stream extraction

1)operator<<

cout<<string<<endl;

ostream& operator<<(ostream& out, string& s)
{
    //遍历这个字符串打印
    for(auto ch:s)
    {
        out<<ch;
    }
        
    return out;
}

2)operator>>

cout>>string

void clear()
{
    _str[_size] = '\0';
    _size = 0;
}

instream& operator>>(istream& in , string& s)
{
    //每次清空
    s.clear();
    //从缓冲区拿到数据
    char ch = in.get();
    size_t i= 0;
    while(ch != ' ' && ch == '\n')
    {
        s+= ch;
        buff[i++] = ch;
        //拿到127个清空数组,然后再加后面的字符串
        if(i == 127)
        {
            buff[127] = '\0';
            s+= buff; 
            i= 0;
        }
        
        ch = in.get();
        
    }
    
    return in;
 }

Summarize

This article mainly imitates some source codes in the stl library. The technology is limited. Please correct me if there are any errors.

Guess you like

Origin blog.csdn.net/jolly0514/article/details/131804318