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

【C++杂货铺】详解string

f9b4d418a2c44c5d892c11ad88c04306.png


目录

 🌈前言🌈

📁 为什么学习string

📁 认识string(了解)

📁 string的常用接口

 📂 构造函数

 📂 string类对象的容量操作

 📂 string类对象的访问以及遍历操作​编辑

 📂 string类对象的修改操作

📁 模拟实现string

📁 总结


 🌈前言🌈

        欢迎观看本期【C++杂货铺】,本期内容将全面string,包含了解string,如何操作string,最后会模拟实现string

        因为计算机行业的不断发展,许多程序员不仅仅要掌握string这些容器的使用方法,有的公司会要求阅读底层源码,模拟实现这些容器,所以本期内容将会从零开始,带大家了解使用string。

        当然,本篇内容的参考文献主要来源于网站:<string> - C++ Reference (cplusplus.com)

        如果,你只想掌握string的具体使用方法,可以阅读下面这篇文章:

【C++杂货铺】详解string的接口-CSDN博客

b9fef61f29b6488b95f0417ce2f9f96a.gif

📁 为什么学习string

        在C语言中,字符串是以‘\0’结尾的一些字符的结合,为了操作方便,C标准库提供了一些str系列的库函数,但这些库函数与字符串是分开的,底层空间需要用户自己管理,可能造成越界访问等。

        在日常生活中,为了简单,方便,快捷,基本都会使用string类,很少会有人去使用C库中的字符串操作函数。

📁 认识string(了解)

        string是表示字符串的字符串。该类的接口与常规容器的接口基本相同,在添加了一系列专门用来操作string的常规操作。

        string是basic_string模板类的一个别名,用char来实例化basic_string模板类。

        string不能操作多字节或者边长字符的序列。

        在使用string时,必须包括#include头文件以及using namespace std;

📁 string的常用接口

        string接口有上百种,这里我们只介绍常用的,以及需要了解的。

 📂 构造函数

94c2d4027e764186a34f52cd9ceb244e.png

//函数名称                                      功能说明
string()   重点                       构造空的string类对象,即空字符串
string(const string* s)  重点         用C_string来构造string类对象
string(size_t n,char c)               string类对象中把包含了n个字符c
string(const string& s) 重点          拷贝构造
string s1;                //构造空的string类对象s1string s2("hello string");    //用C风格字符串构造string类对象s2string s3(s2);            //拷贝构造s3

 📂 string类对象的容量操作

46b6cf8bc8304be089e07124345df30b.png

1. size()

        size函数求的是字符串中元素的个数,不包含‘\0’。

//打印 5
string s("hello");
cout<<s.size()<<endl;

        其中length 和 size作用都是一样的,都是求有效字符串的字符长度,不包含 ‘\0’。size和length方法底层实现原理完全相同。引入size的原因是为了和其他容器接口保持一致。基本使用size。

2. reserve()

        reverse的作用就是为字符串预留空间,应用场景就是已知数据元素有多少,可以减少扩容的操作,减少消耗。

        但reserve()相当于手动扩容,但要注意的是,扩容量不能小于现有的容量。

    string  s;size_t cnt = s.capacity();cout << cnt << endl;cout<<"change:" << endl;for (int i = 0;i < 100;i++){s.push_back('a');if (cnt != s.capacity()){cout << s.capacity() << endl;cnt = s.capacity();}}

  8959243b79514a498db05f97e3a0144f.png

        以上是没有reserve的对象,第一次扩容两倍,之后是扩容1.5倍每次(vs是1.5倍扩容,Linux下按照2倍扩容)。

    string  s;s.reserve(100);size_t cnt = s.capacity();cout << cnt << endl;cout<<"change:" << endl;for (int i = 0;i < 100;i++){s.push_back('a');if (cnt != s.capacity()){cnt = s.capacity();cout << cnt << endl;}}

76ae8d032fa844fc8e7d51fa4370109b.png

        上图可知reseve的结果并不一定是准确的扩容数,可能会增加一些。

