当前位置: 首页 > news >正文

C++之模拟实现string

文章目录

  • 前言
  • 一、包含的相关头文件
  • 二、构造和析构
    • 1.构造函数
    • 2.拷贝构造
      • 1.传统写法
      • 2.现代写法
    • 3.赋值运算符重载
      • 1.传统写法
      • 2.现代写法
    • 4.析构函数
  • 三、iterator
  • 四、modify
    • 1.push_back(尾插一个字符)
    • 2.append(尾插一个字符串)
    • 3.运算符重载+=
      • 1.尾插字符
      • 2.尾插字符串
    • 4.clear
    • 5.insert
      • 1.插入一个字符
      • 2.插入一个字符串
    • 6.erase
  • 五、capacity
    • 1.size
    • 2.capacity
    • 3.empty
    • 4.resize
    • 5.reserve
  • 六、access
    • 1.普通对象的接口(可读可写)
    • 2.const对象的接口(只读)
  • 七、relational operators
    • 1.运算符<重载
    • 2.运算符>重载
    • 3.运算符<=重载
    • 4.运算符>=重载
    • 5.运算符==重载
    • 6.运算符!=重载
  • 八、String operations
    • 1.find
      • 1.找字符
      • 2.找子串
    • 2.c_str
  • 九、Non-member function overloads
    • 1.流插入
    • 2.流提取
  • 十、私有属性
  • 总结


前言

因为学习了string的相关知识,了解了string大部分接口的底层实现原理,所以我决定自己模拟实现一个mini版的string类,用来加深对string各方面知识的理解。
如果有错误或不足之处,还望各位读者小伙伴们指出。


一、包含的相关头文件

#include<iostream>
#include<assert.h>
#include<cstring>
using std::ostream;
using std::istream;
using std:: cout;
using std:: endl;

二、构造和析构

1.构造函数

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

2.拷贝构造

1.传统写法

该对象自己一点一点的进行深拷贝

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

2.现代写法

找一个中间对象,让这个中间对象用参数的值进行直接构造,再将这个中间对象的内容与自己的内容进行交换。相较于传统写法,现代写法更加简洁。

		//拷贝构造string(const string& s):_str(nullptr),//此处要注意将该对象的地址赋值为nullptr,否则析构中间对象时会因为发生野指针的访问而导致程序崩溃。_size(0),_capacity(0){string temp(s);swap(temp);}

此处的swap用的是string自己实现的swap,为什么不用库里的swap呢?因为库里的swap是进行深拷贝,会降低效率。我们自己实现的swap只需要进行浅拷贝,即将它们对应的资源进行交换即可。

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

3.赋值运算符重载

1.传统写法

		//赋值运算符重载string& operator=(const string &s){if (this != &s){char* temp = new char[s._capacity + 1];//用一个中间值记录新开辟的空间,如果开辟空间成功,再将该空间的地址给_str。避免因为开辟空间失败,_str原本的内容也销毁的情况发生。strcpy(temp, s._str);delete[] _str;_str = temp;_capacity = s._capacity;_size = s._size;}return *this;}

2.现代写法

与拷贝构造的现代写法思想类似,可以使程序更加简洁。并且此处不需要专门定义一个中间对象,因为传值传参传过来的形参是实参拷贝构造出来的对象,它就是一个很好的中间对象,我们直接和它进行交换即可。

		//赋值运算符重载string& operator=(string s){swap(s);return *this;}

4.析构函数

		//析构~string(){delete[] _str;_str = nullptr;//释放指针所指向的空间后要将该指针置为空(避免出现野指针的非法访问)_size = _capacity = 0;}

三、iterator

迭代器是一个使用起来像指针的东西,实际上string的迭代器就是char*类型的指针,因此我们先在最开始进行typedef

typedef char* iterator;

定义两个迭代器:分别指向字符串开头和结尾

		iterator begin(){return _str;}iterator end(){return _str + _size;}

四、modify

1.push_back(尾插一个字符)

