7.【CPP】String类

这篇具有很好参考价值的文章主要介绍了7.【CPP】String类。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一.汉字的编码

我们知道计算机存储英文字母,标点,数字用的是ascall码,128种用一个字节表示绰绰有余。而汉字远远不止128种,因此汉字需要两个字节表示

1.gbk编码中汉字占两个字节。
2.utf-8中,一个汉字占三个字节。

> UTF规定:如果一个符号只占一个字节,那么这个8位字节的第一位就为0。如果为两个字节,那么规定第一个字节的前两位都为1,然后第一个字节的第三位为0,第二个字节的前两位为10,然后如果是三个字节的话,那么第一个字节的前三位为111,第四位为0,剩余的两个字节的前两位都为10。按照这样的算法去思考一个中文字符的UTF-8是怎么表示的:一个中文字符需要两个字节来表示,两个字节一共是16位,那么UTF-8下,两个字节是不够的,因为两个字节下,第一个字节已经占据了三位:110,然后剩余的一个字节占据了两位:10,现在就只剩下8位,与Unicode下的两个字节,16位去表示任意一个字符是相悖的,也就是Unicode下的16位减去UTF-8下的8位=8位,刚好差了一个字节的空间,所以就使用三个字节去表示非ANSI字符:三个字节下,一共是24位,第一个字节头四位是:1110,后两个字节的前两位都是:10,那么24位-8位=16位,刚好两个字节去表示Unicode下的任意一个非ANSI字符

7.【CPP】String类,CPP,算法,c++,数据结构,开发语言

二.string类

参考string官方文档

1.扩容

7.【CPP】String类,CPP,算法,c++,数据结构,开发语言

这里resize和reserve都是在string对象后开指定大小的可用空间,而不是把它的容量设置为指定大小。
resize改变了size大小,而reserve不改变.
resize空间小于size大小时会删除元素,reserve空间小于size时不会改变容量也不删除元素。

2.小试牛刀

2.1把字符串转化为整数

迭代器实现

#include <cctype>
class Solution {
  public:
    int StrToInt(string str) {
        int ans = 0;
        int i=0;
        for (string::reverse_iterator rit = str.rbegin(); rit != str.rend(); ++rit) {
            
            if (isdigit(*rit)) {
                ans=ans+((*rit)-48)*pow(10,i++);
                continue;
            }
            if (*rit == '+')
                break;
            else if (*rit == '-')
                ans *= -1;
            else
                return 0;
        }
        return ans;
    }
};

2.2.Leetcode415.字符串相加

给定两个字符串形式的非负整数 num1 和num2 ,计算它们的和并同样以字符串形式返回。

你不能使用任何內建的用于处理大整数的库(比如 BigInteger), 也不能直接将输入的字符串转换为整数形式。

示例 1:
输入:num1 = “11”, num2 = “123”
输出:“134”

class Solution {
public:
    string addStrings(string num1, string num2) {
        int end1=num1.size()-1,end2=num2.size()-1;
        int carry=0;
        string ans;
        //提前扩一波容
        ans.reserve(num1.size()>num2.size()?num1.size()+1:num2.size()+1);
        while(end1>=0||end2>=0)
        {
            int val1=end1>=0?num1[end1]-'0':0;
            int val2=end2>=0?num2[end2]-'0':0;
            int ret=val1+val2+carry;
            carry=ret/10;
            ans+=ret%10+'0';
            --end1;
            --end2;
        }
        if(carry)
            ans+='1';
        reverse(ans.begin(),ans.end());
        return ans;
    }
};

7.【CPP】String类,CPP,算法,c++,数据结构,开发语言

这里我们用数学中用竖式计算加法的方法,用carry表示进位,从后往前一步一步加到ans中,同时注意细节处理,最后反转一下ans得到答案。

3.find+replace(用xx替换xx)

7.【CPP】String类,CPP,算法,c++,数据结构,开发语言
这里我们用空格替换“/”,如果用多个字符替换呢?那么上述方法就显得很低效,因为不仅开空间还要往后挪数据。解决方法:以空间换时间,重新定义一个空字符,遍历两遍老字符。第一遍开空间,第二遍往空字符加数据。如下图
7.【CPP】String类,CPP,算法,c++,数据结构,开发语言

4.string类的swap和算法的swap

7.【CPP】String类,CPP,算法,c++,数据结构,开发语言
我们可以看到string的swap只需要改变指针指向就可以了,而std库里的需要创建一个临时对象还要拷贝赋值完成交换。

5.c_str()

将string转化为c语言能够识别的const char*,如下打开文件并读取
7.【CPP】String类,CPP,算法,c++,数据结构,开发语言

三.string类的写时拷贝(copy-on-write)

1.看下面这段代码

#include<stdio.h>
#include<string>

