首页 > 编程语言 >C++中String的语法及常用接口用法

C++中String的语法及常用接口用法

时间:2023-08-18 23:01:51浏览次数:40  
标签:capacity String 接口 char C++ str ._ string size

在C语言中,string是一个标准库类(class),用于处理字符串,它提供了一种更高级、更便捷的字符串操作方式,string 类提供了一系列成员函数和重载运算符,以便于对字符串进行操作和处理。

C++中String的语法及常用接口用法_ci

一、string类

在学习 string 前,我们不妨先来了解一下 string 类到底是什么,有什么用呢?我们先来了解一下基本的概念吧

C++中String的语法及常用接口用法_string类_02

C++标准库都是英语解释。我们也应该试着去适应,不懂的可以查阅。当然,在这里我就直接给出翻译,主要是以下内容:

字符串是表示字符序列的类;

  • 标准的字符串类提供了对此类对象的支持,其接口类似于标准字符容器的接口,但添加了专门用于操作单字节字符字符串的设计特性。
  • string类是使用char(即作为它的字符类型,使用它的默认char_traits和分配器类型(关于模板的更多信息,请参阅basic_string)。
  • string类是basic_string模板类的一个实例,它使用char来实例化basic_string模板类,并用char_traits和allocator作为basic_string的默认参数(根于更多的模板信息请参考basic_string)。
  • 注意,这个类独立于所使用的编码来处理字节:如果用来处理多字节或变长字符(如UTF-8)的序列,这个类的所有成员(如长度或大小)以及它的迭代器,将仍然按照字节(而不是实际编码的字符)来操作。

二、string的常用见用法

2.1 string对象的构造

C++中String的语法及常用接口用法_ci_03

2.1.1 string对象的构造的使用方法

最为常用的无非就是我们用串string来构造一个对象,也就是存储一个字符,常用的方法有如下几点:

  • string()——构造空的 string 类对象,即空字符串;
  • string(const char* s)——用 char* 来构造 string 类对象;
  • string(size_t n, char c)——string类对象中包含n个字符c
  • string(const string&s)——拷贝构造函数

下面是使用方法所对应的实例,帮助更好的理解其用法。

C++中String的语法及常用接口用法_赋值_04

三、string常用结构的底层实现

3.1 初建结构

我们通过上述的构造,不难发现也不难理解string的底层其实就是一个字符指针,该指针指向一个数组。当然,我们还需要两个变量来维护其有效长度(_size)数组容量(_capacity)

其次,我们自己实现的string类为了区分std命名空间,我们可自己设置一个命名空间。处型的模拟实现如下:

namespace gtm
{
	class string
	{
     public:
        //string()
		//	:_str(new char[1])
		//	, _size(0)
		//	,_capacity(0)
		//{
		//}
		//string(const char* str)
		//	:_str(new char[strlen(str) + 1])  //三次strlen函数,效率低。
		//	,_size(strlen(str))
		//	,_capacity(strlen(str))
		//{
		//	strcpy(_str, str);
		//}
		// 不再使用strlen函数,初始化列表与变量声明顺序固定
		string(const char* str = "") //默认空串。注意:空串是以 \0 结尾
		{
			_size = strlen(str);
			_capacity = _size;
			_str = new char[_size + 1];
			strcpy(_str, str);
		}
        ~string()
		{
			delete[] _str;
			_str = nullptr;
			_size = _capacity = 0;
		}
     private:
		char* _str;
		size_t _size;
		size_t _capacity;
	};

3.2 返回大小和容量

这两个部分,是比较容易实现的两部分。同时也是较为常用的两部分。具体如下:

size_t size() const
		{
			return _size;
		}
		size_t capacity() const
		{
			return _capacity;
		}

3.3 拷贝构造和赋值重载

这两部分较为复杂的两部分。其中均需要深拷贝去实现完成,而浅拷贝是不可以的。注意:拷贝构造使用一个已定义变量去初始化另一个变量,赋值重载是两个已定义变量进行赋值

具体实现如下:

C++中String的语法及常用接口用法_string类_05

//深拷贝
		//string(const string& s)
		//	:_str(new char[s._capacity+1])
		//	,_size(s._size)
		//	,_capacity(s._capacity)
		//{
		//	strcpy(_str, s._str);
		//}
		void swap(string& tmp)
		{
			//调用全局的swap
			::swap(_str, tmp._str);
			::swap(_size, tmp._size);
			::swap(_capacity, tmp._capacity);
		}
		//借助变量tmp
		string(const string& s)
			:_str(nullptr) 
			, _size(0)
			, _capacity(0)
		{
			string tmp(s._str);
			swap(tmp);
		}
		//赋值
		//string& operator=(const string& s)
		//{
		//	if(this == &s)
		//	{
		//		return *this;
		//	}
		//	//先开空间拷贝数据,以防new失败销毁原来的空间
		//	char* tmp = new char[s._capacity + 1];
		//	strcpy(tmp, s._str);
		//	delete[] _str;
		//	_str = tmp;
		//	_size = s._size;
		//	_capacity = s._capacity;
		//	return *this;
		//	//delete[] _str;
		//	//_str = new char[s._capacity + 1];
		//	//strcpy(_str, s._str);
		//	//_size = s._size;
		//	//_capacity = s._capacity;
		//	return *this;
		//}
		//string& operator=(const string& s)
		//{
		//	if(this == &s)
		//	{
		//		return *this;
		//	}
		//	string tmp(s._str);
		//	swap(tmp);
		//  return *this;
		//}
		string& operator=(string s)
		{
			if (this == &s)
			{
				return *this;
			}
			swap(s);
			return *this;
		}

上述的辅助重载我们巧妙地借助了临时变量s。当赋值完成后,出了作用域s会自动调用戏后进行销毁,这里是需要反复理解的。

3.4 扩容(reserve)

我们可简单的理解reserve为扩容(扩容的前提为要求的容量比原来的大),但是我们要记得把字符数组中原有的内容拷贝过来,并且释放之前所动态开辟的空间。 具体实现如下:

void reserve(size_t capacity)
		{
			if (capacity > _capacity)
			{
				char* tmp = new char[capacity + 1];
				strcpy(tmp, _str);
				delete[] _str;
				_str = tmp;
				_capacity = capacity;
			}
		}

3.5 插入(push_back、append、operator+=、insert)

插入的实现,主要的点就是是否要进行扩容。其次,当我们实现push_back和append后,其他的均可复用这两个结构进行实现。具体实现如下:

void push_back(char ch)
		{
			if (_size == _capacity)
			{
				reserve(_capacity == 0 ? 4 : _capacity * 2);
			}
			_str[_size] = ch;
			_size++;
			_str[_size] = '\0';
		}
		void append(const char* str)
		{
			size_t len = strlen(str);
			if (len + _size > _capacity)
			{
				reserve(len + _size >= _capacity * 2 ? len + _size : _capacity * 2);
			}
			strcpy(_str + _size, str);
			_size += len;
		}
		void append(const string& s)
		{
			append(s._str);
		}
		void append(int n, char ch)
		{
			reserve(_size + n);
			for (int i = 0; i < n; i++)
			{
				push_back(ch);
			}
		}
		string& operator+= (char ch)
		{
			push_back(ch);
			return *this;
		}
		string& operator+= (const char* str)
		{
			append(str);
			return *this;
		}
		string& insert(size_t pos, char ch)
		{
			assert(pos <= _size);
			if (_size == _capacity)
			{
				reserve(_capacity == 0 ? 4 : _capacity * 2);
			}
			//注意,当运算数一个是有符号,另一个是无符号时,有符号的运算数会强制类型转换为无符号数。pos等于0的位置插入,end--后为超大数据,会出错。
			//int end = _size;
			//while (end >= (int)pos)
			//{
			//	_str[end + 1] = _str[end];
			//	end--;
			//}
			size_t end = _size+1;
			while (end > pos)
			{
				_str[end] = _str[end - 1];
				end--;
			}
			_str[pos] = ch;
			_size++;
			return *this;
		}
		string& insert(size_t pos, const char* str)
		{
			assert(pos <= _size);
			size_t len = strlen(str);
			if (len + _size > _capacity)
			{
				reserve(len + _size >= _capacity * 2 ? len + _size : _capacity * 2);
			}
			size_t end = _size + len;
			while (end >= pos+len)
			{
				_str[end] = _str[end - len];
				end--;
			}
			for (int i = pos,j=0; j < len;j++, i++)
			{
				_str[i] = str[j];
			}
			_size += len;
			return *this;
		}

string 在C++中算是比较重要的了,也是入门时必须所学的容器。在平常中使用的频率较高,所以我们不仅要掌握其简单的用法,更应该去了解其底层的实现。这有助于我们后续的使用和理解。本篇文章列举出了string中常用的语法和接口底层的底层实现,这些都是我们应该熟练掌握的内容。

标签:capacity,String,接口,char,C++,str,._,string,size
From: https://blog.51cto.com/u_15641375/7142280

相关文章

  • 登陆接口实现返回token
    自定义登陆接口,然后让SpringSecurity对这个接口放行,让用户访问这个接口的时候不用登录也能访问。在接口中我们通过AuthenticationManager的authenticate方法来进行用户认证,所以需要在SecurityConfig中配置把AuthenticationManager注入容器。认证成功的话要生成一个jwt,放入响......
  • Mike and strings 题解
    题目传送门一道字符串题。由于\(n\)非常小,可以暴力枚举字符串。我们可以枚举其中一个字符串\(s_i\),然后让其他的字符串变成\(s_i\),最后记录一下次数,取一个最小值即可。在枚举第二个字符串的时候可以将它再复制一份自己到后面,然后可以用find函数来统计。当然,如果找不到,这......
  • C++项目实战之演讲比赛流程管理系统
    演讲比赛流程管理系统1.演讲比赛程序需求1.1比赛规则学校举行一场演讲比赛,共有12个人参加。比赛共两轮,第一轮为淘汰赛,第二轮为决赛每名选手都有对应的编号,如10001~10012比赛方式:分组比赛,每组6个人第一轮分为两个小组,整体按照选手编号进行抽签后顺序演讲10个......
  • 关于 STM32 在使用 C++ 进行编程时无法进行中断(触发中断就死循环)的问题
    他妈的!!!就因为这破事导致我浪费了两天的时间!!!都是基础不扎实的锅,导致我没能第一时间想到问题的关键好了,平复一下心情,快速的写一篇博客来记录这个叼问题解决方法先把结论放在这里:用extern"C"{}把中断函数包起来//就像这样extern"C"{voidEXTI4_IRQHandler(){HAL_GP......
  • C++11新特性——1.4-1.5 final和override
    1.4final原文:https://subingwen.cn/cpp/final/总结:1.final限制某个类不能被继承,或限制某个虚函数不能被重写2.final修饰虚函数或者类3.final关键字写到虚函数或类后面classBase{public:virtualvoidtest(){cout<<"Baseclass.........
  • c++ 常用的 STL
    c++中常用的STLvector//vector变长数组倍增的思想(倍增:系统为每一个程序分配空间的时候,所需要的时间和空间大小无关,与请求次数相关)尽量减少请求的次数/*返回元素的个数size()判断是否为空empty()清空clear()front()返回第一个数back()返回最后一个数push......
  • [AT_ABC106_C]题解(C++)
    PartIPreface原题目\(\text{(Luogu)}\)原题目\(\text{(AtCoder)}\)PartIISketch给定一个字符串\(s\)以及一个整数\(k\)。该字符串为纯数字串。其中的数字\(x\)会在\(k\)天后变为\(x^{k-1}\)个\(x\)。求出\(10^{15}\)天后,串\(s\)的第\(k\)位是什么......
  • [AT_ABC106_D]题解(C++)
    PartIPreface原题目\(\text{(Luogu)}\)原题目\(\text{(AtCoder)}\)PartIISketch给定正整数\(n,m,q\)。接下来给定\(m\)组\(x_i,y_i\),表示一列列车的起始站和终点站。在接下来给定\(q\)组\(l_i,r_i\)。对于每组询问,回答有多少\(x_i\geql_i\operatorna......
  • [AT_ABC106_B]题解(C++)
    PartIPreface原题目\(\text{(Luogu)}\)原题目\(\text{(AtCoder)}\)PartIISketch给定一个正整数\(N\)。求出\(1\simN\)所有因数个数为\(8\)的数的个数。PartIIIAnalysis先输入\(N\)。遍历\(1\simN\)的每个数,记录每个数的因数个数。若因数个数等于\(8\)......
  • [AT_ABC106_A]题解(C++)
    PartIPreface原题目$\text{(Luogu)}$原题目$\text{(AtCoder)}$PartIISketch给定整数$a,b$,输出$(a-1)\times(b-1)$。$2\leqa,b\leq100$。PartIIIAnalysis运用小学知识,进行平移,把几块地拼接在一起。不难看出长为$a-1$,宽为$b-1$,面积为$(a-1)\tim......