3. resize()

fd5cfaebfdbb48129b71f15ac22dcbd7.png

        resiz的功能是将有效字符的个数改成n;如果n大于有效字符个数,即n>size,则会插入;如果空间不够,即n>capacity,则会扩容+插入。当然传参没有char c则没有插入。

a0472b95a7344ece9b8f5cb577716288.png

 📂 string类对象的访问以及遍历操作53cbfa3de4c54b5f838ae2c2534c36ad.png

1. operator[ ]

8d0d5d06b8894d5498dfc3b08b75de88.png

        string类对象支持下标访问,[ ]支持读写pos位置的数据;const修饰为只读,不能修改。

//非const的对象使用[],可读可写
string s1("hello world");for(int i =0;i<s1.size();i++)
{s1[i] = 'a';
}for(int i=0;i<s1.size();i++)
{cout<<s1[i]<<' '<<endl;
}//const对象,只读
const string s2("hello world");
for(int i =0;i<s2.size();i++)
{cout<<s2[i]<<' '<<endl;
}

2. 迭代器 begin + end

        迭代器iterator,容器中类似与指针的东西,通过迭代器可以访问容器中的数据,使用方法也类似于指针。迭代器可能是指针,也可能不是。

        begin指向容器中第一个数据的位置;end指向容器中最后一个有效字符的下一个位置,即‘\0’( '\0'不算有效字符 )。

c501dc89adbf4b9eb59e346302bd0a54.png

31f9eae604264f03bd9f0167f9924950.png

        3601242138554ae385012930325f9ab3.png

string  s("hello world");for (string::iterator it = s.begin();it != s.end();it++)
{cout << *it << ' ';
}//打印 h e l l o  w o r l d

3. 迭代器 rbegin + rend

        rbegin就是reverse_begin的缩写,rbegin和rend主要用于逆序遍历。反向迭代器则是reverse_iterator. b27ad7dab610411ca76d3861e89667ac.png

379a62fdea0847dfa55a431c511bbb89.png

a6f25de948744222b636008eb1dfc728.png

string s("hello world");
for (string::reverse_iterator it = s.rbegin();it != s.rend();it++)
{cout << *it << ' ';
}

4. 范围for

        范围for的底层就是迭代器,将s的迭代器赋值给e(auto类型是编译器自动推导的数据类型)。

string  s("hello world");
for (auto e : s)
{cout << e << ' ';
}
cout << endl;

 📂 string类对象的修改操作

810008c5395c420c816d859acfee812b.png

1. push_back()

        尾部插入一个字符

//打印 hello w
string s("hello ");s.push_back('w');cout<<s<<endl;

2. append()2c9ea7a4c9e9406e9d73ac892bfc5197.png

        尾部插入一个字符串。

string s1("hello ");
s.append("world");
//打印 hello  worldstring s2("hello ");
s2.append(10, 'x');
//打印helloxxxxxxxxxxstring s3("hello ");
s3.append(s1.begin(),s1.end());
//打印hello hello world

3. operator+=

        尾部插入一个字符或者字符串。

5790d019892d4e2088de7605594ff040.png

string s1("hello ");
s1 += "world";string s2("aaaaa");
s2 += ' ';string s3("bbbbb");
s3 += s2;

4. insert()

        前面之前插入字符或者字符串。

c889e508d7984fbda77ca868f7f5195d.png

5. erase()

        删除从pos位置开始,len个字符,如果len没有传参赋初值,npos就代表着有多少删多少。

npos是string里面的一个静态成员变量static const size_t npos = -1; size_t是无符号整数,所以-1代表整数最大值。

51639864a48a4f56a5a2a45f5ab24c7b.png

        从pos位置开始,删除len个字符。或者从first迭代器开始,到last迭代器结束的字符删除。

string s("a bcd");
s.erase(0,1);
cout << s << endl;
//打印 bcd

6. replace()fbc3d5f790df44f889c01f4227581627.png

        将字符替换。