using namespace std;
int main()
{
  string s1("hello,world");
  string s2(s1);
  printf("%x\n",s1.c_str());
  printf("%x\n",s2.c_str());

  s1[2]='m';
  printf("%x\n",s1.c_str());
  printf("%x\n",s2.c_str());

  s2[2]='m';
  printf("%x\n",s1.c_str());
  printf("%x\n",s2.c_str());
  return 0;
}

下面代码在g++下运行结果
7.【CPP】String类,CPP,算法,c++,数据结构,开发语言
我们发现前面不修改s1和s2时两者地址是一样的,而修改s1中的字符时,操作系统此时才会给s1开辟一块独立的新空间把数据拷贝过去并修改。这就是所谓的写时拷贝技术。

2.简要理解如何实现?

每当我们为string分配内存时,我们总是要多分配一个空间用来存放这个引用计数的值,只要发生拷贝构造可是赋值时,这个内存的值就会加一。而在内容修改时,string类为查看这个引用计数是否为0,如果不为零,表示有人在共享这块内存,那么自己需要先做一份拷贝,然后把引用计数减去一,再把数据拷贝过来。文章来源地址https://www.toymoban.com/news/detail-814142.html

四.string类的模拟实现

class string {
	public:
		typedef char* iterator;
		iterator begin()
		{
			return _str;
		}

		iterator end()
		{
			return _str+_size;
		}

		string(const char* str = "") :
			_size(strlen(str))
		{
			_capacity = _size;
			_str = new char[_capacity + 1+1];
			strcpy(_str, str);
			
		}

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

//现代写法
		void swap(string& tmp)
		{
			::swap(_str, tmp._str);
			::swap(_size, tmp._size);
			::swap(_capacity, tmp._capacity);
		}
		string(const string& s)
			:_str(nullptr)
			,_size(0)
			,_capacity(0)
		{
			string tmp(s._str);
			swap(tmp);
			_str[_capacity + 1]++;
		}


		~string()
		{
			delete[]_str;
			_str = nullptr;
			_size = _capacity = 0;
		}

		//实现赋值操作
		string& operator=(const string& s)
		{
			if (this != &s)
			{
				/*delete[] _str;
				_str = new char[strlen(s._str) + 1];
				strcpy(_str, s._str);*/
				char* tmp = new char[strlen(s._str) + 1];
				strcpy(tmp, s._str);

				delete[] _str;

				_str = tmp;
				_size = s._size;
				_capacity = s._capacity;
			}
			return *this;
		}

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

		size_t size()const
		{
			return _size;
		}

		size_t capacity()const
		{
			return _capacity;
		}

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

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

