C++语言基础——string类

目录

1. STL

2. string类

2.1 概述

2.2 常用接口

3. string的模拟实现

1. STL

在介绍 string 之前,先来了解一下 STL 吧
 STL(standard template libaray-标准模板库):是C++标准库的重要组成部分,不仅是一个可复用的组件库,而且是一个包罗数据结构与算法的软件框架。有了它,许多底层的数据结构以及算法都不需要自己重新造轮子,站在前人的肩膀上,健步如飞的快速开发。

2. string类

2.1 概述

 在C语言中,字符串可以定义为以'\0'结尾的字符数组。在C++有了类的概念,为了更加安全有效的使用字符串,有了string字符串类。可以进入这里瞅瞅

2.2 常用接口

常见构造函数
函数名称功能说明
string()构造空的string类对象,即空字符串
string(const char* s)用C-string来构造string类对象
string(size_t n, char c)string类对象中包含n个字符c
string(const string&s)拷贝构造函数
string(const string&s, size_t n)用s中的前n个字符构造新的string类对象
	//string() 构造空的string类对象,即空字符串
	string s1;
	//	string(const char* s) 用C - string来构造string类对象
	string s2("hello string!");
	//	string(size_t n, char c) string类对象中包含n个字符c
	string s3(5, 'b');
	//	string(const string&s) 拷贝构造函数
	string s4(s2);
	//	string(const string&s, size_t n) 用s中的前n个字符构造新的string类对象
	string s5(s4, 5);
容量操作
函数名称功能说明
size_t size() const返回字符串有效字符长度
size_t length() const返回字符串有效字符长度
size_t capacity ( ) const返回空间总大小
bool empty ( ) const检测字符串释放为空串,是返回true,否则返回false
void clear()清空有效字符
void resize ( size_t n, char c )将有效字符的个数该成n个,多出的空间用字符c填充
void resize ( size_t n )将有效字符的个数改成n个,多出的空间用0填充
void reserve ( size_t res_arg=0 )为字符串预留空间
	string s1("hello string!");

	//size_t size() const 返回字符串有效字符长度
	cout << "size_t size() const:" << s1.size() << endl;

	//	size_t length() const 返回字符串有效字符长度
	cout << "size_t length() const:" << s1.length() << endl;

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

	//	bool empty() const 检测字符串释放为空串,是返回true,否则返回false
	cout << "bool empty() const:" << s1.empty() << endl;

	//	void clear() 清空有效字符
	s1.clear();
	cout << "void clear()" << endl;

	s1 = "hello string!";
	//	void resize(size_t n, char c) 将有效字符的个数该成n个,多出的空间用字符c填充
	cout <<"s1已恢复:s1 =="<< s1 << endl;
	s1.resize(5, 'b');
	cout << "void resize(size_t n == 5, char c):" << s1 << endl;

	//	void resize(size_t n) 将有效字符的个数改成n个,多出的空间用0填充
	s1.resize(5);
	cout << "void resize(size_t n == 5):" << s1 << endl;

	//	void reserve(size_t res_arg = 0) 为字符串预留空间
	cout << "当前容量:" << s1.capacity() << endl;
	s1.reserve(16);
	cout << "void reserve(size_t res_arg = 16):" << s1.capacity() << endl;

