STL之string类的介绍

1.C语言中的string

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

2.string类的常用接口说明

string类的文档介绍

2.1 string类的常用构造

(constructor)函数名称功能说明
string() (重点)构造空的string类对象,即空字符串
string(const char* s) (重点)用C-string来构造string类对象
string(size_t n, char c)string类对象中包含n个字符c
string(const string&s) (重点)拷贝构造函数
void teststring()
{
    string s1;
    string s2("hello world");
    string s3(s2);
    string s4(5, c);
}

2.2 string类对象的容量操作函数

函数名称功能说明
size返回字符串有效字符长度
length返回字符串有效字符长度
capacity返回空间总大小
empty检测字符串释放为空串,是返回true,否则返回false
clear清空有效字符
reserve为字符串预留空间**
resize将有效字符的个数该成n个,多出的空间用字符c填充

string类容量相关方法使用代码演示

注意⚠️:

1. size()与length()方法底层实现原理完全相同,引入size()的原因是为了与其他容器的接口保持一
致,一般情况下基本都是用size()。
2. clear()只是将string中有效字符清空,不改变底层空间大小。
3. resize(size_t n) 与 resize(size_t n, char c)都是将字符串中有效字符个数改变到n个,不同的是当字符个数增多时:resize(n)用0来填充多出的元素空间,resize(size_t n, char c)用字符c来填充多出的元素空间。注意:resize在改变元素个数时,如果是将元素个数增多,可能会改变底层容量的大
小,如果是将元素个数减少,底层空间总大小不变。
4. reserve(size_t res_arg=0):为string预留空间,不改变有效元素个数,当reserve的参数小于
string的底层空间总大小时,reserver不会改变容量大小。

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

函数名称功能说明
operator[] (重点) 返回pos位置的字符,const string类对象调用
begin+ endbegin获取一个字符的迭代器 + end获取最后一个字符下一个位置的迭代器
rbegin+rendrbegin获取最后一个字符的迭代器 + rend获取第一个字符的迭代器
范围forC++11支持更简洁的范围for的新遍历方式

2.4 string类对象的修改操作

函数名称功能说明
push_back在字符串后尾插字符c
append在字符串后追加一个字符串
operator+=在字符串后追加字符串str
c_str返回C格式字符串
find+npos从字符串pos位置开始往后找字符c,返回该字符在字符串中的位置
rfind从字符串pos位置开始往前找字符c,返回该字符在字符串中的位置
substr在str中从pos位置开始,截取n个字符,然后将其返回

注意⚠️:
1. 在string尾部追加字符时,s.push_back(c) / s.append(1, c) / s += 'c'三种的实现方式差不多,一般情况下string类的+=操作用的比较多,+=操作不仅可以连接单个字符,还可以连接字符串。
2. 对string操作时,如果能够大概预估到放多少字符,可以先通过reserve把空间预留好。

3.string类的模拟实现

#include"string.h"
#include <intrin.h>

namespace dt
{
    string::iterator string::begin()
	{
		return _str;
	}

    string::iterator string::end()
	{
		return _str + _size;
	}

    string::string (const char* str)  //构造函数
        :_size (strlen(str))
    {
        _str = new char[_size + 1];
        _capacity = _size;
        strcpy(_str, str);
    }

    string::string (const string& s)  //拷贝构造
    {
        _str = new char[s._capacity + 1];
        strcpy (_str, s._str);
        _size = s._size;
        _capacity = s._capacity;
    }

    string::~string()                  //析构函数
    {
        delete[]_str;
        _str = nullptr;
        _size = _capacity = 0;
    }

    const char* string::c_str() const
    {
        return _str;
    }

    size_t string::size() const
    {
        return _size;
    }

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

    string& string::operator=(const string& s)
    {
        if (this != &s)
        {
            char* tmp = new char[s._capacity + 1];
            strcpy (tmp, s._str);
            delete[] _str;
            _str = tmp;
            _size = s._size;
            _capacity = s._capacity;
        }

        return *this;
    }

    void string::insert (size_t pos, char ch)        //插入单个字符
    {
        assert (pos <= _size);
        
        if (_size == _capacity)
        {
            size_t newcapacity = _capacity == 0 ? 4 : _capacity * 2;
            reserve (newcapacity);
        }

        size_t end = _size + 1;
        while (end > pos)
        {
            _str[end] = _str[end - 1];
            end--;
        }

        _str[pos] = ch;
        _size++;
    }

    void 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 - 1)
        {
            _str[end] = _str[end - len];
            end--;
        }

        memcpy(_str + pos, str, len);
        _size += len;
    }

    void string::push_back(char ch)
    {
        insert(_size, ch);
    }
 
    void string::append(const char* str)
    {
        insert(_size, str);
    }

    string& string::operator+=(char ch)
	{
		push_back(ch);

		return *this;
	}

    void string::erase (size_t pos, size_t len)
    {
        assert (pos < _size);

        if (len >= _size - pos)
        {
            _str[pos] = '\0';
            _size = pos;
        }
        else{
            strcpy(_str + pos, _str + pos + len);
            _size -= len;
        }
    }

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

		return npos;
	}

	size_t string::find(const char* sub, size_t pos)
	{
		char* p = strstr(_str + pos, sub);
		return  p - _str;
	}

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

	string string::substr(size_t pos, size_t len)
	{
		// len大于后面剩余字符,有多少取多少
		if (len > _size - pos)
		{
			string sub(_str + pos);
			return sub;
		}
		else
		{
			string sub;
			sub.reserve(len);
			for (size_t i = 0; i < len; i++)
			{
				sub += _str[pos + i];
			}

			return sub;
		}
	}

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

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

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

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

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

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

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

	istream& operator>> (istream& is, string& str)
	{
		str.clear();
		char ch = is.get();
		while (ch != ' ' && ch != '\n')
		{
			str += ch;
			ch = is.get();
		}

		return is;
	}

	ostream& operator<< (ostream& os, const string& str)
	{
		for (size_t i = 0; i < str.size(); i++)
		{
			os << str[i];
		}

		return os;
	}
}


 


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值