string s1("a bcd");
s1.replace(1,1,"a");
cout << s1 << endl;
//打印aabcstring s2("a bcd");
s2.replace(1,1,1,'a');
cout << s2 << endl;
//打印aabc

 insert,earse,replace等函数尽量少用,因为涉及数据元素的移动,效率太低。

5cc14a3430b541348fc2972e5e0bd43b.png

7. c_str()

        因为C++是要兼容C语言的,在C语言中,表示字符串使用char* 来表示的,所以C语言库中许多操作使用的是char* 来操作的。而在C++中,我们大多数使用的是string,那么如何将string类型转为C语言字符串类型呢?

        c_str()的作用就是从string中返回C格式字符串。

string filename("test.txt");
/*
FILE* file = fopen(filename,"r");
filename是string类型,而fopen函数的第一个参数类型是C格式字符串。
*/
FILE* file = fopen(filename.c_str(),"r");

8. find()bb80bcdcbcf246c3894ded0015662303.png

        find()作用就是查找字符或者字符串,从pos位置开始。默认情况下,pos位置是从0开始。

        rfind()作用与find几乎相同,不过是从字符串尾开始查找。

9. sub_str()

a978d148b9ef41aeba186d74d2d8ae3f.png

        在str中从pos位置开始,截取len个字符,将其作为字符串返回。如果len没有给或者大于npos(-1),含义则是从pos位置截取到字符串尾。

#include <iostream>
#include <string>int main ()
{std::string str="We think in generalities, but we live in details.";// (quoting Alfred N. Whitehead)std::string str2 = str.substr (3,5);     // "think"std::size_t pos = str.find("live");      // position of "live" in strstd::string str3 = str.substr (pos);     // get from "live" to the endstd::cout << str2 << ' ' << str3 << '\n';return 0;
}

📁 模拟实现string

        下面会有大量的string接口的模拟实现,模拟实现是为了更好的从里层理解string,使用string。

📂 拓展知识 :  编码

028e6539116b40fa82cc8b81324f4d7b.png

        常见的编码有:ASCII编码,GBK编码,UTF编码。

        所谓的编码,就是文字在计算机中的存储和表示。我们通过编码将计算机0 1 表示成日常生活中的文字。

        但随着越来越多国家的加入,简单的ASCII编码已经不能满足需求。所以有了UTF编码,UTF编码有UTF-8,UTG-16(2B),UTF-32(4B),它们主要的区别就是UTF-8是可变字节,utf-16和utf-32是不变字节。

        我们常用的string的底层就是使用utf-8的编码方式的char实例化的。