(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的有效字符小于15个的时候,string的容量是15。容量!=size。且是二倍增加在额外多一些预留空间。

迭代器
函数名称功能说明
begin返回迭代器的开始
end返回迭代器的结尾的位置
rbegin返回迭代器的结尾的前一个位置
rend返回迭代器开始的位置

                                   

	string s1( "hello string!");

	string::iterator sit = s1.begin();//s1最开始的位置
	string::iterator sit2 = s1.end();//s1最后一个位置的后一个位置
	cout << "hello string!" << endl;

	cout << "string::iterator:" << endl;
	while (sit != sit2)//遍历字符串
	{
		cout << *sit << "  ";
		++sit;
	}
	cout << endl;

	string::reverse_iterator sit3 = s1.rbegin();//s1最后一个位置
	string::reverse_iterator sit4 = s1.rend();//s1第一个位置

	cout << "string::reverse_iterator:" << endl;
	while (sit3 != sit4)
	{
		cout << *sit3<< "  ";
		++sit3;//虽然是最后一个位置,还是++操作,底层进行了重载
	}
	cout << endl;

(1)迭代器不是指针,是类模板,表现的像指针
(2)迭代器返回的是对象引用而不是对象的值
(3)指针其实是狭义的迭代器,迭代器是指针的抽象
(4)注意迭代器失效的问题。迭代器只是指向当前的空间,如果空间发生改变,迭代器要重新获取。
       后面凡是提到迭代器都要注意迭代器失效的问题

    string str1("iterator");//创建一个字符串

    string::iterator sit = str1.begin();//这时sit == 'i'

    str1 += "useless!!!";//这时我追加了一串字符串,肯定要扩容的。初始容量只有15字节

    cout << *sit << endl;//出现错误,这便是迭代器失效,sit指向原来的空间呢。
修改操作
函数名称功能说明
void push_back(char c)在字符串后尾插字符c
string& append (const char* s);在字符串后追加一个字符串
string& operator+=(const string&str)在字符串后追加字符串str
string& operator+=(const char* s)在字符串后追加C个数字符串
string& operator+=(char c)在字符串后追加字符c
const char* c_str( )const返回C格式字符串
size_t find (char c, size_t pos = 0)const从字符串pos位置开始往后找字符c,返回该字符在字符串中的位置
size_t rfind(char c, size_t pos = npos)从字符串pos位置开始往前找字符c,返回该字符在字符串中的位置
string substr(size_t pos = 0, size_t n= npos)const在str中从pos位置开始,截取n个字符,然后将其返回
	string str("hello change!");
//void push_back(char c) 在字符串后尾插字符c
	str.push_back('!');
	cout <<"在字符串后尾插字符'!':" <<str << endl;
//string& append(const char* s); 在字符串后追加一个字符串
	string s2("hey");
	str.append(s2);
	cout << "在字符串后追加一个字符串:" << str << endl;
//string& operator+=(const string	str)	在字符串后追加字符串str
	str += s2;
	cout << "在字符串后追加一个字符串(=+):" << str << endl;
//	string& operator+=(const char* s) 在字符串后追加C个数字符串
	str +="string";
	cout << "在字符串后追加C个数字符串:" << str << endl;
//	string& operator+=(char c) 在字符串后追加字符c
	str += 's';
	cout << "在字符串后追加字符c:" << str << endl;
//	const char* c_str()const 返回C格式字符串
	const char* ch = str.c_str();
	cout << "返回C格式字符串:" << ch << endl;
//	size_t find(char c, size_t pos = 0)const	从字符串pos位置开始往后找字符c,返回该字符在	字符串中的位置
	size_t pos = str.find('s', 0);
	cout << "回该's'在str中的位置:" << pos << endl;
//	size_t rfind(char c, size_t pos = npos) 从字符串pos位置开始往前找字符c,返回该字符在	字符串中的位置
	size_t pos2 = str.rfind('s', str.size());
	cout << "回该's'在str中的位置:" << pos2 << endl;
//	string substr(size_t pos = 0, size_t n	= npos)const 在str中从pos位置开始,截取n个字符,然后将其返回
	string sub = str.substr(0, 5);
	cout << "在str中从0位置开始,截取5个字符" << sub << endl;

3. string的模拟实现

要想对接口有熟练的运用,模拟实现它是最好的理解方式了。

#pragma once
#pragma once
#include<iostream>
#include<assert.h>
using namespace std;
class newString
{
private://放前面,先认识其私有成员
	char* str_;                //指针
	size_t size_;              //有效字符串长度
	size_t capacity_;          //实际申请的空间大小
	static const size_t npos;  //静态成员。后面重载的时候会用到
public:
	typedef char* iterator;    
	typedef const char* const_iterator;
	//全缺省构造函数
	newString(const char* str = "")//显示定义构造函数
	{
		//不能是空指针
		if (nullptr == str)
		{
			assert(false);
			return;
		}
		size_ = strlen(str);
		capacity_ = size_;
		str_ = new char[size_ + 1];
		strcpy(str_, str);
	}

	//析构函数
	~newString()
	{
		if (str_)
		{
			size_ = 0;
			capacity_ = 0;
			delete[] str_;
			str_ = nullptr;
		}
	}
	//交换函数
	void Swap(newString& str)
	{
		swap(str_, str.str_);
		swap(size_, str.size_);
		swap(capacity_, str.capacity_);
	}
	//拷贝构造
	newString(const newString& str)//引用
		:str_(nullptr),
		size_(0),
		capacity_(0)
	{		//创建临时对象
		newString tmp(str.str_);//创建临时对象是因为不能直接交换指针
		Swap(tmp);        //直接交换指针,被拷贝的对象的内容就变了
	}

	//重载运算符 =     &引用的目的:连续赋值
	newString& operator=(newString str)     //这里有一个临时对象
	{
		Swap(str);
	}
        //这是改变容量的大小capacity_。
	void Reserve(size_t newcapacity)
	{
		if (newcapacity > capacity_)
		{
			char* tmp = new char[newcapacity + 1];
			strcpy(tmp, str_);
			delete[] str_;    //释放原来的空间
			str_ = tmp;
			capacity_ = newcapacity;
		}
	}
	//添加字符
	void PushBack(char c)
	{
		//检查空间是否足够
		if (size_ == capacity_)
		{        //因为string类开始的容量是15
			size_t newcapacity = (size_ == 0 ? 15 : capacity_ * 2);
			Reserve(newcapacity);
		}
		str_[size_++] = c;
		str_[size_] = '\0';
	}

	//插入字符串
	void Append(const char* str)
	{
		size_t leng = strlen(str);
		if (size_ + leng >= capacity_)
		{
			size_t newcapacity = (size_ + leng <= 15 ? 15 : size_ + leng);
			Reserve(newcapacity);
		}
		strcpy(str_ + leng, str);
		size_ += leng;
	}
	// 在pos位置上插入字符c/字符串str,并返回该字符的位置
	newString& Insert(size_t pos, char c)
	{
		assert(pos <= size_);
		if (size_ == capacity_)
		{
			size_t newcapacity = (size_ == 0 ? 15 : capacity_ * 2);
			Reserve(newcapacity);
		}
		size_t end = size_;
		while (pos < end)
		{
			str_[end] = str_[end - 1];
			--end;
		}
		str_[pos] = c;
		++size_;
		return *this;
	}
	newString& Insert(size_t pos, const char* str)
	{
		assert(pos <= size_);
		size_t len = strlen(str);
		if (size_ + len >= capacity_)
		{
			size_t newcapacity = (size_ + len <= 15 ? 15 : size_ + len);
			Reserve(newcapacity);
		}
		size_t end = size_ + len;
		while (pos + len - 1 < end)
		{
			str_[end] = str_[end - len];
			--end;
		}
		for (size_t i = 0; i < len; ++i)
		{
			str_[pos] = str[i];
		}
		size_ += len;
		return *this;
	}

	//尾删
	void PopBack()
	{
		if (size_ > 0)
		{
			--size_;
		}
	}

	//删除函数
	void Erase(size_t pos, size_t len)
	{
		assert(pos < size_);
		if (pos + len >= size_)
		{
			size_ = pos;
			str_[pos] = '\0';//pos后面的字符串
		}
		else
		{
			for (size_t i = pos + len; i <= size_; i++)
			{
				str_[pos++] = str_[i];
			}
			size_ = pos - 1;
		}
	}

	// 返回c在newString中第一次出现的位置
	size_t Find(char c, size_t pos = 0) const
	{
		while (pos < size_)
		{
			if (str_[pos] == c)
			{
				return pos;
			}
			++pos;
		}
		return npos;
	}
	// 返回子串s在newString中第一次出现的位置
	// 判断字串
	char* SubStr( char* str)
	{
		char* dst = str_;
		char* src = str;
		while (*dst)
		{
			if (*dst == *src)
			{
				char* mathdst = dst + 1;
				char* mathsrc = src + 1;

				while (*mathdst && * mathsrc)
				{
					if (*mathdst != *mathsrc)
					{
						return 0;
					}
					++mathdst;
					++mathsrc;
				}
				if (mathsrc == '\0')
				{
					return dst;
				}
			}

			++dst;
		}
		return 0;
	}
	size_t Find(const char* str, size_t pos = 0) const
	{
		char* res = SubStr(str);
	}
	// 截取newString从pos位置开始的n个字符
	newString SubStr(size_t pos, size_t n);

	void Clear()
	{
		size_ = 0;
		str_[size_] = '\0';
	}
	//改变size
		// n <= size_ ;  修改size_ = n, str[n] = '\n'
		//	size_ < n <= capacity_; size_ = n ; str[n] = '\n'    原来未用的空间按用字符填补
		//	n > capacity_ 进行扩容
	void Resize(size_t newsize)
	{
		if (newsize > capacity_)
		{
			Reserve(newsize);
		}
		if (newsize > size_)
		{
			memset(str_ + size_, '\0', newsize - size_);
		}
		size_ = newsize;
		str_[size_] = '\0';
	}
	//字符串长度
	size_t Size() const
	{
		return size_;
	}

	//迭代器
	const_iterator begin() const
	{
		return str_;
	}
	const_iterator end() const
	{
		return str_ + size_;
	}


	//各类重载
	char& operator[](size_t pos)
	{
		assert(pos < size_);
		return str_[pos];
	}
	const char& operator[](size_t pos) const
	{
		assert(pos < size_);
		return str_[pos];
	}
	newString& operator+=(const char* str)
	{

		//size_t leng = strlen(str);
		//if (this->size_ + leng > capacity_)
		//{
		//	Reserve(this->size_ + leng);
		//}
		//strcpy(this->str_+ size_, str);
		Append(str);
		return *this;
	}
	newString& operator+=(const newString& str)
	{
		Append(str.str_);
		return *this;
	}

	bool operator<(const newString& str)
	{
		if (strcmp(str_, str.str_) + 1)
		{
			return false;
		}
		return true;
	}
	bool operator<=(const newString& str)
	{
		return !(str_ > str.str_);
	}
	bool operator>(const newString& str)
	{
		if (strcmp(str_,str.str_))
		{
			return true;
		}
		return false;
	}
	bool operator>=(const newString& str)
	{
		return !(str_ < str.str_);
	}
	bool operator==(const newString& str)
	{
		return !((str_ > str.str_) || (str_ < str.str_));
	}
	bool operator!=(const newString& str)
	{
		return !(str_ == str.str_);
	}

};
const size_t newString::npos = -1;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值