string只提供了push_back的接口没有提供头插的接口,因为头插需要移动数据,效率很低,所以尽量不要在string中使用头插。

		void push_back(char c){if (_size == _capacity){size_t newcapacity = _capacity == 0 ? 4 : _capacity * 2;//要考虑到如果初始字符串的容量为0的情况reserve(newcapacity);_capacity = newcapacity;}_str[_size++] = c;_str[_size] = '\0';}

2.append(尾插一个字符串)

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

3.运算符重载+=

1.尾插字符

尾插一个字符(复用尾插)

		string& operator+=(char c){push_back(c);return *this;}

2.尾插字符串

尾插一个字符串(复用append)

		string& operator+=(const char* str){append(str);return *this;}

4.clear

清除string中所有元素

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

5.insert

1.插入一个字符

在字符串某位置插入一个字符:

		// 在pos位置上插入字符c/字符串strstring& insert(size_t pos, char c){assert(pos <= _size);if (_size + 1 > _capacity){reserve(_size + 1);}for (size_t i = _size + 1; i > pos; --i)//要注意避免i减为-1变成一个极大的无符号数,导致死循环{_str[i] = _str[i - 1];}_str[pos] = c;++_size;return *this;}

2.插入一个字符串

在字符串某位置插入一个字符串:

		string& insert(size_t pos, const char* str){assert(pos <= _size);size_t i = 0;size_t len = strlen(str);if (_size + len > _capacity){reserve(_size + len);}for (i = _size + len; i > pos + len - 1; --i){_str[i] = _str[i - len];}strncpy(_str + pos, str, len);_size += len;return *this;}

6.erase

删除从字符串某位置开始,某长度的子串(如果不说明删除子串的长度,则默认从开始位置到最后的所有内容都删除)

		// 删除pos位置上的元素string& erase(size_t pos, size_t len = npos){if (len == npos || pos + len > _size){_str[pos] = '\0';_size = pos;}else{strcpy(_str + pos, _str + pos + len);_size -= len;}return *this;}

五、capacity

1.size

类外成员不能直接访问类的私有属性/数据,因此需要提供一个接口进行访问数据,但是要对数据进行保护,因此用了const传参和传值返回。
访问string中的元素个数。

		size_t size()const{return _size;}

2.capacity

访问string的容量。

		size_t capacity()const{return _capacity;}

3.empty

判断字符串是否为空。

		bool empty()const{if (_size == 0){return true;}return false;}

4.resize

修改字符串的元素个数,可以尾插指定的字符,未指定则默认插入’\0’。

		void resize(size_t n, char c = '\0')//更改元素个数{if (n <= _size){_size = n;_str[_size] = '\0';}else{reserve(n);//先扩容,再加元素for (size_t i = _size; i < n; ++i){_str[i] = c;}_str[n] = '\0';_size = n;}}

5.reserve

修改字符串的容量。

		void reserve(size_t n)//更改容量大小{if (n > _capacity){char* temp = new char[n + 1];//先开空间再拷贝值(避免因为空间开辟失败的异常使_str原地址也丢失了)strcpy(temp, _str);delete[] _str;_str = temp;_capacity = n;}}

六、access

访问字符串中的字符,运算符[]重载。

1.普通对象的接口(可读可写)

		char& operator[](size_t index)//普通对象的接口(可读可写){assert(index < _size);return _str[index];}

2.const对象的接口(只读)

		const char& operator[](size_t index)const//const对象的接口(只读){assert(index < _size);return _str[index];}

七、relational operators

1.运算符<重载

		bool operator<(const string& s){size_t len = _size < s._size ? _size : s._size;for (size_t i = 0; i < len; ++i){if ((*this)[i] >= s[i]){return false;}return true;}}

2.运算符>重载

		bool operator>(const string& s){size_t len = _size < s._size ? _size : s._size;for (size_t i = 0; i < len; ++i){if ((*this)[i] <= s[i]){return false;}return true;}}

3.运算符<=重载

复用>。

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

4.运算符>=重载

复用<。

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

5.运算符==重载

复用<和>。

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

6.运算符!=重载

复用==。

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

八、String operations

1.find

1.找字符

找一个字符第一次在字符串中出现的下标

		// 返回c在string中第一次出现的位置(下标)size_t find(char c, size_t pos = 0) const{assert(pos < _size);for (size_t i = 0; i < _size; ++i){if ((*this)[i] == c){return i;}}return npos;}

2.找子串

找一个子串第一次出现在字符串中的下标
复用C语言对字符串的操作——strstr函数(在一个字符串中找子串)

		// 返回子串s在string中第一次出现的位置(下标)size_t find(const char* s, size_t pos = 0) const{assert(pos < _size);const char* ptr = strstr(_str + pos, s);if (ptr == nullptr){return npos;}else{return ptr - _str;}}

也可以一个字符一个字符的遍历寻找:

		// 返回子串s在string中第一次出现的位置(下标)size_t find(const char* s, size_t pos = 0) const{assert(pos < _size);size_t i = 0;while (i < _size){int flag = 0;if ((*this)[i] == s[0]){size_t k = i;for (size_t j = 0; j < strlen(s); ++j, ++k){if ((*this)[k] != s[j]){flag = 1;}}if (flag == 0) return i;}i++;}return npos;}

2.c_str

返回字符串的地址

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

九、Non-member function overloads

1.流插入

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

2.流提取

	istream& operator>>(istream& _cin, string& s){s.clear();//将原来s中的值清除char buff[128] = { '\0' };size_t i = 0;char ch = _cin.get();//这里不能使用getc或者scanf函数的原因是他们都是按照空格' '或者换行'\n'进行分割内容的,所以无法取到空格和换行,因此只能用get()while (ch != ' ' || ch != '\n'){if (i == 127)//缓存部分满了{s += buff;//将内容存入s,同时将缓存部分情况i = 0;}buff[i++] = ch;ch = _cin.get();}return _cin;}

十、私有属性

	private:char* _str;size_t _capacity;size_t _size;const static size_t npos = -1;//只有这个特例可以这样定义,其他static数据成员都要在类内声明,在类外定义。

总结

以上就是今天要讲的内容,本文介绍了作者自己实现的string类的相关类成员函数,如果文章中的内容有错误或者不严谨的部分,欢迎大家在评论区指出,也欢迎大家在评论区提问、交流。
最后,如果本篇文章对你有所启发的话,希望可以多多支持作者,谢谢大家!

相关文章:

C++之模拟实现string

文章目录前言一、包含的相关头文件二、构造和析构1.构造函数2.拷贝构造1.传统写法2.现代写法3.赋值运算符重载1.传统写法2.现代写法4.析构函数三、iterator四、modify1.push_back(尾插一个字符&#xff09;2.append&#xff08;尾插一个字符串&#xff09;3.运算符重载1.尾插字…...

SpringBoot实战(十三)集成 Admin

目录一、简介二、搭建 springboot-admin 管理服务1.Maven 依赖2.application.yml3.添加 EnableAdminServer4.启动服务&#xff0c;查看页面三、搭建 springboot-admin-client 客户端服务1.Maven 依赖2.application.yml3.启动服务&#xff0c;查看页面四、搭配 Eureka 使用1.搭建…...

mke2fs命令:建立ext2文件系统

以下内容源于网络资源的学习与整理&#xff0c;如有侵权请告知删除。 使用格式 mke2fs [options] [设备名称] [区块数] options与含义 -c&#xff1a;检查是否有损坏的区块。-F&#xff1a;不管指定的设备为何&#xff0c;强制执行mke2fs。-M&#xff1a;记录最后一次挂入的…...

免费分享一个springboot+vue的办公系统

springbootvue的OA系统项目介绍项目部署项目特点项目展示项目介绍 这是一个采用前后端分离开发的项目&#xff0c;前端采用 Vue 开发、后端采用 SpringBoot Mybatis 开发。 很适合java初学者练手和学习。 前端技术&#xff1a;Vue3.2 Vue-Router Pinia Ant Design Vue 3.X…...

STM32数据搬运工DMA

DMA的概念DMA&#xff0c;全称为&#xff1a;Direct Memory Access&#xff0c;即直接存储器访问。DMA 传输方式无需 CPU 直接控制传输&#xff0c;也没有中断处理方式那样保留现场和恢复现场的过程&#xff0c;通过硬件为 RAM 与 I/O 设备开辟一条直接传送数据的通路&#xff…...

4、操作系统——进程间通信(2)(system V-IPC介绍)

目录 一、system V-IPC常识 1、key和ID 2、文件描述符 3、函数&#xff08;ftok&#xff09; ftok产生IPC对象的健值key&#xff08;类似文件路径&#xff09; 4、例子 5、使用命令查看或删除当前系统中的IPC对象 一、system V-IPC常识 1、key和ID &#xff08;1&#x…...

基于CentOS Stream 9平台搭建Nacos2.0.4集群以及OpenResty反向代理

目录展示Nacos2.0.4集群搭建1. 下载2. 解压3.修改配置3.1分别修改下启动类中JDK路径以及启动大小3.2 分别配置数据源3.3 创建nacos数据库3.4 修改cluster.conf配置3.4.1 复制并修改3.4.2 编辑文件&#xff0c;修改三台主机地址3.4.3 分别放入另外两个nacos的conf目录下:4. 启动…...

老杜MySQL入门基础 第二天

导入演示数据 1、连接MySQL 2、创建"bjpowernode"数据库 create database bjpowernode;3、选择数据库 use bjpowernode4、导入数据 source D&#xff1a;\bjpowernode.sql(文件的路径)1 去除重复记录(把查询结果去除重复记录)(原表数据不会改变) 使用关键字dist…...

Python深度学习实战:人脸关键点(15点)检测pytorch实现

引言 人脸关键点检测即对人类面部若干个点位置进行检测&#xff0c;可以通过这些点的变化来实现许多功能&#xff0c;该技术可以应用到很多领域&#xff0c;例如捕捉人脸的关键点&#xff0c;然后驱动动画人物做相同的面部表情&#xff1b;识别人脸的面部表情&#xff0c;让机…...

linux简单入门

目录Linux简介Linux目录结构Linux文件命令文件处理命令文件查看命令常用文件查看命令Linux的用户和组介绍Linux权限管理Linux简介 Linux&#xff0c;全称GNU/Linux&#xff0c;是一种免费使用和自由传播的类UNIX操作系统&#xff0c;其内核由林纳斯本纳第克特托瓦兹&#xff0…...

给准备面试网络工程师岗位的应届生一些建议

你听完这个故事&#xff0c;应该会有所收获。最近有一个23届毕业的大学生和我聊天&#xff0c;他现在网络工程专业大四&#xff0c;因为今年6、7月份的时候毕业&#xff0c;所以现在面临找工作的问题。不管是现在找一份实习工作&#xff0c;还是毕业后找一份正式工作&#xff0…...

主线程与子线程之间相互通信(HandlerThread)

平时&#xff0c;我们一般都是在子线程中向主线程发送消息&#xff08;要在主线程更新UI&#xff09;&#xff0c;从而完成请求的处理。那么如果需要主线程来向子线程发送消息&#xff0c;希望子线程来完成什么任务。该怎么做&#xff1f;这就是这篇文章将要讨论的内容。 一、…...

13基于双层优化的电动汽车日前-实时两阶段市场竞标

MATLAB代码&#xff1a;基于双层优化的电动汽车日前-实时两阶段市场竞标 关键词&#xff1a;日前-实时市场竞标 电动汽车 双层优化 编程语言&#xff1a;MATLAB平台 参考文献&#xff1a;考虑电动汽车可调度潜力的充电站两阶段市场投标策略_詹祥澎 内容简介&#xff1a;…...

REDIS19_zipList压缩列表详解、快递列表 - QuickList、跳表 - SkipList

文章目录①. 压缩列表 - zipList②. 快递列表 - QuickList③. 跳表 - SkipList①. 压缩列表 - zipList ①. ZipList是一种特殊的"双端链表",由一系列特殊编码的连续内存块组成。可以在任意一端进行压入/弹出操作,并且该操作的时间复杂度为O(1) (oxff:11111111) type…...

JavaScript 基础 - 第3天

文章目录JavaScript 基础 - 第3天笔记数组数组的基本使用定义数组和数组单元数据单元值类型数组长度属性操作数组JavaScript 基础 - 第3天笔记 数组 数组的基本使用 定义数组和数组单元 <script>// 1. 语法&#xff0c;使用 [] 来定义一个空数组// 定义一个空数组let…...

23.3.26总结

康托展开 是一个全排列与自然数的映射关系&#xff0c;康托展开的实质是计算当前序列在所有从小到大的全排列中的顺序&#xff0c;跟其逆序数有关。 例如&#xff1a;对于 1,2,3,4,5 来说&#xff0c;它的康托展开值为 0*4&#xff01;0*3&#xff01;0*2&#xff01;0*1&…...

【Java学习笔记】37.Java 网络编程

Java 网络编程 网络编程是指编写运行在多个设备&#xff08;计算机&#xff09;的程序&#xff0c;这些设备都通过网络连接起来。 java.net 包中 J2SE 的 API 包含有类和接口&#xff0c;它们提供低层次的通信细节。你可以直接使用这些类和接口&#xff0c;来专注于解决问题&…...

Azure OpenAI 官方指南03|DALL-E 的图像生成功能与安全过滤机制

2021年1月&#xff0c;OpenAI 推出 DALL-E。这是 GPT 模型在图像生成方面的人工智能应用。其名称来源于著名画家、艺术家萨尔瓦多 • 达利&#xff08;Dal&#xff09;和机器人总动员&#xff08;Wall-E&#xff09;。DALL-E 图像生成器&#xff0c;能够直接根据文本描述生成多…...

【数据结构】堆

文章目录前言堆的概念及结构堆初始化堆的判空堆的销毁插入数据删除数据堆的数据个数获取堆顶数据用数组创建堆对数组堆排序有关topk问题整体代码展示写在最后前言 &#x1f6a9;前面了解了树&#xff08;-> 传送门 <-&#xff09;的概念后&#xff0c;本章带大家来实现一…...

电脑硬盘文件数据误删除/格式化为什么可以恢复? 怎么恢复?谈谈文件删除与恢复背后的原理

Hello 大家好&#xff0c; 我是元存储~ 主页&#xff1a;元存储的博客_CSDN博客 1. 硬盘数据丢失场景 我们在每天办公还是记录数据的时候&#xff0c;文件存储大多数都是通过硬盘进行存储的&#xff0c;因此&#xff0c;使用多了&#xff0c;各种问题就会出现&#xff0c;比如…...

Gateway服务网关

Spring Cloud Gateway为微服务架构提供一种简单有效的统一的 API 路由管理方式。Gateway网关是所有微服务的统一入口。网关的核心功能特性&#xff1a;请求路由和负载均衡&#xff1a;一切请求都必须先经过gateway&#xff0c;但网关不处理业务&#xff0c;而是根据某种规则&am…...

K8S + GitLab + Jenkins自动化发布项目实践(一)

K8S GitLab Jenkins自动化发布项目实践&#xff08;一&#xff09;发布流程设计安装Docker服务部署Harbor作为镜像仓库部署GitLab作为代码仓库常用Git命令发布流程设计 #mermaid-svg-pe9VmFytb9GmqMvG {font-family:"trebuchet ms",verdana,arial,sans-serif;font-…...

【数据结构篇C++实现】- 堆

文章目录&#x1f680;一、堆的原理精讲⛳&#xff08;一&#xff09;堆的概念⛳&#xff08;二&#xff09;看图识最大堆⛳&#xff08;三&#xff09;详解堆是用数组表示的树&#x1f680;二、堆的向下调整算法&#x1f680;三、堆的向上调整算法&#x1f680;四、将任意一棵…...

C++笔试题

作用域运算符(::)的作用&#xff1a;1.存在具有相同名称的局部变量时&#xff0c;访问全局变量。2.在类之外定义类相关函数。3.访问类的静态变量。4.在多重继承的情况下&#xff0c;如果两个基类中存在相同的变量名&#xff0c;可以使用作用域运算符来进行区分。5.限定成员函数…...

【Python】基本语法

数据类型 通过 print(type(x)) 可以输出 x 的数据类型&#xff0c;type() 函数可以获取数据类型 整数 a 10 print(type(a)) 浮点数 a 0.5 print(type(a)) 字符串 a hello print(type(a)) 获取字符串长度 a hello print(len(a))字符串拼接 a hello b world prin…...

用栈实现队列(图示超详解哦)

全文目录引言用栈实现队列题目介绍思路简述实现栈的部分队列的部分创建队列判断队列是否为空在队列尾入在队列头出访问队头元素释放队列总结引言 在上一篇文章中&#xff0c;我们了解了用两个队列实现栈。在这篇问章中将继续介绍用两个栈实现队列的OJ练习&#xff1a; 用栈实现…...

Spring - Spring 注解相关面试题总结

文章目录01. Spring 配置方式有几种&#xff1f;02. Spring 如何实现基于xml的配置方式&#xff1f;03. Spring 如何实现基于注解的配置&#xff1f;04. Spring 如何基于注解配置bean的作用范围&#xff1f;05. Spring Component, Controller, Repository, Service 注解有何区别…...

【数据结构】实现二叉树的基本操作

目录 1. 二叉树的基本操作 2. 具体实现 2.1 创建BinaryTree类以及简单创建一棵树 2.2 前序遍历 2.3 中序遍历 2.4 后序遍历 2.5 层序遍历 2.6 获取树中节点的个数 2.7 获取叶子节点的个数 2.8 获取第K层节点的个数 2.9 获取二叉树的高度 2.10 检测值为val的元素是否…...

代码随想录算法训练营第五十二天| ● 300.最长递增子序列 ● 674. 最长连续递增序列 ● 718. 最长重复子数组

300.最长递增子序列 看完题后的思路 dp[i] [0,i]子数组中,以nums[i]结尾的子序列的长度 dp[i]dp[j]1 j从i-1向0遍历,在所有nums[j]<nums[i]中dp[j]最大 初始化 dp[0]1 代码 class Solution {public int lengthOfLIS(int[] nums) {if (nums.length0){return 0;}int[] dpne…...

手机验证发送及其验证(基于springboot+redis)保姆级

在Java开发中&#xff0c;发送手机验证码时需要考虑以下几个问题&#xff1a; 验证码的有效期&#xff1a;验证码应该有一定的有效期&#xff0c;一般设置为几分钟或者十几分钟。过期的验证码应该被认为是无效的&#xff0c;不能用于验证用户身份。手机号码格式的校验&#xf…...

哪里找做网站的公司/活动推广软文

1 饼状图 import mx.collections.ArrayCollection; //绑定需要显示的数据 [Bindable] //设定要显示的数据 private var modelData:ArrayCollection new ArrayCollection( [ { Year: "2010年世界杯", Count: 4 }, { Year: "2014年世界杯", Count: 10 }, { …...

织梦网站怎么做下载地址/企业培训考试

来上海的这段日子里偶的博客有很长一段时间没有更新了&#xff0c;人流量下降了不少哈&#xff01;为了弥补自己的过失&#xff0c;打算最近开博啦&#xff0c;不过说句实话还真不知道该写些什么哈&#xff01;既然不知道该写什么&#xff0c;那就说说来上海的这段日子的感受吧…...

个人房产查询系统网站官网/百度收录提交网站后多久收录

因为要讲座&#xff0c;随便写一下&#xff0c;等讲完有时间好好写一篇splay的博客。 先直接上题目然后贴代码&#xff0c;具体讲解都写代码里了。 参考的博客等的链接都贴代码里了&#xff0c;有空再好好写。 P2042 [NOI2005]维护数列 题目描述 请写一个程序&#xff0c;要求维…...

温州网站制作费用/星巴克网络营销案例分析

[NOIP2017 普及组] 棋盘 题目背景 NOIP2017 普及组 T3 题目描述 有一个mmm \times mmm的棋盘&#xff0c;棋盘上每一个格子可能是红色、黄色或没有任何颜色的。你现在要从棋盘的最左上角走到棋盘的最右下角。 任何一个时刻&#xff0c;你所站在的位置必须是有颜色的&#…...

网站导航上的图片做多大尺寸/seo和竞价排名的区别

一个完整的信号一定是以0开始然后以0结尾的,输入一串方波信号是由一个或者多个完整信号组成的,两个相邻的信号之间可能有-个或者多个低位, 同一个信号中间可以有连续的高位,完全连续交替方波是指0交替, while 1:try:nums = input()# 提取信号段,由0分隔的信号段dp = []…...

新疆建设云网站办理程序/微信拓客的最新方法

复盘微信支付金额不正确问题—PHP浮点型计算2020-11-15 11:58:29一、背景在做微信支付项目的时候&#xff0c;微信要求金额的单位必须为分&#xff0c;而数据库中订单金额单位是元&#xff0c;所以使用订单金额*100是正确的做法&#xff0c;但是会经常出现少一分钱的状况&#…...