模拟实现string类,并完成测试namespace bit{class string{friend ostream& operator<<(ostream& _cout, const bit::string& s);friend istream& operator>>(istream& _cin, bit::string& s);public:typedef char* iterator;public:string(const char* str = "");string(const string& s);string& operator=(const string &s);~string();//// iteratoriterator begin();iterator end();/// modifyvoid push_back(char c);string& operator+=(char c);void append(const char* str);string& operator+=(const char* str);void clear();void swap(string& s);const char* c_str()const;/// capacitysize_t size()constsize_t capacity()constbool empty()constvoid resize(size_t n, char c = '\0');void reserve(size_t n);/// accesschar& operator[](size_t index);const char& operator[](size_t index)const;///relational operatorsbool operator<(const string& s);bool operator<=(const string& s);bool operator>(const string& s);bool operator>=(const string& s);bool operator==(const string& s);bool operator!=(const string& s);// 返回c在string中第一次出现的位置size_t find (char c, size_t pos = 0) const;// 返回子串s在string中第一次出现的位置size_t find (const char* s, size_t pos = 0) const;// 在pos位置上插入字符c/字符串str,并返回该字符的位置string& insert(size_t pos, char c);string& insert(size_t pos, const char* str);// 删除pos位置上的元素,并返回该元素的下一个位置string& erase(size_t pos, size_t len);private:char* _str;size_t _capacity;size_t _size;}};

📂 默认成员函数的模拟实现

//构造函数string(const char* str = ""):_size(strlen(str)){_str = new char[_size + 1];strcpy(_str, str);_capacity = _size;}//拷贝构造函数string(const string& s){string temp(s._str);swap(temp);}//赋值重载string& operator=(string temp){swap(temp);return *this;}//析构函数~string(){delete[] _str;_str = nullptr;_size = _capacity = 0;}

📂 iterator模拟实现

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

📂 insert 和 erase的模拟实现

//再字符串的pos位置插入字符string& insert(size_t pos, char ch){assert(pos <= _size);if (_size == _capacity){reserve(_capacity == 0? 4:2 * _capacity);}size_t end = _size + 1;while (end > pos){_str[end] = _str[end - 1];end--;}_str[end] = 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-1){_str[end] = _str[end - len];end--;}strncpy(_str + pos, str, len);_size += len;return *this;}//删除pos位置后len个元素string& erase(size_t pos=0, size_t len=npos){assert(pos < _size);if (len >= _size - pos || len == npos){_str[pos] = '\0';_size = pos;return *this;}else{strcpy(_str + pos, _str + pos + len);_size -= len;return *this;}}

📂 modify模拟实现

//modifyvoid swap(string& s){std::swap(this->_str, s._str);std::swap(this->_size, s._size);std::swap(this->_capacity, s._capacity);}const char* c_str() const{return _str;}void clear(){_size = 0;_str[_size] = '\0';}void push_back(char ch){//扩容2倍/*if (_size == _capacity){reserve(_capacity == 0 ? 4 : 2 * _capacity);}_str[_size] = ch;_size++;_str[_size] = '\0';*/insert(_size, ch);}void append(const char* str){//扩容/*size_t len = strlen(str);if(_size >= _capacity - len){reserve(_size + len);}strcpy(_str + _size, str);_size += len;*/insert(_size, str);}string& operator+=(char ch){push_back(ch);return *this;}string& operator+=(const char* str){append(str);return *this;}

📂 capacity模拟实现

//capacitysize_t size() const{return _size;}size_t capacity() const {return _capacity;}bool empty() const{return _size == 0;}void reserve(size_t n){if (n > _capacity){char* temp = new char[n + 1];strcpy(temp, _str);delete[] _str;_str = temp;_capacity = n;}}void resize(size_t n, const char ch = '\0'){if (n <= _size){_str[n] = '\0';_size = n;}else{reserve(n);for (size_t i = _size;i < n;i++){_str[i] = ch;}_str[n] = '\0';_size = n;}}

📂  relational operators的模拟实现

//relational operatorsbool operator<(const string& s){return strcmp(this->c_str(), s.c_str()) < 0;}bool operator<=(const string& s){return *this < s  || *this == s;}bool operator>(const string& s){return !(*this <= s);}bool operator>=(const string& s){return !(*this < s);}bool operator==(const string& s){return strcmp(this->c_str(), s.c_str()) == 0;}bool operator!=(const string& s){return !(*this == s);}

📂 find 的模拟实现

//返回字符c在字符串中出现的第一次位置size_t find(char ch, int pos = 0){assert(pos < _size);for (size_t i = pos;i < _size;i++){if (_str[i] == ch){return i;}}return npos;}//返回子串s在字符串中出现的第一次位置size_t find(const char* s, size_t pos = 0){assert(pos < _size);char* ps = strstr(_str + pos, s);if (ps != nullptr){return ps - _str;}else{return npos;}}

📂 substr的模拟实现

string substr(size_t pos=0, size_t len=npos){string temp;if (len == npos || _size - pos < len){for (size_t i = pos;i < _size;i++){temp += _str[i];}}else{for (size_t i = pos;i < pos + len;i++){temp += _str[i];}}return temp;}

📁 总结

        以上,我们就对string进行了全面的讲解,介绍了string的常用接口,string的底层实现,以及string相关的拓展知识。

        如果你能看到这里,恭喜你,你已经对string有了全面的了解,可以说已经上手了string。剩下的就是不断调试模拟实现string了,当然模拟实现只是为了更好的理解string。

        如果感觉本期内容对你有帮助,欢迎点赞,收藏,关注。Thanks♪(・ω・)ノ

相关文章:

【C++杂货铺】详解string

目录 &#x1f308;前言&#x1f308; &#x1f4c1; 为什么学习string &#x1f4c1; 认识string&#xff08;了解&#xff09; &#x1f4c1; string的常用接口 &#x1f4c2; 构造函数 &#x1f4c2; string类对象的容量操作 &#x1f4c2; string类对象的访问以及遍历操…...

算法刷题day20:二分

目录 引言概念一、借教室二、分巧克力三、管道四、技能升级五、冶炼金属六、数的范围七、最佳牛围栏八、套餐设计九、牛的学术圈I十、我在哪&#xff1f; 引言 这几天一直在做二分的题&#xff0c;都是上了难度的题目&#xff0c;本来以为自己的二分水平已经非常熟悉了&#x…...

【Spring云原生】Spring Batch:海量数据高并发任务处理!数据处理纵享新丝滑!事务管理机制+并行处理+实例应用讲解

&#x1f389;&#x1f389;欢迎光临&#x1f389;&#x1f389; &#x1f3c5;我是苏泽&#xff0c;一位对技术充满热情的探索者和分享者。&#x1f680;&#x1f680; &#x1f31f;特别推荐给大家我的最新专栏《Spring 狂野之旅&#xff1a;从入门到入魔》 &#x1f680; 本…...

docker ubuntu20.04 安装教程

ubuntu20.04 安装 docker 教程 本博客测试安装时间2023.8月 一、docker安装内容&#xff1a;docker Engine社区版 和 docker Compose 二、安装环境&#xff1a;ubuntu20.04 三、安装步骤&#xff1a; # 如果已经安装过docker&#xff0c;请先卸载&#xff0c;没安装则跳过…...

防御保护----IPSEC VPPN实验

实验拓扑&#xff1a; 实验背景&#xff1a;FW1和FW2是双机热备的状态。 实验要求&#xff1a;在FW和FW3之间建立一条IPSEC通道&#xff0c;保证10.0.2.0/24网段可以正常访问到192.168.1.0/24 IPSEC VPPN实验配置&#xff08;由于是双机热备状态&#xff0c;所以FW1和FW2只需要…...

音视频数字化(视频线缆与接口)

目录 1、DVI接口 2、DP接口 之前的文章【音视频数字化(线缆与接口)】提到了部分视频线缆,今天再补充几个。 视频模拟信号连接从莲花头的“复合”线开始,经历了S端子、色差分量接口,通过亮度、色度尽量分离的办法提高画面质量,到VGA已经到了模拟的顶峰,实现了RGB的独立…...

爬虫实战——巴黎圣母院新闻【内附超详细教程,你上你也行】

文章目录 发现宝藏一、 目标二、简单分析网页1. 寻找所有新闻2. 分析模块、版面和文章 三、爬取新闻1. 爬取模块2. 爬取版面3. 爬取文章 四、完整代码五、效果展示 发现宝藏 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不…...

mysql的语法总结2

命令&#xff1a; mysql -u 用户名 -p mysql登录 命令&#xff1a;create database u1 创建数据库u1 查询数据库 使用数据库u1 创建表department 查询表department ALTER TABLE 表名 操作类型&#xff1b; 操作类型可以有以下的操作&#xff1a; 添加列&#x…...

一度电竟然可以做这么多事情!

一度电竟然可以做这么多事情&#xff01;&#xff01;&#xff01; 一度电可以让手机充电100多次&#xff1b; 一度电可以生产医用口罩100个&#xff1b; 一度电可以让节能灯点亮九十个小时&#xff1b; 一度电可以让电视播放10小时&#xff1b; 一度电可以让冰箱运作36个小…...

【Go】golang值交换,指针

package mainimport "fmt"func swap(a *int, b *int) int {var o into *a*a *b*b oreturn o}func main() {var a int 1var b int 2swap(&a, &b)fmt.Println(a, b) }这个函数接受两个整数指针作为参数&#xff0c;然后通过指针操作&#xff0c;交换它们所…...

共享WiFi软件哪家强?2024年共享wifi项目排名为你揭晓!

共享WiFi软件在如今的智能手机时代已经成为人们生活中不可或缺的一部分。随着移动互联网的飞速发展&#xff0c;人们对于随时随地都能够连接到网络的需求也日益增长。为了满足这一需求&#xff0c;共享经济应运而生&#xff0c;而在众多共享产品中&#xff0c;共享WiFi软件也逐…...

Hudi入门

一、Hudi编译安装 1.下载 https://archive.apache.org/dist/hudi/0.9.0/hudi-0.9.0.src.tgz2.maven编译 mvn clean install -DskipTests -Dscala2.12 -Dspark33.配置spark与hudi依赖包 [rootmaster hudi-spark-jars]# ll total 37876 -rw-r--r-- 1 root root 38615211 Oct …...

LORA: LOW-RANK ADAPTATION OF LARGE LAN-GUAGE MODELS

TOC 1 前言2 方法2.1 LOW-RANK-PARAMETRIZED UPDATE MATRICES 1 前言 1) 提出背景 大模型时代&#xff0c;通常参数都是上亿级别的&#xff0c;若对于每个具体任务都要去对大模型进行全局微调&#xff0c;那么算力和资源的浪费是巨大的。 根据流形学习思想&#xff0c;对于数…...

使用Pytorch导出自定义ONNX算子

在实际部署模型时有时可能会遇到想用的算子无法导出onnx&#xff0c;但实际部署的框架是支持该算子的。此时可以通过自定义onnx算子的方式导出onnx模型&#xff08;注&#xff1a;自定义onnx算子导出onnx模型后是无法使用onnxruntime推理的&#xff09;。下面给出个具体应用中的…...

unity-urp:视野雾

问题背景 恐怖游戏在黑夜或者某些场景下&#xff0c;需要用雾或者黑暗遮盖视野&#xff0c;搭建游戏氛围 效果 场景中&#xff0c;雾会遮挡场景和怪物&#xff0c;但是在玩家视野内雾会消散&#xff0c;距离玩家越近雾越薄。 当前是第三人称视角&#xff0c;但是可以轻松的…...

Spring Cloud Gateway介绍及入门配置

Spring Cloud Gateway介绍及入门配置 概述&#xff1a; Gateway是在Spring生态系统之上构建的API网关服务&#xff0c;基于Spring6&#xff0c;Spring Boot 3和Project Reactor等技术。它旨在为微服务架构提供一种简单有效的统一的 API 路由管理方式&#xff0c;并为它们提供…...

Thingsboard本地源码部署教程

本章将介绍ThingsBoard的本地环境搭建&#xff0c;以及源码的编译安装。本机环境&#xff1a;jdk11、maven 3.6.2、node v12.18.2、idea 2023.1、redis 6.2 环境安装 开发环境要求&#xff1a; Jdk 11 版本 &#xff1b;Postgresql 9 以上&#xff1b;Maven 3.6 以上&#xf…...

【MySQL 系列】MySQL 起步篇

MySQL 是一个开放源代码的、免费的关系型数据库管理系统。在 Web 开发领域&#xff0c;MySQL 是最流行、使用最广泛的关系数据库。MySql 分为社区版和商业版&#xff0c;社区版完全免费&#xff0c;并且几乎能满足全部的使用场景。由于 MySQL 是开源的&#xff0c;我们还可以根…...

C++的成员初始化列表

C的成员构造函数初始化列表&#xff1a;构造函数中初始化类成员的一种方式&#xff0c;当我们编写一个类并向该类添加成员时&#xff0c;通常需要某种方式对这些成员变量进行初始化。 建议应该在所有地方使用成员初始化列表进行初始化 成员初始化的方法 方法一&#xff1a; …...

为什么TikTok视频0播放?账号权重提高要重视

许多TikTok账号运营者都会遇到一个难题&#xff0c;那就是视频要么播放量很低&#xff0c;要么0播放&#xff01;不管内容做的多好&#xff0c;最好都是竹篮打水一场空&#xff01;其实你可能忽略了一个问题&#xff0c;那就是账号权重。下面好好跟大家讲讲这个东西&#xff01…...

铭豹扩展坞 USB转网口 突然无法识别解决方法

当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…...

uniapp中使用aixos 报错

问题&#xff1a; 在uniapp中使用aixos&#xff0c;运行后报如下错误&#xff1a; AxiosError: There is no suitable adapter to dispatch the request since : - adapter xhr is not supported by the environment - adapter http is not available in the build 解决方案&…...

ios苹果系统,js 滑动屏幕、锚定无效

现象&#xff1a;window.addEventListener监听touch无效&#xff0c;划不动屏幕&#xff0c;但是代码逻辑都有执行到。 scrollIntoView也无效。 原因&#xff1a;这是因为 iOS 的触摸事件处理机制和 touch-action: none 的设置有关。ios有太多得交互动作&#xff0c;从而会影响…...

学习STC51单片机32(芯片为STC89C52RCRC)OLED显示屏2

每日一言 今天的每一份坚持&#xff0c;都是在为未来积攒底气。 案例&#xff1a;OLED显示一个A 这边观察到一个点&#xff0c;怎么雪花了就是都是乱七八糟的占满了屏幕。。 解释 &#xff1a; 如果代码里信号切换太快&#xff08;比如 SDA 刚变&#xff0c;SCL 立刻变&#…...

nnUNet V2修改网络——暴力替换网络为UNet++

更换前,要用nnUNet V2跑通所用数据集,证明nnUNet V2、数据集、运行环境等没有问题 阅读nnU-Net V2 的 U-Net结构,初步了解要修改的网络,知己知彼,修改起来才能游刃有余。 U-Net存在两个局限,一是网络的最佳深度因应用场景而异,这取决于任务的难度和可用于训练的标注数…...

微服务通信安全:深入解析mTLS的原理与实践

&#x1f525;「炎码工坊」技术弹药已装填&#xff01; 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 一、引言&#xff1a;微服务时代的通信安全挑战 随着云原生和微服务架构的普及&#xff0c;服务间的通信安全成为系统设计的核心议题。传统的单体架构中&…...

sshd代码修改banner

sshd服务连接之后会收到字符串&#xff1a; SSH-2.0-OpenSSH_9.5 容易被hacker识别此服务为sshd服务。 是否可以通过修改此banner达到让人无法识别此服务的目的呢&#xff1f; 不能。因为这是写的SSH的协议中的。 也就是协议规定了banner必须这么写。 SSH- 开头&#xff0c…...

React从基础入门到高级实战:React 实战项目 - 项目五:微前端与模块化架构

React 实战项目&#xff1a;微前端与模块化架构 欢迎来到 React 开发教程专栏 的第 30 篇&#xff01;在前 29 篇文章中&#xff0c;我们从 React 的基础概念逐步深入到高级技巧&#xff0c;涵盖了组件设计、状态管理、路由配置、性能优化和企业级应用等核心内容。这一次&…...

AD学习(3)

1 PCB封装元素组成及简单的PCB封装创建 封装的组成部分&#xff1a; &#xff08;1&#xff09;PCB焊盘&#xff1a;表层的铜 &#xff0c;top层的铜 &#xff08;2&#xff09;管脚序号&#xff1a;用来关联原理图中的管脚的序号&#xff0c;原理图的序号需要和PCB封装一一…...

CSS3相关知识点

CSS3相关知识点 CSS3私有前缀私有前缀私有前缀存在的意义常见浏览器的私有前缀 CSS3基本语法CSS3 新增长度单位CSS3 新增颜色设置方式CSS3 新增选择器CSS3 新增盒模型相关属性box-sizing 怪异盒模型resize调整盒子大小box-shadow 盒子阴影opacity 不透明度 CSS3 新增背景属性ba…...