当前位置 博文首页 > C/C++菜鸟养成记:【C++自学笔记】STL—string类详解及自主实现s

    C/C++菜鸟养成记:【C++自学笔记】STL—string类详解及自主实现s

    作者:[db:作者] 时间:2021-08-19 15:46

    一、什么是string类?

    1、C语言中的字符串

    C语言中,字符串是以'\0'结尾的一些字符的集合,为了操作方便,C标准库 中提供了一些str系列的库函数,但是这些库函数与字符串是分离开的,不太符合OOP的思想,而且底层空间需要用户自己管理,稍不留神可能还会越界访问。

    2、什么是string类?

    string类是表示字符串的字符串类,该类的接口与常规容器的接口基本相同,再添加了一些专门用来操作string的常规操作。

    string在底层实际是:basic_string模板类的别名,typedef basic_string string;

    在使用string类时,必须包含头文件<string>以及using namespace std;

    二、string的常用接口

    1、string的常用构造

    //构建一个空的字符串
    string();
    //用c-string来构造string类对象
    string(const char* s);
    //构造一个包含有n个c字符的对象
    string(size_t n,char c);
    //拷贝构造函数
    string(const string& s);
    //用s中的前n个字符构造一个新对象
    string(const string& s,size_t n);

    示例:

    #include<string>
    using namespace std;
    int main(){
        string s1;
        string s2("Hello World!");
        string s3(10,'a');
        string s4(s2);
        string s5(s3,5);
        return 0;
    }

    ==> s1是空字符串;s2->"Hello World";s3->"aaaaaaaaaa";s4->"Hello World";s5->"aaaaa";

    2、string类对象的容量操作

    //返回字符串的有效字符长度
    size_t size() const;
    //返回字符串的有效字符长度
    size_t length() const;
    //返回空间的总大小
    size_t capacity() const;
    //检测字符串是否为空,为空返回ture,不为空返回false
    bool empty() const;
    //清空有效字符
    void clear();

    其中需要注意的地方:

    1. size()和length()两者的用法完全相同,而函数后面的const是通过把类成员函数声明为const ? 以表明它们不修改类对象;
    2. clear()只是将string中的有效字符清空,并不会改变底层空间的大小;

    还有几个修改有效字符个数的操作:

    //将有效字符的个数改成n个,多出的空间用字符c填充
    void resize(size_t n,char c);
    //将有效字符的个数改成n个,多出的空间用\0填充
    void resize(size_t n);
    //为字符串预留空间
    void reserve(size_t res_arg=0);

    需要注意的地方:

    1. 前两个的用法是一样的,差别只是在有没有第二个参数,如果有就用第二参数填充多出来的部分,如果没有就用\0填充多出来的部分;
    2. reserve(size_t res_arg=0):为string预留空间,不改变有效元素个数,当reserve的参数小于 string的底层空间总大小时,reserver不会改变容量大小

    对于reserve()进行如下测试:

    void Test() {
    	string s("Hello world");
    	cout << s.size() << endl;
    	cout << s.capacity() << endl;
    	s.reserve(500);
    	cout << s.size() << endl;
    	cout << s.capacity() << endl;
    	s.reserve(50);
    	cout << s.size() << endl;
    	cout << s.capacity() << endl;
    }

    3、string的类对象访问操作

    //返回pos位置的字符,const string类对象调用
    char& operator[](size_t pos);
    //返回pos位置的字符,非const string类对象调用
    const char& operator[](size_t pos) const;

    类似于对数组的下标访问;

    4、string类对象的修改操作

    1、增加

    //在字符串后尾插字符串c
    void push_back(char c);
    //在字符串后追加一个字符串
    string& append(const char* c);
    //在字符串后追加字符串str
    string& operator+=(const string& str);
    //在字符串后追加字符C
    string& operator+=(char c);

    2、返回C格式字符串

    const char* c_str()const;

    3、寻找/匹配/删除

    //从字符串pos位置开始往后匹配字符C,返回C的位置
    size_t find(char c,size_t pos = 0)const;
    //从字符串pos位置开始往前匹配字符C,返回C的位置
    size_t rfind(char c,size_t pos = npos);
    //在str中从pos位置开始,截取n个字符,然后将其返回
    string substr(size_t pos = 0,size_t n = nops)const;
    //在str中从pos位置开始,删除n个字符
    string& erase ( size_t pos = 0, size_t n = npos );
    

    ==》小练习:去除url中的域名

    void UrlStrTest() {
    	string url("http://www.baidu.com/hahah/heheh/121231");
    	cout << url << endl;
    	size_t start = url.find("://");
    	if (start == string::npos) {
    		cout << "invalid url" << endl;
    		return;
    	}
    	start += 3;
    	size_t finish = url.find('/',start);
    	string address = url.substr(start, finish - start);
    	cout << "address" << address << endl;
    }
    

    三、string类的模拟实现

    要自主实现string类其实不是很难,但是在完成拷贝构造函数的时候需要注意,之前我们有总结过,默认的拷贝构造函数都是进行浅拷贝,而在string类中实现拷贝构造则需要进行深拷贝,这是特别需要注意的一点!!!那么什么是深拷贝?什么是浅拷贝??

    1、深拷贝和浅拷贝

    浅拷贝:也称位拷贝,编译器只是将对象中的值拷贝过来。如果对象中管理资源,最后就会导致多个对象共享同一份资源,当一个对象销毁时这份资源就会被释放掉,而此时另一些对象并不知道,还会对原来的内存空间进行资源操作,会发生访问违规;

    深拷贝:给每个对象都独立分配资源,保证多个对象之间不会因为共享资源而造成多次释放,造成程序的崩溃;

    所以在完成string类的自主实现时,有以下做法:

    class string {
    public:
    	string(const char* str = ""){
    		if (str == nullptr) {
    			assert(false);
    			return;
    		}
    		_str = new char[strlen(str) + 1];
    		strcpy(_str, str);
    	}
    	string(const string& s)
    		:_str(new char[strlen(s._str) + 1])
    	{
    		strcpy(_str, s._str);
    	}
    	~string() {
    		if (_str) {
    			delete[] _str;
    			_str = nullptr;
    		}
    	}
    private:
    	char* _str;
    };

    当然除了拷贝构造函数,还有赋值运算符的重载!!!!

    2、自主实现string类

    namespace My {  
    	class String {
    	public:
    		//构造
    		String(const char* str = "") {
    			if (str == nullptr) {
    				assert(false);
    				return;
    			}
    			_size = strlen(str);
    			_capacity = _size;
    			_str = new char[_capacity + 1];
    			strcpy(_str,str);
    		}
    		String(const String& s)
    			: _str(new char[s._capacity + 1])
    			, _size(s._size)
    			, _capacity(s._capacity)
    		{	
    			strcpy(_str, s._str);
    		}
    		String& operator=(const String& s) {
    			if (this != &s) {
    				char* pStr = new char[s._capacity + 1];
    				strcpy(pStr, s._str);
    
    				delete[] _str;
    				_str = pStr;
    				_size = s._size;
    				_capacity = s._capacity;
    			}
    			return *this;
    		}
    		~String() {
    			if (_str) {
    				delete[] _str;
    				_str = nullptr;
    			}
    		}
    		//Iterators:begin、end
    		typedef char* Interators;
    		Interators Begin() {
    			return _str;
    		}
    		Interators End() {
    			return _str + _size;
    		}
    		//Capacity:size,length,
    		void Reserve(size_t res_arg = 0) {
    			if (_capacity >= res_arg)
    				return;
    			else
    				_capacity = res_arg;
    		}
    		//Modify:operator+=、PushBack、Append、
    		void PushBack(char c) {
    			if (_size == _capacity)
    				Reserve(_capacity * 2);
    			_str[_size++] = c;
    			_str[_size] = '/0';
    		}
    		void Append(size_t n,char c) {
    			for (size_t i = 0; i < n; ++i) {
    				PushBack(c);
    			}
    		}
    		void Append(const char* str) {
    
    		}
    		String& operator+=(char c) {
    			PushBack(c);
    			return *this;
    		}
    		String& operator+=(const char* str) {
    
    		}
    
    	private:
    		char* _str;
    		size_t _capacity;
    		size_t _size;
    	};
    }

    还没写完,等有时间会完善的~

    cs
    下一篇:没有了