C++ --> string类模拟实现(附源码)
欢迎来到我的Blog,点击关注哦💕
前言:
C++中
STL
扮演着极其重要的角色,学习C++重中之重的就是学习STL
,虽然string不作为containers的其中一员,但是也是值得学习的le类。下面就进行string
的模拟实现
string的模拟实现和顺序表是差不多,就是增加了C++的特性。
string 模拟实现
存储结构
结构上使用命名空间mystr
进行封装,防止与库冲突,使用class封装成为对象string:
- 定义
_size
方便记录string
的大小。 - 定义
_capacity
方便记录string
的容量大小 - 定义
char* _str
是存储数据,进行动态new出空间 nops
:npos
用于表示在字符串中未找到所查找的子串,或者表示一个超出字符串长度的有效索引位置。npos
的值通常被定义为std::size_t
类型的最大值,这是一个无符号整数类型,因此npos
实际上是一个非常大的正整数,用于表示没有找到匹配项或字符串的结束位置.
namespace mystr
{class string{public:static const size_t npos = -1;private: size_t _size;size_t _capacity;char* _str;};
}
默认构造函数
构造函数
- 全缺省的构造函数也是默认构造函数,结尾给
""
常量字符串末尾存在\0
;
- 默认构造函数:全缺省、无参、编译器默认生成的构造函数称之为
默认构造函数
- 采取初始化列表,对于常量引用可以进行初始化。
strlen
计算出大小,初始化_size
2. 注意:初始化顺序就是声明的顺序,这个也是为什么将char* _str
放在最后; _capacoty
初始化容量+1的目的是给\0
开辟空间;- 最后将
str
进行拷贝,这里采用memcpy
不采用strcpy
3.memcpy
可以将全部内容拷贝,strcpy
会识别\0
停止,假使字符串hello\0 world
构造就不会得到我们想要的结果
string(const char* str = ""):_size(strlen(str)), _capacity(_size), _str(new char[_capacity + 1]){ memcpy(_str, str, _capacity + 1);}
拷贝构造函数
- 众所周知的是当不存在拷贝构造函数,编译器会自动生成拷贝构造函数;
- 编译器生成的仅仅会实现数值上的拷贝(浅拷贝)
_str
new出空间,要实现内容上的拷贝(深拷贝)
_capacoty
初始化容量+1的目的是给\0
开辟空间;
string(const string& s)
{_capacity = s._capacity;_size = s._size;_str = new char[s._capacity+1];memcpy(_str, s._str, _capacity+1);
}
赋值运算符重载
赋值预算符重载的底层逻辑是和拷贝构造函数是一样的,在这里就不过多介绍了
string& operator=(const string& s)
{_capacity = s._capacity;_size = s._size;_str = new char[_capacity + 1];memcpy(_str, s._str, _capacity + 1);}
析构函数
程序的整个历程开辟空间,不进行空间的释放不是一个好的习惯,这里析构函数就要上场了
~string()
{_size = 0;_capacity = 0;delete[] _str;_str = nullptr;
}
迭代器(iterator)
-
string
的迭代器的本质就是指针,根据C语言的指针很容易就可以理解,就是将 char * 进行typefed char* iterator
-
迭代器实现两个版本
const
和非const
, 只读和可读可写
begin()
iterator begin()
{return _str;
}iterator begin()const
{return _str;
}
end()
iterator end()
{return _str + _size;
}iterator end()const
{return _str + _size;
}
容量(capacity)
size
mstr::string
类定义了_size
直接将其返回
size_t size()const
{
return _size;
}
capacity
mstr::string
类定义了_capacity
直接将其返回
size_t capacity() const
{return _capacity;
}
resize
resize
是将后面指定大小初始化指定的字符(缺省:\0
)- 进行容量的检查,不够扩容
- 一层循环初始化为
ch
- 修改
_size
长度为n
void resize(size_t n,char ch = '\0')
{if (n < _size){_str[n ] = '\0';_size = n;}else{reverse(n);for (size_t i = _size; i < n; i++){_str[i] = ch;}_str[_size] = '\0';_size = n;}}
reverse
- 由于很多地方进行复用,需要在函数内部进行判断提高效率
- 开辟一个大于原始空间的新的空间,将
_str
拷贝过去,改变_str
的指向,将新开辟的空间释放谨防内存泄漏
void reverse(size_t n)
{if (n > _capacity){char* tmp = new char[n + 1];memcpy(tmp, _str, _capacity + 1);delete[] _str;_capacity = n;_str = tmp;}}
empty
直接判断_size
是否为0即可
bool empty()const
{
return _size == 0 ? true : false;
}
clear
- 直接将首位置赋值为
\0
,修改_size
大小即可
void clear()
{_str[0] = '\0';_size = 0;
}
修改(modify)
push_back
C++string
中 push_back 函数声明:void push_back (char c);
在字符串后追加一个字符;
- 开始要检查容量 进行扩容这里用
reverse
实现 - 由于一个字符,仅仅需要在
_size
位置上直接赋值,在_size+1
的位置上赋值\0
void push_back(char ch)
{if (_size == _capacity){reverse(_capacity == 0 ? 4 : _capacity * 2);}_str[_size] = ch;_str[_size + 1] = '\0';_size++;
}
append
append
后面追加一个字符可以进行复用push_back
append
后面追加一个字符串和添加一个string
类是一样的思路是一样;
//追加一个字符
void append(const char ch)
{
push_back(ch);
}
//追加一个字符串
void append(const char* str)
{
size_t len = strlen(str);
if (_size + len > _capacity)
{
reverse(_capacity + len);
}
memcpy(_str + _size, str, len + 1);
}
//追加一个string类
void append(const string& str)
{
if (_size + str._size == _capacity)
{
reverse(_size + str._size);
}memcpy(_str + _size, str._str, str._size+1);
}
operator+=
由于是实现了append
实现运算符重载就方便跟多,功能一样,结果一样直接进行复用
//追加一个字符
string& operator+= (const char* str)
{append(str);return *this;
}
//追加一个字符串
string& operator+= (const string& str)
{append(str._str);return *this;
}
//追加一个string类
string& operator+= (char ch)
{push_back(ch);return *this;
}
inset
-
实现两个版本,插入字符和插入字符串
-
string
类是没有实现push_front
头插入,insert
就有很大的作用了在pos
位置进行插入 -
首先进行
pos
位置的断言,保证pos
在字符串的有效位置 -
进行容量检查,进行扩容.
-
将
pos
位置后面的字符(以及pos
位置)依次向后面移len
个长度,在pos
位置插入字符(字符串) -
i!= npos
在for
循环中如果i
变成了0,之后再去减1 ,size_t
下的-1
会变为无线大,会陷入死循环。 -
最后不要忘记将
_size
进行修改
//插入字符
string& insert(size_t pos, char c)
{assert(pos < _size);if (_capacity == _size){reverse(_size+1);}for (size_t i = _size; i >= pos&& i!= npos; i--){_str[i + 1] = _str[i];}_str[pos] = c;_size++;return *this;
}
//插入字符串
string& insert(size_t pos, const char* str)
{assert(pos < _size);size_t len = strlen(str);if (_capacity == _size){ reverse(_size + len);}for (size_t i = _size; i >= pos&& i!= npos; i--){_str[i + len] = _str[i];}memcpy(_str + pos, str, len);_size+=len;return *this;}
erase
-
首先进行
pos
位置的断言,保证pos
在字符串的有效位置 -
erase
是在pos
位置删除len
个字符(缺省值:npos
) -
函数主体进入进
len
的判断,如果len == npos
或pos + len >= _size
超出字符串的长度,就是从pos
后全部删除 -
否则没有超过将
pos + len
位置后面的数据将pos
位置移动直至移动到\0
string& erase(size_t pos, size_t len = npos)
{assert(pos < _size);if (len == npos || pos + len >= _size){_str[pos] = '\0';_size = pos;}else{size_t end = pos + len;while (end <= _size){_str[pos++] = _str[end++];}_size -= len;}}
swap
- 利用C++库中的swap进行
string
类的交换
void swap(string& s)
{
string tmp(s);
std::swap(_str, tmp._str);
std::swap(_size, tmp._size);
std::swap(_capacity, tmp._capacity);
}
元素访问(Element access)
operator [ ]
- 实现
const
和非const
两种,只读和可读可改 - 充分利用字符串特性可以进行下标的访问
//const
char& operator[](size_t index)
{assert(index < _size);return _str[index];
}
//nonconst
const char& operator[](size_t index)const
{assert(index < _size);return _str[index];
}
字符串操作(String operations)
c_str
- 直接返回
_str
const char* c_str()
{return _str;
}
find
- 首先进行
pos
位置的断言,保证pos
在字符串的有效位置 - 字符串查找利用C语言中的
strstr
函数进行查找 - 返回下面的下标,利用指针减指针的方法,没有找到返回
npos
size_t find(const char* s, size_t pos = 0) const
{assert(pos < _size);char* p = strstr(_str, s);if (p){return p - _str;}else{return npos;}}
关系运算符(relational operators)
进行比较的重载
- 实现
<
==
其他的进行复用即可 - 使用
memcpy
进行比较,比较字符串较小的那个_size < s._size ?_size : s._size
- 返回 为 0 返回比较长(
_size < s._size
)的那个否则返回假(ret < 0
)
//重载<
bool operator<(const string& s)
{int ret = memcmp(_str, s._str, (_size < s._size ?_size : s._size));return ret == 0 ? _size < s._size : ret < 0;
}
//重载==
bool operator==(const string& s)
{return _size == s._size && memcmp(_str, s._str, _size);
}
//重载<=
bool operator<=(const string& s)
{return !(*this > s);
}
//重载>
bool operator>(const string& s)
{return !(*this <= s);
}
//重载>=
bool operator>=(const string& s)
{return !(*this < s);
}
//重载!=
bool operator!=(const string& s)
{return !(*this == s);
}
流提取和插
operator<<
- 这个函数是写在类外面的一个友元函数
- 使用范围
for
进行实现
ostream& operator<<(ostream& out, const mystr::string& s)
{for (auto ch : s){out << ch;}return out;
}
operator>>
s.clear();
这句话是清理缓冲区上次cin
的残留- 第一个
while
循环是处理缓冲区的空格 - 创建一个数组,避免多次开辟空间,直至大小到128拷贝会加到
string
s 中 - 最后的
if
语句是字符遇见空格或者换行结束,末尾添加\0
istream& operator>>(istream& in, string& s)
{s.clear();char ch = in.get();// 处理前缓冲区前面的空格或者换行while (ch == ' ' || ch == '\n'){ch = in.get();}char buff[128];int i = 0;while (ch != ' ' && ch != '\n'){buff[i++] = ch;if (i == 127){buff[i] = '\0';s += buff;i = 0;}ch = in.get();}if (i != 0){buff[i] = '\0';s += buff;}return in;
}
mystr:: string
源码
#pragma once#include<iostream>#include<string.h>
#include <assert.h>
#include <stdlib.h>using namespace std;namespace mystr
{class string{friend ostream& operator<<(ostream& _cout, const mystr::string& s);friend istream& operator>>(istream& _cin,mystr::string& s);public:typedef char* iterator;typedef const char* const_iterator;string(const char* str = ""):_size(strlen(str)), _capacity(_size), _str(new char[_capacity + 1]){ memcpy(_str, str, _capacity + 1);}//析构函数~string(){_size = 0;_capacity = 0;delete[] _str;_str = nullptr;}// 拷贝构造函数string(const string& s){_capacity = s._capacity;_size = s._size;_str = new char[s._capacity+1];memcpy(_str, s._str, _capacity+1);}//赋值预算符重载string& operator=(const string& s){_capacity = s._capacity;_size = s._size;_str = new char[_capacity + 1];memcpy(_str, s._str, _capacity + 1);}const char* c_str(){return _str;}//迭代器iterator begin(){return _str;}iterator end(){return _str + _size;}iterator begin()const {return _str;}iterator end()const{return _str + _size;}//capacitysize_t size()const{return _size;}size_t capacity() const{return _capacity;}void reverse(size_t n){if (n > _capacity){char* tmp = new char[n + 1];memcpy(tmp, _str, _capacity + 1);delete[] _str;_capacity = n;_str = tmp;}}void resize(size_t n,char ch = '\0'){if (n < _size){_str[n ] = '\0';_size = n;}else{reverse(n);for (size_t i = _size; i < n; i++){_str[i] = ch;}_str[_size] = '\0';_size = n;}}bool empty()const{return _size == 0 ? true : false;}//access//modifyvoid push_back(char ch){if (_size == _capacity){reverse(_capacity == 0 ? 4 : _capacity * 2);}_str[_size] = ch;_str[_size + 1] = '\0';_size++;}void append(const char ch){push_back(ch);}void append(const char* str){size_t len = strlen(str);if (_size + len > _capacity){reverse(_capacity + len);}memcpy(_str + _size, str, len + 1);}void append(const string& str){if (_size + str._size == _capacity){reverse(_size + str._size);}memcpy(_str + _size, str._str, str._size+1);}string& operator+= (const char* str){append(str);return *this;}string& operator+= (const string& str){append(str._str);return *this;}string& operator+= (char ch){push_back(ch);return *this;}void clear(){_str[0] = '\0';_size = 0;}void swap(string& s){string tmp(s);std::swap(_str, tmp._str);std::swap(_size, tmp._size);std::swap(_capacity, tmp._capacity);}//relational operatorsbool operator<(const string& s){int ret = memcmp(_str, s._str, (_size < s._size ?_size : s._size));return ret == 0 ? _size < s._size : ret < 0;}bool operator==(const string& s){return _size == s._size && memcmp(_str, s._str, _size);}bool operator<=(const string& s){return !(*this > s);}bool operator>(const string& s){return !(*this <= s);}bool operator>=(const string& s){return !(*this < s);}bool operator!=(const string& s){return !(*this == s);}// 返回c在string中第一次出现的位置size_t find(char c, size_t pos = 0) const{assert(pos < _size);for (size_t i = pos; i < _size; i++){if (_str[i] == c){return i;}}return npos;}// 返回子串s在string中第一次出现的位置size_t find(const char* s, size_t pos = 0) const{assert(pos < _size);char* p = strstr(_str, s);if (p){return p - _str;}else{return npos;}}// 在pos位置上插入字符c/字符串str,并返回该字符的位置string& insert(size_t pos, char c){assert(pos < _size);if (_capacity == _size){reverse(_size+1);}for (size_t i = _size; i >= pos; i--){_str[i + 1] = _str[i];}_str[pos] = c;_size++;return *this;}string& insert(size_t pos, const char* str){assert(pos < _size);size_t len = strlen(str);if (_capacity == _size){ reverse(_size + len);}for (size_t i = _size; i >= pos; i--){_str[i + len] = _str[i];}memcpy(_str + pos, str, len);_size+=len;return *this;}string& erase(size_t pos, size_t len = npos){assert(pos < _size);if (_capacity == _size){reverse(_size + len);}if (len == npos || pos + len >= _size){_str[pos] = '\0';_size = pos;}else{size_t end = pos + len;while (end <= _size){_str[pos++] = _str[end++];}_size -= len;}}private: size_t _size;size_t _capacity;char* _str;public:const static size_t npos;};const size_t string::npos = -1;ostream& operator<<(ostream& out, const mystr::string& s){for (auto ch : s){out << ch;}return out;}istream& operator>>(istream& in, string& s){//清除缓冲区s.clear();char ch = in.get();while (ch == ' ' || ch == '\n'){ch = in.get();}char buff[128];int i = 0;while (ch != ' ' && ch != '\n'){buff[i++] = ch;if (i == 127){buff[i] = '\0';s += buff;i = 0;}ch = in.get();}if (i!= 0){buff[i] = '\0';s += buff;}return in;}}
相关文章:
C++ --> string类模拟实现(附源码)
欢迎来到我的Blog,点击关注哦💕 前言: C中STL扮演着极其重要的角色,学习C重中之重的就是学习STL,虽然string不作为containers的其中一员,但是也是值得学习的le类。下面就进行string的模拟实现 string的模拟…...
基于PHP+MySQL组合开发的微信活动投票小程序源码系统 带完整的安装代码包以及搭建部署教程
系统概述 在当今数字化时代,微信作为社交媒体的巨头,为企业和个人提供了丰富的互动营销平台。其中,投票活动作为一种有效的用户参与和互动方式,被广泛应用于各种场景。为了满足这一需求,我们推出了一款基于PHPMySQL组…...
利用Arcgis设置分式标注(分子分母标注)
因工作需要,需要设置分式标注,下面详细介绍下如何利用arcgis 设置分式标注,以下操作以供参考,如有疑义可提出。 一、准备工作 软件:arcmap 示例数据:行政区shp矢量图 二、操作步骤 1.添加数据 将行政区sh…...
大麦网抢票攻略:使用Python Selenium实现
随着互联网技术的发展,在线购票已成为人们获取演出、比赛等活动门票的主要方式。然而,面对热门活动,门票往往在开售瞬间被抢购一空。为了解决这一问题,本文将介绍如何利用Python和Selenium技术实现大麦网的自动抢票。 1. 环境准备…...
Navicat 在整个数据库中查找字符
Navicat 在整个数据库中查找字符 1.首先打开Navicat,连接目标数据库。2.选择工具选项卡,选择在数据库或模式中查找。3.查找前填入关键字信息,点击查找4.双击查找到数据,进行查看 说明:当我们知道数据库有数据的关键字,…...
Python基础—处理时间问题
一文帮助您解决99%时间处理问题...
如何选择合适的自动化测试工具!
选择合适的自动化测试工具是一个涉及多方面因素的决策过程。以下是一些关键步骤和考虑因素,帮助您做出明智的选择: 一、明确测试需求和目标 测试范围:确定需要自动化的测试类型(如单元测试、集成测试、UI测试等)和测试…...
数字图像边缘曲率计算及特殊点检测
一、曲率和数字图像边缘曲率检测常用方法简介 边缘曲率作为图像边缘特征的重要参数,不仅反映了边缘的几何形状信息,还对于图像识别、图像分割、目标跟踪等任务具有显著影响。 曲线的曲率(curvature)就是针对曲线上某个点的切线方向…...
python map
在 Python 中,如果你指的是字典(dictionary),可以使用字典的 .items() 方法来遍历键值对。Python 中没有严格意义上的 Map 类型,而是使用字典来实现类似于键值对映射的功能。 遍历字典的键值对 可以使用 for 循环和 …...
每日一练 - NFV部署应用环境
01 真题题目 NFV 常常部署在下列哪些应用环境中?(多选) A.数据中心 B.网络节点 C.用户接入侧 D.客户机/服务器 02 真题答案 ABC 03 答案解析 NFV(Network Functions Virtualization,网络功能虚拟化)是一种技术,它允许在标准的…...
031-GeoGebra中级篇-GeoGebra的布尔值
在 GeoGebra 中,布尔值和条件判断是实现动态数学模型和交互式几何图形的重要工具。布尔值,即逻辑值,只有两个可能的取值:真(True)或假(False)。通过使用布尔值,我们可以创…...
基于Debian用户安装星火商店
星火商店下载地址:https://www.spark-app.store/ 本文章我以kali linux来做示范 注:基本debian的linux包括ubuntu,mint linux,kali linux,Pop!_OS,deepin等等 1.点击下载最新版本 2.点击下载 3.点击开始下载(它会自动跳转网页) 4.选择要下载…...
《计算机网络》(第8版)课后习题答案
【1-01】 计算机网络可以向用户提供哪些服务? 解答:这道题没有现成的标准答案,因为可以从不同的角度来看“服务”。 首先要明确的是,计算机网络可以向用户提供的最重要的功能有两个:连通性和共享。所 谓连通性,就是计算机网络使上网用户之间都可以交换信息,好像这些用户…...
我们的网站被狗爬了!
大家好,我是程序员鱼皮。 世风日下,人心不古。我们的程序员面试刷题网站 《面试鸭》 才刚刚上线了一个多月,就由于过于火爆,被不少同行和小人发起网络攻击。 而且因为我们已经有 4500 多道人工整理的企业高频面试题、100 多个各…...
docker安装与container基本使用
安装 Homebrew 的 Cask 已经支持 Docker for Mac, mac用户狂喜 brew install --cask --appdir/Applications docker其他入门用法可参考 Docker Hello World- 菜鸟教程 或网上自行搜索博客学习。本文主要记录我运行go-zero-mall用到的一些注意点。当然,gonivinck项…...
掌握文本搜索的利器:深入解析 Linux grep 命令的强大功能
grep 是一个强大的命令行工具,用于在文件中搜索指定的模式(字符串或正则表达式)。它的名字来源于 "global regular expression print",常用于文本处理、日志分析等任务。以下是 grep 命令的详细介绍和常用操作: 基本用法 搜索匹配的行 grep "pattern"…...
【天机学堂】面试总结
写在前面,首先要将天机学堂包装一下,智慧教育平台》,暂时就想到这个。天机学堂文档 1.包装简历 待更新。。。...
Java中Stream操作
Java中Stream操作 Stream 和 Optional区别 用途不同:Stream 用于处理集合中的元素序列,支持丰富的中间操作和终端操作;Optional 用于表示一个值可能为 null 的情况,提供了一种更优雅的处理方式。数据处理 vs. 容器:S…...
Spring Boot + MinIO 实现文件的分片上传、秒传、续传功能
文件上传是一个常见的功能需求。然而,传统的文件上传方式在面对大文件或不稳定的网络环境时,可能会出现性能瓶颈和上传失败的问题。为了解决这些问题,分片上传、秒传和续传技术应运而生. 技术选型 Spring Boot:一个快速开发框架,简化了 Spring 应用的搭建和配置。 MinIO:…...
Kafka基本概念,工作流程介绍
1、消息队列与Kafka 1.1、Kafka简介 Kafka使用scala开发,支持多语言客户端(c、java、python、go等) Kafka最先由LinkedIn公司开发,之后成为Apache的顶级项目。 Kafka是一个分布式的、分区化、可复制提交的日志服务 LinkedIn使…...
Golang | Leetcode Golang题解之第306题累加数
题目: 题解: func stringAdd(x, y string) string {res : []byte{}carry, cur : 0, 0for x ! "" || y ! "" || carry ! 0 {cur carryif x ! "" {cur int(x[len(x)-1] - 0)x x[:len(x)-1]}if y ! "" {cur i…...
快速排序(上)
快速排序 前言 快速排序算法是最流行的排序算法,且有充足的理由,因为在大多数情况下,快速排序都是最快的。所以学习快速排序算法十分有必要。当然,既然它这么好,也就不太容易理解。 正文 Hoare版快排 快速排序是Hoare在1962年提出的一种二叉树结构的…...
数据结构-队列
队列对于临时数据的处理也十分有趣,它跟栈一样都是有约束条件的数组。区别在于我们想要按什么顺序去处理数据,而这个顺序当然是要取决于具体的应用场景。 你可以将队列想象成是电影院排队。排在最前面的人会最先离队进入影院。套用到队列上,…...
MySQL:操作符
MySQL 操作符 MySQL 操作符是 MySQL 数据库操作中不可或缺的一部分,它们用于执行各种数据运算、比较、逻辑判断等。 MySQL 中有多种操作符可用于数据查询和筛选 MySQL 所提供的运算符可以直接对表中数据或字段进行运算 MySQL 支持 4 种运算符,分别是&…...
反序列化靶机实战serial(保姆级教程)
一.信息收集 靶机地址下载:https://download.vulnhub.com/serial/serial.zip 打开靶机,在kali虚拟机中进行主机存活探测 可以知道靶机ip地址为192.168.133.171 然后扫描端口 可以发现有一个22端口跟80端口 然后接下来用kali扫描它的目录 可以发现有一…...
【Git】git 从入门到实战系列(一)—— Git 的诞生,Linus 如何在 14 天内编写出 Git?
<> 博客简介:Linux、rtos系统,arm、stm32等芯片,嵌入式高级工程师、面试官、架构师,日常技术干货、个人总结、职场经验分享 <> 公众号:嵌入式技术部落 <> 系列专栏:C/C、Linux、rt…...
com.microsoft.sqlserve r:sqljdbc4:jar:4.0 was not found in......如何解决?
这个错误提示说 com.microsoft.sqlserver:sqljdbc4:jar:4.0 这个依赖无法从 Maven 中央仓库(https://repo.maven.apache.org/maven2)下载,导致项目无法构建。以下是解决该问题的几种方法: 方法一:手动安装依赖 下载 J…...
数据集——鸢尾花介绍和使用
文章目录 一、鸢尾花数据集内容二、使用中常转换DataFrame 一、鸢尾花数据集内容 from sklearn import svm, datasets # 鸢尾花数据 iris datasets.load_iris() print(iris.data) X iris.data[:, :2] # 为便于绘图仅选择2个特征 y iris.target它包含了150个样本,…...
ElasticSearch第4篇(亿级中文数据量 ElasticSearch与Sphinx建索引速度、查询速度、并发性能、实测对比)
经过实测:1.09亿的数据量进行中文检索。ElasticSearch单机的检索性能在0.005~5.6秒之间,此检索速度可满足95%的业务场景(注意:每条ES文档平均65个汉字,数据源取自几千本小说,大部分文档在15~300个汉字之间&…...
过期知识:thinkphp5 使用migrate给现有的数据表新增表字段
个人开发网站记录, 这个文章主要是个以后健忘的我看的. 我在搞我的画笔审核 , 发现数据表的画笔数据在审核驳回的时候还是软删除好一些, 免得用户找不到之前上传的画笔数据, 后期也可以考虑重新显示给用户,让用户可以修改画笔信息重新提交审核. 这个时候想起了…...
地方网站怎么做的/百度一下官网网址
1. 涉及平台 平台管理、商家端(PC端、手机端)、买家平台(H5/公众号、小程序、APP端(IOS/Android)、微服务平台(业务服务) 2. 核心架构 Spring Cloud、Spring Boot、Mybatis、Redis 3. 前端框架…...
花生棒做网站/如何推广app更高效
老电脑要装什么系统比较好?电脑更新换代速度非常快,现在买的新电脑没几天就变成“老电脑”了,电脑目前已经普及十几年,最开始的老旧电脑硬件配置惨不忍睹,不过在那个年代算很牛逼了,毕竟技术有限。那么老旧…...
利用博客做网站/seo实战密码第三版pdf下载
在 Apache RocketMQ 中,当消费者去消费消息的时候,无论是通过 pull 的方式还是 push 的方式,都可能会出现大批量的消息突刺。如果此时要处理所有消息,很可能会导致系统负载过高,影响稳定性。但其实可能后面几秒之内都没…...
云南 网站建设网站/百度收录规则
某条消息发布后,距离当前时间多久的时间显示 1 //显示发布时间的函数2 function pastTime(_createTime) {3 //var createTime _createTime.substr(0, _createTime.lastIndexOf(" ")) //不能包含毫秒,如果有毫秒,进行截取4 …...
wordpress 同步 微博/美国搜索引擎排名
视频链接 一.:设计模式面试题 & 课程介绍(1~4) 1.:原型设计模式的,几个经典面试题: 1)请使用 UML 类图,画出原型模式核心角色? 2)原型设计模式的深拷贝 & 浅拷贝是什么? 并写出 深拷贝的,两种方式的源码? -1:重写 clone 方法,…...
wordpress简体切换/网站推广软文
展开全部大四学生32313133353236313431303231363533e58685e5aeb931333433653933,应该先考研还是工作后再考研?这两种选择,哪一个更实惠?作出选择之前,这3个问题一定要考虑清楚。考虑复习效果一般情况下,多数…...