C++修炼:string类的使用

        Hello大家好!很高兴我们又见面啦!给生活添点passion,开始今天的编程之路!

我的博客:<但凡.

我的专栏:《编程之路》、《数据结构与算法之美》、《题海拾贝》、《C++修炼之路》

欢迎点赞,关注!

1、string类初识

         <string> 是 C++ 标准库中用于处理字符串的头文件。我们可以用string提供的丰富的接口来实现各种各样的字符串操作。string类的底层其实就是顺序表,只不过在存储字符的同时还多存储了一个‘\0’。再后续的使用讲解中大家会感受到string的强大。

        使用string类需要包含头文件:

#include<iostream>
#include<string>

         好的现在我尽量用最直白的语言告诉大家为什么这个string类非常方便。

#include<iostream>
#include<string>
using namespace std;
int main()
{string s="Hello World!";cout << s;
}

        我们创建了一个helloworld字符串,并且把他打印了出来。现在的字符串就像int, char一样是一个类型,我们不需要再去像C语言一样再去创建字符数组啊什么什么的。但是不仅如此,string类提供了非常多的接口,所以我们可以随便的在这个字符串中增删查改。具体怎么增删查改,我们继续往下看。

2、迭代器

        我们可以把迭代器理解成和指针差不多的东西。因为我们想访问它都得解引用。

        对于迭代器类型的接收我们可以使用auto,auto可以自动识别变量的类型。但需要注意的是auto这个东西不推荐多用,因为很可能会识别错误。

auto不能作为函数的参数,可以做返回值,但是建议谨慎使用 。auto不能直接用来声明数组

        这些都是string类中返回迭代器的接口,我们一个一个来介绍:

2.1、begin和end

         begin是返回该字符串中第一个字符位置的迭代器,end是返回该字符串最后一个字符位置的下一位的迭代器(也就是‘\0’的位置)。我们可以使用begin和end对字符串进行遍历:

#include<iostream>
#include<string>
using namespace std;
int main()
{string s="Hello World!";auto it1 = s.begin();auto it2 = s.end()-1;while (it1 != it2){cout << *it1 << " ";it1++;}
}

输出结果:

         注意我们这里没让他输出感叹号!

        有几个细节需要提一下:第一,我们的迭代器是支持+-操作的,+就是让迭代器挪到下一个位置,-与+相反。

第二,我们迭代器的比较其实是非常严格的,所以尽量使用 != 和== 来比较。

 2.2、rbegin和rend

        这个rbegin和rend就有意思了啊,它实际上就是和begin和end进行了一个对调,rbegin返回的是整个字符串最后一个字符的位置,而rend返回的是第一个字符的位置的前一个。但需要注意,++begin其实是往前走,向前遍历。也就是说我们现在从字符串最后向前是正方向。

#include<iostream>
#include<string>
using namespace std;
int main()
{string s="Hello World!";auto it1 = s.rbegin();auto it2 = s.rend();while (it1 != it2){cout << *it1 << " ";it1++;}
}

         需要注意一点,我们不能执行rbegin-1的操作,因为rbegin-1这个位置虽然物理内存上是存在的,但是对于反向迭代器来说是不合法的,属于越界访问。

2.3、cbegin、cend、crbegin、crend

        这四个迭代器其实和上面我们介绍过的四个指向的位置没有区别,但是他们迭代器的类型变成了const_iterator。也就是说,我们迭代器指向的这一块内存存放的内容是不可以被修改的。

#include<iostream>
#include<string>
using namespace std;
int main()
{string s = "Hello World!";auto it1 = s.begin();(*it1)++;auto it2 = s.cbegin();(*it2)++;//报错:表达式必须是可修改的左值
}

        实际上后面四个我们不常用。

        如果我们在不使用auto的情况接收以下两种情况的迭代器,必须使用const_iterator:

void test(const string& s)
{string::const_iterator it = s.begin();string p = "asd";string::const_iterator it2 = p.cbegin();
}

       注意以下两串代码表达的意思并不相同,第一个是指迭代器的指向不能改变,也就是不能执行it2++这样的操作,而第二个是迭代器的指向的内容不能被修改。

	const string::iterator it2 = p.begin();string::const_iterator it = p.begin();

 3、capacity

以下是我们这一部分要介绍的接口:

3.1、size、length和max_size

        其实这两个接口都是返回字符串的长度。size()是为了和后面STL里面其他容器的接口一致而后设计出来的。我们一般使用size,不使用length。

        max_length就是返回我们这个字符串能够容纳的最大长度。

#include<iostream>
#include<string>
using namespace std;int main()
{//两种定义string的方式string s = "Hello World!";//隐式类型转换string s1("abc");cout << s.size() << endl;//包含空格cout << s1.size()<< endl;cout << s1.length() << endl;cout << s.max_size() << endl;//输出2147483647
}

输出结果:

 3.2、resize

        resize可以将字符串大小调整为 n 个字符的长度。

        如果n小于当前字符串的长度,就会对该字符串进行截取,如果n大于当前字符串的长度,多余的位置用我们指定的字符串进行补充。如果没有指定就用\0补充。

#include<iostream>
#include<string>
using namespace std;int main()
{//两种定义string的方式string s = "Hello World!";//隐式类型转换s.resize(5);cout << s << endl;s.resize(50);cout << s << endl;s.resize(100, 'c');cout << s << endl;
}

输出结果:

 

 3.3、capacity

        capacity可以返回当前为字符串分配的存储空间的大小,以字节表示。

#include<iostream>
#include<string>
using namespace std;int main()
{string s = "Hello World!";cout << s.capacity() <<endl;
}

输出结果:

 

        现在我们可以把capacity用来观察编译器对string容量的自动扩容。