				_str = tmp;
				_capacity = n;
			}
		}

		void push_back(char ch)
		{
			if (_size == _capacity)
			{
				reserve(_capacity == 0 ? 0 : _capacity * 2);
			}

			_str[_size] = ch;
			++_size;
			_str[_size] = '\0';
		}

		void append(const char* str)
		{
			size_t len = strlen(str);
			if (_size + len > _capacity)
			{
				reserve(_size + len);
			}
			strcpy(_str + _size, str);
			_size += len;
		}

		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);
			}

			/*size_t end = _size;
			while (end >= 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 (_size + len > _capacity)
			{
				reserve(_size + len);
			}

			size_t end = _size + len;
			while (end >= pos + len)
			{
				_str[end] = _str[end + len];
				--end;
			}
			strncpy(_str + pos, str, len);
			_size += len;
		}

		void erase(size_t pos, size_t len = npos)
		{
			assert(pos < _size);

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

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

			return npos;
		}

		size_t find(const char* sub, size_t pos = 0)const
		{
			assert(sub);
			assert(pos < _size);
			const char* ptr = strstr(_str + pos, sub);
			if (ptr == NULL)
			{
				return npos;
			}
			else
			{
				return ptr - _str;
			}
		}

		string substr(size_t pos, size_t len = npos)const
		{
			assert(pos < _size);
			size_t reallen = len;
			if (len == npos || pos + len > _size)
			{
				reallen = _size - pos;
			}

			string sub;
			for (size_t i = 0; i < reallen; i++)
			{
				sub += _str[pos + i];
			}
			return sub;
		}


	private:
		char* _str;
		size_t _size;
		size_t _capacity;


	public:
		static size_t npos;
	};
	size_t string::npos = -1;

	istream& operator>>(istream& in, string& s)
	{
		char ch;
		ch = in.get();

		const size_t N = 32;
		char buff[N];
		size_t i = 0;

		while (ch != ' ' && ch != '\n')
		{
			buff[i++] = ch;
			if (i=N-1)
			{
				buff[i] = '\0';
				s += buff;
				i = 0;
			}
			ch = in.get();
		}
		buff[i] = '\0';
		s += buff;
	}

到了这里,关于7.【CPP】String类的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • C语言 数据结构与算法 I

    因为之前写算法都是用C++,也有了些C++基础,变量常量数据类型就跳过去吧。 首先是环境,学C++时候用Clion,C语言也用它写吧~ 新建项目,选C执行文件,语言标准。。。就先默认C99吧,反正是测试环境,应该问题不大 直接运行一手 嗯。。JB家的新UI。。真是。。。。。。。一

    2024年02月09日
    浏览(32)
  • 【C/C++数据结构与算法】C语言数据存储

    目录 一、大小端存储 二、整型提升和截断 三、数据的二进制存储 四、结构体内存对齐 大端存储 :数据的低位字节存储在高地址 小端存储 :数据的低位字节存储在低地址 不同编译器有不同的存储方式 提升 :短字节数据类型 --- 长字节数据类型 截断 :长字节数据类型 --

    2024年02月09日
    浏览(33)
  • 【学习笔记】数据结构算法文档(类C语言)

    1.1.1 线性表的顺序存储表示 1.1.2 顺序表中基本操作的实现 1.1.2.1 初始化 1.1.2.2 取值 1.1.2.3 查找 1.1.2.4 插入 1.1.2.5 删除 1.1.2.6 计数 1.2.1 单链表的定义和表示 ★ 关于结点 1.2.2 单链表基本操作的实现 1.2.2.1 初始化 1.2.2.2 取值 1.2.2.3 查找 1.2.2.4 插入 1.2.2.5 删除 1.2.2.6 前插法创建单

    2024年02月07日
    浏览(35)
  • (C语言)数据结构算法-病毒感染检测(BF算法&&KMP算法)

    病毒感染检测: 医学研究者最近发现了某些新病毒,得知它们的DNA序列都是环状的。为了快速检测出患者是否感染了相应的病毒,研究者将患者的DNA和病毒的DNA均表示成一些字母组成的字符串序列,然后检测某种病毒DNA序列是否在患者的DNA序列中出现过,如果出现过,则此人

    2024年02月08日
    浏览(38)
  • [数据结构-C语言] 算法的时间复杂度

    目录 1.算法的复杂度 2.时间复杂度 2.1 时间复杂度的概念 2.2 大O的渐进表示法 3、常见时间复杂度计算举例 3.1 冒泡排序 3.2 二分查找 3.3 阶乘递归 3.4 斐波那契数列 1.算法的复杂度 算法在编写成可执行程序后,运行时需要耗费时间资源和空间(内存)资源 。因此 衡量一个算法的

    2024年02月02日
    浏览(33)
  • 【数据结构与算法】魔王语言解释(C/C++)

    有一个魔王总是使用自己的一种非常精炼而抽象的语言讲话,没有人能听懂。但他的语言是可以逐步解释成人能懂的语言的,因为他的语言是由以下两种形式的规则由人的语言逐步抽象上去的: 形式一 α → β 1 β 2 . . . β m alpha to beta _{1} beta_{2}...beta_{m} α → β 1 ​ β 2 ​

    2024年02月07日
    浏览(38)
  • 『初阶数据结构 • C语言』② - 算法为何重要

    本文内容借鉴一本我非常喜欢的书——《数据结构与算法图解》。学习之余,我决定把这本书精彩的部分摘录出来与大家分享。   算法这个词听起来很深奥,其实不然。它只是解决某个问题的一套流程。  准备一碗麦片的流程也可以说是一种算法,它包含以下 4步(对我来说

    2024年02月14日
    浏览(26)
  • 内部排序算法比较-数据结构C语言课设

    名称: 内部排序算法比较 内容: 在教科书中,各种内部排序算法的时间复杂的分析结果只给出了算法执行时间的阶,或大概执行时间。试通过随机数据比较各种算法的比较次数和移动次数,以取得直观感受。 任务: (1)对以下7中常会用的内部排序算法进行比较

    2024年02月12日
    浏览(43)
  • 数据结构与算法教程,数据结构C语言版教程!(第五部分、数组和广义表详解)三

    数组和广义表,都用于存储逻辑关系为“一对一”的数据。 数组存储结构,99% 的编程语言都包含的存储结构,用于存储不可再分的单一数据;而广义表不同,它还可以存储子广义表。 本章重点从矩阵的角度讨论二维数组的存储,同时讲解广义表的存储结构以及有关其广度和

    2024年01月21日
    浏览(40)
  • 数据结构与算法教程,数据结构C语言版教程!(第五部分、数组和广义表详解)五

    数组和广义表,都用于存储逻辑关系为“一对一”的数据。 数组存储结构,99% 的编程语言都包含的存储结构,用于存储不可再分的单一数据;而广义表不同,它还可以存储子广义表。 本章重点从矩阵的角度讨论二维数组的存储,同时讲解广义表的存储结构以及有关其广度和

    2024年01月23日
    浏览(37)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包