【C++】STL—容器—string类介绍

一、为什么要学习string类

1、C语言中,字符串是以’\0’结尾的一些字符的集合,为了操作方便,C标准库中提供了一些str系列的库函数,但是这些库函数与字符串是分离开的,不太符合OOP(面向对象编程)的思想,而且底层空间需要用户自己管理,稍不留神可能还会越界访问。
2、在OJ中,有关字符串的题目基本以string类的形式出现,而且在常规工作中,为了简单、方便、快捷,基本 都使用string类,很少有人去使用C库中的字符串操作函数。

二、标准库中的string类

2.1 string类

1、string是表示字符串的字符串类
2、该类的接口与常规容器的接口基本相同,再添加了一些专门用来操作string的常规操作。
3、string在底层实际是:basic_string模板类的别名,typedef basic_string<char, char_traits, allocator> string;
4、不能操作多字节或者变长字符的序列。
在使用string类时,必须包含#include头文件以及using namespace std;

2.2 string类的常用接口说明(常用)

1、string类对象的常见构造

void TestString1()
{
    
    
	string s1;         // 构造空的string类对象s1 
	string s2("hello world");  // 用C格式字符串构造string类对象s2 
	string s3(s2);     // 拷贝构造s3
	string s4(10, 'a');   //构造10个字符a
}

2、string类对象的容量操作

void TestString2()
{
    
    
	string s1("hello");
	cout << s1.size() << endl;//返回字符串有效字符长度

	cout << s1.length() << endl;//返回字符串有效字符长度,同size

	cout << s1.capacity() << endl;//返回空间总大小


	if (s1.empty())//检测字符串释放为空串,是返回true,否则返回false

	{
    
    
		cout << "空字符串" << endl;
	}
	else
	{
    
    
		cout << "非空字符串" << endl;
	}

	s1.clear();//清空有效字符

	if (s1.empty())
	{
    
    
		cout << "空字符串" << endl;
	}
	else
	{
    
    
		cout << "非空字符串" << endl;
	}
}

    //将s1中有效字符增加到10个,多出的5个字符使用'!'来进行填充
	s1.resize(10,'!');

	//将s1中有效字符增加到32个,多出的22个字符使用'$'来进行填充
	//在增加字符期间会进行扩容
	s1.resize(32, '$');

	//当resize将有效元素个数减少时,只修改有效元素个数,而不会缩小底层空间的大小
	s1.resize(28);

    //将容量增大
	s1.reserve(10);
	s1.reserve(21);   
	s1.reserve(28);
	s1.reserve(40);

	//将容量缩小
	s1.reserve(32);
	s1.reserve(20);
	s1.reserve(13);

3、string类对象的访问及遍历操作

void Teststring3() 
{
    
        
    string s("hello Bit");    
    // 3种遍历方式:    
    // 需要注意的以下三种方式除了遍历string对象,还可以遍历是修改string中的字符,    
    // 另外以下三种方式对于string而言,第一种使用最多    
    // 1. for+operator[]    
    for(size_t i = 0; i < s.size(); ++i)        
        cout<<s[i]<<endl;        
    // 2.迭代器    
    string::iterator it = s.begin();    
    while(it != s.end())    
    {
    
            
        cout<<*it<<endl;        
        ++it;    
    }       
    string::reverse_iterator rit = s.rbegin();    
    while(rit != s.rend())        
        cout<<*rit<<endl;        
    // 3.范围for
    for(auto ch : s)
        cout<<ch<<endl; 
}

4、string类对象的修改操作

void TestString6()
{
    
    
	string s1("hello");
	
	s1.push_back(',');//在s1后面加,
	s1 += "world";//在s1后面追加"world"
	cout << s1 << endl;

	string s2("!!!");
	s1 += s2;
	s1 += '$';
	cout << s1 << endl;

	s1.append(1, '%');//在s1后面追加1个%
	cout << s1 << endl;

	s1.append(s1, 2, 3);//追加s1中第二个字符的后3个字符
	cout << s1 << endl;
}

三、string类的模拟实现

namespace bit 
{
    
        
    class string    
    {
    
        
    public:        
        typedef char* iterator;    
    public:        
        string(const char* str = "")        
        {
    
                
            _size = strlen(str);            
            _capacity = _size;           
            _str = new char[_capacity+1];            
        strcpy(_str, str);        
        }
 
        string(const string& s)            
        : _str(nullptr)            
        , _size(0)            
        , _capacity(0)        
        {
    
                
            string tmp(s);             
            this->Swap(tmp);        
        }
 
        string& operator=(string s)       
         {
    
    
             this->Swap(s)
             return *this;        
         }
 
         ~string()        
         {
    
                
             if (_str)            
             {
    
                    
                 delete[] _str;                
                 _str = nullptr;            
             }        
         }
 
        /        // iterator        
        iterator begin() {
    
    return _str;}        
        iterator end(){
    
    return _str + _size;}
 
        /        // modify        
        void push_back(char c)        
        {
    
                
            if (_size == _capacity)                            
                Reserve(_capacity*2);                          
            _str[_size++] = c;            
            _str[_size] = '\0';        
        }
 
        string& operator+=(char c)        
        {
    
                
            PushBack(c);           
            return *this;       
        }
        void clear()        
        {
    
                
            _size = 0;            
            _str[_size] = '\0';        
        }
 
        void swap(string& s)        
        {
    
                
            swap(_str, s._str);            
            swap(_size, s._size);            
            swap(_capacity, s._capacity);       
        }
 
        const char* c_str()const
        {
    
    
             return _str;        
        }
        size_t size()const        
        size_t capacity()const       
        bool empty()const                    
        void resize(size_t newSize, char c = '\0')        
        {
    
                
            if (newSize > _size)            
            {
    
                    
        // 如果newSize大于底层空间大小,则需要重新开辟空间                  
                if (newSize > _capacity)                
                {
    
                        
                    Reserve(newSize);                
                }
 
                memset(_str + _size, c, newSize - _size);            
            }
 
            _size = newSize;            
            _str[newSize] = '\0';        
        }
 
        void reserve(size_t newCapacity)        
        {
    
                
            // 如果新容量大于旧容量,则开辟空间            
            if (newCapacity > _capacity)            
            {
    
                    
                char* str = new char[newCapacity + 1];                 
                strcpy(str, _str);
 
                // 释放原来旧空间,然后使用新空间                
                delete[] _str;                
                _str = str;                
                _capacity = newCapacity;            
            }        
        }
 
                // 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];
        }
    private:        
        friend ostream& operator<<(ostream& _cout, const bit::string& s);        
        friend istream& operator>>(istream& _cin, bit::string& s);    
    private:        
        char* _str;        
        size_t _capacity;        
        size_t _size;    
    };
} 

猜你喜欢

转载自blog.csdn.net/zhao_leilei/article/details/109435589