#include<iostream>
#include<string>
using namespace std;int main()
{string s = "Hello World!";for (int i = 1;i <= 10;i++){s += "ssssssssss";//每次尾插10个字符cout << s.capacity() << endl;}
}

输出结果:

 

3.4、reserve

        reserve根据计划的大小更改调整字符串容量,长度最多为 n 个字符。如果我们给的容量小于当前容量,他并不会缩小容量。这意味着他不会改变当前字符串的内容。但我说的不会缩小是针对我是用的编译器vs2022来说的,不同环境下可能有不同的结果,可能缩也可能不缩。

        但需要注意的是,如果给的大小大于当前的容量,他也不会严格按照你给的容量进行扩容,由于底层内存对齐规则和编译器的优化(这不在讨论的范围内),他只会大于或等于你要求他扩容到的大小。

#include<iostream>
#include<string>
using namespace std;int main()
{string s = "Hello World!";cout << s.capacity() << endl;//15s.reserve(5);cout << s.capacity() << endl;//15s.reserve(20);cout << s.capacity() << endl;//31s.reserve(40);cout << s.capacity() << endl;//47
}

 输出结果:

        所以说这个东西大家尽量别用,很可怕,用户对于容量的可控性很低。

3.5、clear和empty

        clear可以情况当前串,使它变成空串,而empty可以判断当前串是不是空串。

#include<iostream>
#include<string>
using namespace std;int main()
{string s = "Hello World!";cout << s.empty() << endl;//0s.clear();cout << s.empty() << endl;//1
}

输出结果:

 

4、Element access

        这里我们介绍几种接口用来访问元素。

4.1、方括号

        首先是最常用的方括号访问元素。这里的访问我们就把字符串看成一个下标从0开始的字符数组就好。

#include<iostream>
#include<string>
using namespace std;int main()
{string s = "Hello World!";cout << s[0] << endl;cout << s[12] << endl;//访问'\0
}

输出结果: 

4.2、at

        at也可以访问特定下标的元素:

#include<iostream>
#include<string>
using namespace std;int main()
{string s = "Hello World!";cout << s[0] << endl;cout << s[12] << endl;//访问'\0cout << s.at(0) << endl;cout << s.at(4) << endl;
}

输出结果:

 

        需要注意,方括号访问越界是直接断言报错,而at访问越界是抛异常(我们之前介绍过异常)。但是只有debug版本才会断言报错,realease版本断言就被忽略了。

 4.3、back和front

        这两个C++11新增的接口就是返回字符串首尾元素,没啥好说的、

#include<iostream>
#include<string>
using namespace std;int main()
{string s = "Hello World!";cout << s.front() << endl;cout<<s.back()<<endl;
}

输出结果:

 

 5、Modifiers

        这里我们介绍几个修改我们字符串的接口。

         

5.1、+=,insert和erase

        之所以先介绍这三个,是因为这三个使我们最常用的。

        首先来说+=,这个+=就是运算符重载了,可以支持我们的字符串相加:

#include<iostream>
#include<string>
using namespace std;int main()
{string s = "Hello";s += " World!";cout<<s<<endl;
}

输出结果:

 

         接下来再来看insert,他可以支持我们在字符串中任意位置插入数据:

        我们可以看一下,他支持了这么多函数重载。 现在我们挑几个来实验一下:

#include<iostream>
#include<string>
using namespace std;int main()
{string s = "Hello";s.insert(0, 1, '*');//在下标为0,传入1个字符,内容为*cout<<s<<endl;s.insert(s.begin(), '&');//在begin迭代器指向的位置插入&cout << s << endl;s.insert(5, "pppppp");//从下标为5的位置插入字符串//注意下标为5的位置被改变了cout << s << endl;
}

输出结果:

 

         erase支持我们在指定的位置进行删除。

 使用案例:

#include<iostream>
#include<string>
using namespace std;int main()
{string s = "Hello";s.erase(s.begin());//删掉迭代器指向位置的cout << s << endl;s.erase(0, 2);//从下标0开始,删掉两个字符cout << s << endl;s.erase(0, string::npos);//从下标0开始,删掉npos个字符,实际上就删完了,我们后面会介绍nposcout << s << endl;s += "yyy";s.erase(s.begin(), s.end());//删除所有字符cout << s << endl;
}

输出结果:

 5.2、append

        append可以在字符串末尾追加字符串。他既可以追加string字符串,也可以追加c风格字符串还可以追加多个字符,甚至还支持追加迭代器范围内的字符。

#include<iostream>
#include<string>
using namespace std;int main()
{string s = "Hello";s.append("ssss");//追加c风格string s1 = "***";s.append(s1);s.append(10, '@');//追加多个字符s.append(s.begin(), s.end());//相当于把这个字符串复制一遍加上去cout << s << endl;
}

输出结果:

5.3、push_back

        这个也是尾插,没啥好说的。 但是这个只能插入单个字符。

#include<iostream>
#include<string>
using namespace std;int main()
{string s = "Hello";s.push_back('H');cout << s << endl;
}

 5.4、assign

        assign可以以多种方式替换字符串的内容。

 使用案例:

#include<iostream>
#include<string>
using namespace std;int main()
{string s = "Hello";string s1("ppp");s.assign(s1);//另一串赋值cout << s << endl;s.assign("sssss");//c风格字符串cout << s << endl;s.assign(10,'o');//多个字符cout << s << endl;s.assign("*********", 2, 4);//从给定的string串下标2开始以后的4个字符进行替换cout << s << endl;string s2 = "666";s.assign(s1.begin(), s1.end());//迭代器cout << s << endl;
}

输出结果:

 

5.5、replace

        这个replace也是替换,但是他更灵活,我们可以自己指定需要替换的范围。在这我就简单列举几个例子:

#include<iostream>
#include<string>
using namespace std;int main()
{string s = "Hello";string s1("ppp");s.replace(2,3,s1);//从2开始替换3个字符为s1cout << s << endl;s.replace(2, 3,"sssss");//c风格字符串cout << s << endl;s.replace(2,10,5,'o');//从2开始以后10个字符替换为5个'o’cout << s << endl;
}

输出结果:

         replace要谨慎使用因为如果替换的长度不对等他需要自己挪动数据,消耗时间。

 5.6、swap

        这个就是单纯的替换,没啥好说的。但需要注意的是这个交换是string特有的只能交换字符串的浅拷贝,效率比算法库自带的swap更高。下一篇我们还会展开说这个地方。

#include<iostream>
#include<string>
using namespace std;int main()
{string s = "Hello";string s1("ppp");s.swap(s1);cout << s << endl;
}

 

5.7、pop_back

        pop_back可以删除最后一个字符 (注意不是‘\0’)。

#include<iostream>
#include<string>
using namespace std;int main()
{string s = "Hello";s.pop_back();cout << s << endl;
}

输出结果: 

        好了这部分也算是讲完了。大家应该可以感受得到,实际上string类在这地方设计的还是比较冗余的,有很多功能都是重复的。 

6、string operations

 6.1、c_str、data和copy

        这个主要是让我们的string类型字符串以c风格返回。

#include<iostream>
#include<string>
using namespace std;int main()
{string s = "Hello";cout << s.c_str() << endl;
}

输出结果:

        data的作用和c_str类似,但是在不同的标准中有一些区别。这个不过多说了因为不常用。

        copy可以将string串中的字符拷贝到字符数组中,但是必须手动添加终止符:

#include<iostream>
#include<string>
using namespace std;int main()
{string s = "Hello";char s1[100] = " ";s.copy(s1,s.size());s1[5] = '\0';cout << s1 << endl;
}

 输出结果:

 6.2、find和rfind

        这个是比较常用的,他可以支持我们以多种方式查找string串中出现的字符或字符串。

#include<iostream>
#include<string>
using namespace std;int main()
{string s = "Hello***&&&@@";cout << s.find('*', 0) << endl;//5cout << s.find("*&", 0) << endl;//支持C风格字符串查找cout << s.find("9", 0) << endl;//未找到返回nposcout << s.find("*&#",0,2) << endl;//指定要查找我给定的C风格字符串的前两个字符
}

输出结果:

        对于find来说,只要没找到,就返回npos,也就是字符串能容纳下的最大长度。

        rfind就是倒着往前找,但需要注意的是如果我们想让他查找完全整个串的话我给给定的应该是从最后一个字符得下标开始查找

#include<iostream>
#include<string>
using namespace std;int main()
{string s = "Hello***&&&@@";cout << s.rfind('*', 12) << endl;cout << s.rfind("*&", 12) << endl;//支持C风格字符串查找cout << s.rfind("9", 12) << endl;//未找到返回nposcout << s.rfind("*&#",12,2) << endl;//指定要查找我给定的C风格字符串的前两个字符
}

 输出结果:

 6.3、find_first_of和find_last_of

        find_first_of可以查找整个串中从前往后第一次出现这个字符或者给定的字符串中任意一个字符的位置。他经常用于检验这个字符串中是否包含某个特定字符。他和find的区别就是,就算给定的串与string串不完全匹配也没关系,只要包含其中的一个字符就好。

#include<iostream>
#include<string>
using namespace std;int main()
{string s = "Hello***&&&@@";cout << s.find_first_of('*', 0) << endl;cout << s.find_first_of("*&", 0) << endl;//支持C风格字符串查找cout << s.find_first_of("9", 0) << endl;//未找到返回nposcout << s.find_first_of("*&#", 0,2) << endl;//指定要查找我给定的C风格字符串的前两个字符
}

 输出结果:

 

        find_last_of就是和find_first_of反过来到这往前找而已,没啥好说的。

 6.4、find_first_not_of和find_last_not_of

        这两个其实就是字面意思,查找第一个不是该字符或字符串的位置。一个是从前往后找,一个是从后往前找。

#include<iostream>
#include<string>
using namespace std;int main()
{string s = "Hello***&&&@@";cout << s.find_first_not_of('H', 0) << endl;//cout << s.find_first_not_of("*&", 0) << endl;//支持C风格字符串查找cout << s.find_first_not_of("9", 0) << endl;//未找到返回nposcout << s.find_first_not_of("*&#", 0,2) << endl;//指定要查找我给定的C风格字符串的前两个字符
}

 输出结果:

 6.5、substr

        substr可以截取规定区域的字符串。但需要注意的是substr并不会改变原字符串。

#include<iostream>
#include<string>
using namespace std;int main()
{string s = "Hello***&&&@@";cout << s.substr(0,5) << endl;
}

输出结果:

 6.6、compare

        compare就是字符串比较,和C语言里面的strcmp差不多的道理,都是字典序进行排序。

#include<iostream>
#include<string>
using namespace std;int main()
{//大写字母ASCII码比小写字母小//按照字典序排序string s = "Hello";cout << s.compare("Assaa") << endl;string s1 = "Hello";cout << s.compare(s1) << endl;cout << s.compare(0, 3, s1) << endl;//s的0到3个字符和s1作比较cout << s.compare(0, 3, s1, 0, 3) << endl;//s的0到3个字符和s1的0到3个字符作比较}

输出结果:

        返回1表示s大于我们传入的字符串,0表示相等,-1表示s小于我们传入的字符串。

 7、getline

        getline就是读取当前这一行。什么意思?我们的scanf和cin都不能读取包含有空格的字符串,所以我们得用getline读取这一行能够读取空格。

#include<iostream>
#include<string>
using namespace std;int main()
{//输入hello worldstring s;cin >> s;//hellocin.ignore(256, '\n');//刷新缓冲区,把剩下的world清掉string s2;getline(cin,s2);cout << s << endl;cout << s2 << endl;
}

 输出结果:

        好了,今天的内容就分享到这,我们下期再见!

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/75856.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【go微服务】如何快速掌握grpc开发

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…

【区块链 + 文化版权】基于 FISCO BCOS 的方言大数据语料库 | FISCO BCOS 应用案例

苏州喵自在区块链科技有限公司打造的基于FISCO BCOS 的粤语大数据语料库&#xff0c; 旨在利用区块链技术保护和发展粤语文化遗产。该项目利用区块链的不可篡改性、分布式存储、智能合约和激励机制等特性&#xff0c; 为保护非物质文化遗产&#xff0c; 加强粤语研究与教育和开…

大模型在支气管扩张预测及治疗方案制定中的应用研究

目录 一、引言 1.1 研究背景与意义 1.2 研究目的与方法 1.3 国内外研究现状 二、大模型技术概述 2.1 大模型的基本原理与架构 2.2 适用于支气管扩张预测的大模型类型及特点 2.3 大模型在医疗领域的应用现状与优势 三、支气管扩张的相关医学知识 3.1 支气管扩张的病因…

亚马逊云科技提供完全托管的DeepSeek-R1模型

近日&#xff0c;亚马逊云科技宣布在Amazon Bedrock上线完全托管的DeepSeek-R1模型。DeepSeek是首个登陆Amazon Bedrock的国产大模型&#xff0c;自今年1月底推出以来&#xff0c;已有数千客户使用Amazon Bedrock的自定义模型导入功能部署了DeepSeek-R1模型。 DeepSeek在过去几…

二叉树、排序算法与结构图

二叉树、排序算法与数据库 二叉树 二叉树的性质 节点数与深度的关系&#xff1a;深度为 k k k的二叉树&#xff0c;最多有 2 k − 1 2^k - 1 2k−1个节点。例如&#xff0c;深度为 3 3 3的二叉树&#xff0c;最多有 2 3 − 1 7 2^3 - 1 7 23−17个节点。叶子节点与度为2节…

vmwaretools解压失败|vmware tools distrib cannot mkdir read only file system|bug汇总

最简单的一条路线&#xff1a;你的解压命令用sudo了吗&#xff1f; 这个方法不能解决的话就看下面内容。本文提供给你全过程思路。 如需转载&#xff0c;标记出处 背景&#xff1a; 之前虚拟机和主机的复制黏贴还能用&#xff0c;今天突然用不了&#xff0c;重新下载安装包&am…

jEasyUI 创建自定义视图

jEasyUI 创建自定义视图 引言 jEasyUI 是一款流行的 jQuery UI 组件库&#xff0c;它提供了丰富的 UI 组件和交互效果&#xff0c;极大地简化了 Web 开发的复杂度。在 jEasyUI 中&#xff0c;我们可以通过自定义视图来扩展其功能&#xff0c;满足特定的业务需求。本文将详细介…

Spring MVC配置详解:从历史到实战

文章目录 一、Java Web的发展历程1.Model I与Model II开发模式&#xff08;1&#xff09; Model I开发模式&#xff08;2&#xff09;Model II开发模式 2.MVC设计模式Spring MVC本质MVC工作流程 二、Spring MVC快速入门实战1.环境搭建步骤&#xff08;1&#xff09;创建Maven W…

老是忘记package.json,备忘一下 webpack 环境下 Vue Cli 和 Vite 命令行工具对比

Vue 2.X webpack 环境下 Vue Cli 的命令 "scripts": {"dev": "vue-cli-service serve","prod": "vue-cli-service serve --mode production","build:dev": "vue-cli-service build --mode development"…

【树莓派Pico FreeRTOS】-Mutex(互斥体)

Mutex(互斥体) 文章目录 Mutex(互斥体)1、硬件准备2、软件准备3、FreeRTOS的Mutex介绍4、完整示例RP2040 由 Raspberry Pi 设计,具有双核 Arm Cortex-M0+ 处理器和 264KB 内部 RAM,并支持高达 16MB 的片外闪存。 广泛的灵活 I/O 选项包括 I2C、SPI 和独特的可编程 I/O (P…

sock文件介绍--以mysql.sock为例

socket 文件 (.sock) 通常是临时文件。 MySQL 的 socket 文件是临时文件&#xff0c;只在服务运行时有效。可通过配置文件更改 socket 文件的存放路径&#xff0c;常见路径如 /tmp/mysql.sock 或指定自定义目录。如果连接出现问题&#xff0c;可能需要检查 MySQL 服务状态或路…

Docker应用部署之mysql篇(day5)

文章目录 前言一、问题描述二、解决方案1. 搜索 MySQL 镜像2. 拉取 MySQL 镜像3. 创建并运行 MySQL 容器参数说明&#xff1a; 4. 验证容器是否运行5. 进入 MySQL 容器 三、总结 前言 在日常开发和部署中&#xff0c;MySQL 是最常用的关系型数据库之一。借助 Docker&#xff0…

【Elasticsearch基础】基本核心概念介绍

Elasticsearch作为当前最流行的分布式搜索和分析引擎&#xff0c;其强大的功能背后是一套精心设计的核心概念体系。本文将深入解析Elasticsearch的五大核心概念&#xff0c;帮助开发者构建坚实的技术基础&#xff0c;并为高效使用ES提供理论支撑。 1 索引&#xff08;Index&…

Qt在ARM中,如何使用drmModeObjectSetProperty 设置 Plane 的 zpos 值

在 Qt 中直接使用 drmModeObjectSetProperty 设置 Plane 的 zpos 值需要结合 Linux DRM/KMS API 和 Qt 的底层窗口系统&#xff08;如 eglfs 平台插件&#xff09;。以下是详细步骤和代码示例&#xff1a; 1. 原理说明 DRM/KMS 基础&#xff1a; Plane&#xff1a;负责图层合成…

MFC添加免费版大漠3.1233

先创建一个MFC工程&#xff0c; 添加dm.dll 方法一&#xff1a;通过类向导-添加类-类型库中的MFC类-文件&#xff0c;选择dm.dll&#xff0c;如果没有"添加类型库中的MFC类"选项就用方法二添加 方法二&#xff1a;添加-新建项-MFC-Active或TypeLib-实现接口位置选…

【Linux】应用层协议 HTTP

应用层协议 HTTP 一. HTTP 协议1. URL 地址2. urlencode 和 urldecode3. 请求与响应格式 二. HTTP 请求方法1. GET 和 POST (重点) 三. HTTP 状态码四. HTTP 常见报头五. 手写 HTTP 服务器 HTTP&#xff08;超文本传输协议&#xff09;是一种应用层协议&#xff0c;用于在万维网…

【活动回顾】StarRocks Singapore Meetup #2 @Shopee

3 月 13 日&#xff0c;StarRocks 社区在新加坡成功举办了第二场 Meetup 活动&#xff0c;主题为“Empowering Customer-Facing Analytics”。本次活动在 Shopee 新加坡办公室举行&#xff0c;吸引了来自 Shopee、Grab 和 Pinterest 的专家讲师以及 50 多位参会者。大家围绕电商…

Retinexformer:基于 Retinex 的单阶段 Transformer 低光照图像增强方法

开头发点牢骚&#xff1a;本来做的好好都都要中期了&#xff0c;导师怎么突然给我换题目啊。真是绷不住了......又要从头开始学了&#xff0c;唉&#xff01; 原论文链接&#xff1a;Retinexformer: One-stage Retinex-based Transformer for Low-light Image Enhancement 低光…

后端——AOP异步日志

需求分析 在SpringBoot系统中&#xff0c;一般会对访问系统的请求做日志记录的需求&#xff0c;确保系统的安全维护以及查看接口的调用情况&#xff0c;可以使用AOP对controller层的接口进行增强&#xff0c;作日志记录。日志保存在数据库当中&#xff0c;为了避免影响接口的响…

flink广播算子Broadcast

文章目录 一、Broadcast二、代码示例三.或者第二种(只读取一个csv文件到广播内存中)提示:以下是本篇文章正文内容,下面案例可供参考 一、Broadcast 为了关联一个非广播流(keyed 或者 non-keyed)与一个广播流(BroadcastStream),我们可以调用非广播流的方法 connect(),…