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

STL中的string容器和迭代器iterator

前言这一片博客开始我们进入STL标准模板库的学习什么是STLSTLStandard Template Library是C标准库的核心组成部分提供了一系列通用模板类和函数实现了常见的数据结构和算法。它基于泛型编程思想强调代码复用和高效性。STL的版本STL的六大组件就像上图所示的一样STL中一共有六大组件分别是仿函数、算法、迭代器、空间配置器、容器、配接器今天我们主要来讲一下容器中的string和迭代器中的iterator、const_iteratorSTL中的容器stringstring - C Reference (cplusplus.com)上面这个链接是C的一个文档网站里面有C中相关的所有内容这里我们可以看到string其实就是一个类而且是一个字符串类型的类string的构造函数这就是string的构造函数这里主要的是要去掌握1、2、4具体的3、5可以做一个了解因为没有前面三个常用// string 是 basic_stringchar 的重命名 typedef basic_stringchar string; basic_stringchar s; int main() { //string(); string s1; s1 hello world; //string(const string str) string s2(s1); string s3 s2;//调用拷贝函数 //string(const char* s) string s4(hello world); //字符串类型可以直接用来打印和输入 //string类中有对的重载 cout s1 endl; cout s2 endl; cout s3 endl; cout s4 endl; return 0; }int main() { //string(const string str, size_t pos, size_t len npos) //第三个是缺省值要是你不输入他会默认给一个-1size_t的-1就是一个很大的数字了大约是42亿bit~4G左右 string s1(hello world); string s2(s1, 1, 9); cout s2 endl; //string(const char* s, size_t n) //这个构造函数的使用方式是从第一个参数的第一个字符开始拷贝拷贝n个字符结束 //第一个参数必须得是字符串不能是字符串对象 //否则就会调用string(const string str, size_t pos, size_t len npos)这个构造函数 string s3(hello world, 5); cout s3 endl; return 0; }以上是这几个常用的构造函数创建对象的方式这里在对npos说明一下这是string类模版中的静态常量size_tnpos -1 这会使的npos是一个非常大的值这个值足以应付我们正常的字符串拷贝stirng中size()、lenght()的使用int main() { string s1(hello world); size_t _size s1.size();//size()和lenght()的返回值都是size_t类型的数据 cout _size endl; cout s1.size()endl; cout s1.length() endl; return 0; }size()、length()俩者没有任何区别你想使用哪一个都可以作用就是计算该字符串对象中字符串的长度string中[ ]的使用int main() { string s1(hello world); for (int i 0; i s1.size(); i) { cout s1[i] ; } return 0; }可以支持直接访问操作int main() { string s1(hello world); s1[0] x; for (int i 0; i s1.size(); i) { cout s1[i] ; } return 0; }也可以支持赋值操作[]重载也是支持const修饰的保证了[]在针对const修饰的string对象的时候不会被修改数据string中at的使用at的作用和[]是一样的但是at是更安全的[]它支持越界的检查我知道[]对越界的检查只在为尾元素的后几个一旦超过一定距离编译器就不会报错at就很好的解决了这个问题#define _CRT_SECURE_NO_WARNINGS 1 #includeiostream using namespace std; void print(const string str) { for(size_t i 0;i str.size(); i) { cout str.at(i) ; } cout endl; } int main() { string s(1234567890); print(s); return 0; }代码结果1 2 3 4 5 6 7 8 9 0string中back/front的使用front是返回string对象中的第一个元素back是返回string对象中的最后一个元素俩个const版本也是对应const修饰的string类型对象#define _CRT_SECURE_NO_WARNINGS 1 #includeiostream using namespace std; int main() { string s(1234567890); cout s.back() endl; cout s.front() endl; return 0; }代码结果01sting中max_sizemax_size返回的是该容器对象在理想情况下理论上可以容纳的最大元素个数这个方法的作用并没有什么真正的运用场景因为内存的大小系统的不同都会影响所以这个方法可以不看string中capacity作用是返回string对象的最大存储容量之前我们就说了其实string就是一个字符串那么是字符串就会存在最大存储容量和当前存储个数和起始位置这三个成员属性string中resize该方法的作用是根据你给的n来调整string对象的大小1.n 对象的最大存储容量时(capacity)capacity会扩大到至少n可能略大于n取决于内存分配策略size会变成n新元素会初始化为指定值c存在或默认值c不存在⚠️注意capacity可能大于n不一定精确等于n2.size n capacity 时capacity不变size n新元素会初始化为指定值c存在或默认值c不存在3.n size时capacity不变size nsize - n这段数据丢失#define _CRT_SECURE_NO_WARNINGS 1 #includeiostream using namespace std; int main() { string s(1234567890); cout s endl; cout s的初始capacity和size endl; cout capacity:s.capacity() endl; cout size: s.size() endl; cout endl endl; cout n capacity endl; s.resize(15,a); cout capacity: s.capacity() endl; cout size: s.size() endl; cout s endl; cout endl endl; cout size n capacity endl; s.resize(11); cout capacity: s.capacity() endl; cout size: s.size() endl; cout s endl; cout endl endl; cout n size endl; s.resize(5); cout capacity: s.capacity() endl; cout size: s.size() endl; cout s endl; return 0; }代码结果string中reservereserve的作用就是将string对象的capacity扩容到 大于等于n#define _CRT_SECURE_NO_WARNINGS 1 #includeiostream using namespace std; int main() { string s(12345); cout capacity: s.capacity() endl; s.reserve(20); cout reserve-capacity: s.capacity() endl; s.reserve(20); cout reserve-capacity: s.capacity() endl; return 0; }代码结果特点当 n 小于capacity的时候string对象的capacity不会改变当 n 大于capacity的时候string对象的capacity会增容到大于等于n不同的编译器下的reserve的实现机制不同在vs2019下的reserve的增容不是以n这个数值为基准的他会在n的基础上进行对齐操作所以最后增容的大小其实并不是n但是在Linux下reserve就是按照n的大小来进行扩容并且最后的增容大小也是以n为基准重点不同的编译器下的reserve的实现不同clearclear的作用是清空string对象的数据将size置为0capacity不变#define _CRT_SECURE_NO_WARNINGS 1 #includeiostream using namespace std; int main() { string s(12345); cout s endl; s.clear(); cout clear: s endl; return 0; }代码结果empty作用是判断string是否为空为空就返回true不为空就返回false#define _CRT_SECURE_NO_WARNINGS 1 #includeiostream using namespace std; int main() { string s(12345); cout s.empty() endl; s.clear(); cout clear: s.empty() endl; return 0; }代码结果我们看到有三个版本其实版本1可以不用设计因为c中有隐式转化就是对string对象进行尾差#define _CRT_SECURE_NO_WARNINGS 1 #includeiostream using namespace std; int main() { string s(12345); string ss one two three; cout s endl; s 6789 ; s qwe; s c ; s ss; cout s endl; return 0; }代码结果append常用的几个版本就是我框选出来的几个这几个已经可以满足我们的大部分的使用场景了属于一定要掌握的其他的可以按需来学习append的作用就是对string对象进行尾差不过尾差的类型可以是string、char*、char类型也可以是目标数据str的一部分subpos-sublen进行尾插这个版本的append在使用的过程你可能觉得他是左闭右开的其实不是。如果你传的是0-size这个区间那么其实最后是有把\0也插入进去的因为\0对于string来说就是一个普通的字符而已只是在打印的时候会以\0作为结束标志如果区间超过了源数据这种行为是C未定义的行为编译器不回去自动检查你的append有没有发生越界#define _CRT_SECURE_NO_WARNINGS 1 #includeiostream using namespace std; int main() { string s(12345); string ss(ont two three); cout ss.len: ss.size() endl; s.append(ss, 0, ss.size()); cout s endl; return 0; }代码结果这个版本和一般的append不一样正常append在插入是遇到源数据的\0就会停止插入这个版本n的优先度大于\0只要没有插入到n个数据哪怕遇到\0也不会停下如果源数据的元素个数小于n这种行为是C未定义的行为编译器不回去自动检查你的append有没有发生越界注意看我这段代码我用append(9,10明显我的源数据是不够的10位但是在vs2019下在插入完9以后还插入了9个\0但是这种行为C是没有做出定义的所以在不同的编译器下的结果可能不一样这一图片就很好的证明了该版本对于\0的优先级并没有n的高这个版本是用迭代器来完成插入操作#define _CRT_SECURE_NO_WARNINGS 1 #includeiostream using namespace std; int main() { string s(12345); string ss one two three; cout s endl; s.append(ss.begin(), ss.end()); cout s endl; return 0; }代码结果push_back对string对象进行尾差一个字符#define _CRT_SECURE_NO_WARNINGS 1 #includeiostream using namespace std; int main() { string s(12345); s.push_back(a); s.push_back(b); s.push_back(c); s.push_back(d); s.push_back(e); cout s endl; return 0; }代码结果assignassign的作用是将原string对象中的数据用参数列表中的第一个参数或者他的一部分覆盖掉原有数据这个assign的版本参数设置和刚刚我们讲的append一模一样其实确实一个意思这个就是用str字符串和s的数据去覆盖原string的数据#define _CRT_SECURE_NO_WARNINGS 1 #includeiostream using namespace std; int main() { string s(12345); string ss(ont two three); s.assign(abcde); cout s endl; s.assign(ss); cout s endl; return 0; }代码结果这两个的功能比较类似我就放一起说了一个是用string对象的subpos-sublen的数据来覆盖源数据一个是用迭代器来实现用新数据来覆盖源数据这里的一些使用性质用参考和append相同的参数列表#define _CRT_SECURE_NO_WARNINGS 1 #includeiostream using namespace std; int main() { string s(12345); string ss(ont two three); s.assign(ss, 0, ss.size()); cout s endl; s.assign(ss.begin() 1, ss.end() - 1); cout s endl; return 0; }然后这个版本我就不在多说了参数的使用规则和append那个是一致的只是这个是覆盖原数据而已insertintsert的作用在pos位置之前插入数据还是一样我们不需要全部掌握所有的版本只要掌握我框上的版本就可以其他的用的时候在查也是可以的在pos位置插入一个string对象#define _CRT_SECURE_NO_WARNINGS 1 #includeiostream using namespace std; int main() { string str(ss); string s xx; str.insert(0, s); cout str endl; return 0; }代码结果在pos位置之前插入一个字符串其实这个版本和string版本是一样的因为C支持隐式类型转换没必要再去设计一个char*的版本#define _CRT_SECURE_NO_WARNINGS 1 #includeiostream using namespace std; int main() { string str(ss); str.insert(0, 1234); cout str endl; return 0; }代码结果在pos位置之前插入n个字符c这也是insert唯一种不使用迭代器可以插入字符的方式#define _CRT_SECURE_NO_WARNINGS 1 #includeiostream using namespace std; int main() { string str(ss); str.insert(0, 3,1); cout str endl; return 0; }代码结果一个是在迭代器p位置之前插入n个字符c另一个是在迭代器p位置之前插入一个字符c#define _CRT_SECURE_NO_WARNINGS 1 #includeiostream using namespace std; int main() { string str(ss); cout str endl; str.insert(str.begin(), 3, 1); cout str endl; str.insert(str.begin(),2); cout str endl; return 0; }代码结果eraseerase的作用删除指定位置的数据或是指定位置的后len个长度单位的数据区间len是一个缺省值如果你没传len的值那么len就会默认赋nops值我们可以看到nops其实就是一个静态属性size_t unsigned int所以当nops -1时npos就是最大的正整数共享性类直接访问再类加载是初始化#define _CRT_SECURE_NO_WARNINGS 1 #includeiostream using namespace std; int main() { string str(abce); str.erase(0, 1); cout str endl; str.erase(0); cout str endl; return 0; }代码结果这俩版本分别是删除迭代器指向的未知的数据、删除俩个迭代器之间的数据左闭右开左闭右开包括左迭代器指向的数据但不包括右迭代器指向的数据删除到他的前一个位置为止#define _CRT_SECURE_NO_WARNINGS 1 #includeiostream using namespace std; int main() { string str(abce); str.erase(str.begin() 1); cout str endl; str.erase(str.begin() 1, str.end() - 1); cout str endl; return 0; }代码结果replace主要关注我框选的几个版本掌握即可其他的使用场景不多可以用到在来看replace的作用用于替换字符串中部分内容的成员函数就是将string对象中的数据或者一部分数据替换掉替换不一定就是等值个数的数据替换也可能是1个元素被替换成2个元素2个元素被替换成1个元素在pos位置到poslen的区间替换为str左闭右开在迭代器i1到迭代器i2区间替换为str#define _CRT_SECURE_NO_WARNINGS 1 #includeiostream using namespace std; int main() { string str(abcdef); string s(123456); str.replace(0, str.size(), s); cout str endl; str.replace(str.begin(), str.end(), aaaa); cout str endl; return 0; }代码结果这个两版本其实和上面的string版本是一样的就是替换的源数据不一样一个是string一个是char*类型的这里我就不再去演示了把指定的区间的数据替换成n个字符c#define _CRT_SECURE_NO_WARNINGS 1 #includeiostream using namespace std; int main() { string str(abcdef); string s(123456); str.replace(0,1, 5,1); cout str endl; str.replace(str.begin(), str.begin()1, 5, z); cout str endl; return 0; }代码结果——————————————————————————————————————————这里在讲一下当len的长度为0的的时候、当i1和i2相等的时候#define _CRT_SECURE_NO_WARNINGS 1 #includeiostream using namespace std; int main() { string str(abcdef); string s(123456); str.replace(0,0, 5,1); cout str endl; str.replace(str.begin(), str.begin(), 5, z); cout str endl; return 0; }代码结果我们可以看到当len的长度为0i1和i2相等的时候其实此时的替换操作就变成了插入操作而且是posi1位置之前插入的操作虽然replace可以进行这一的操作但是如果我们要进行插入操作还是建议直接使用insertswapswap作用交换俩个string对象的数据这个第一的个swap是string类的成员函数第二个是std域名中的swap函数区别string类中的swap成员函数内部是直接交换两个string对象的地址来达到数据交换的效果std域名中的swap函数内部是创建一个相同的数据类型作为媒介来交换两个对象的数据但是这种交换会涉及到对象的拷贝构造所以并没有类中的swap来的高效#define _CRT_SECURE_NO_WARNINGS 1 #includeiostream using namespace std; int main() { string str(abcdef); string s(123456); str.swap(s); cout str endl; return 0; }代码结果pop_backpop_back的作用删除字符串的最后一个元素#define _CRT_SECURE_NO_WARNINGS 1 #includeiostream using namespace std; int main() { string str(abcdef); str.pop_back(); cout str endl; return 0; }代码结果c_str和datac_str和data的作用返回一个char*地址我们一开始就说了string其实就是一个字符串是字符串就会有char*的地址只是string对char*字符串进行了一系列的封装最后以string 的形式供我们使用那有没有什么使用场景呢有的当我们想用printf来打印string对象的时候你会发现报错为什么会这样呢因为printf会根据%s来判断接受的地址是一个字符串地址但是string对象他的地址里面不光是存储了字符串还有字符串的元素个数、最大存储容量等等信息所以你直接当字符串打印打出来的就很可能是乱码当你使用c_str和data的时候就可以正常打印这相当于你直接把string对象中的字符串地址提取出来了copycopy作用用数组s来接收string对象距离pos位置的len个距离单位的数据区间#define _CRT_SECURE_NO_WARNINGS 1 #includeiostream using namespace std; int main() { string str(abcdef); char data[20]; str.copy(data, 2, 0); cout data endl; return 0; }代码结果直接截取拷贝到目标数组里肯定会丢失\0但是没关系因为data是以字符的形式存储的不需要\0来作为结束标记findfind的作用根据给的第一个参数在string对象中从pos位置开始查找第一次匹配的数据返回该数据的的下标找不到返回nops#define _CRT_SECURE_NO_WARNINGS 1 #includeiostream using namespace std; int main() { string str(abcdef); string s(b); //size_t find (const string str, size_t pos 0) const; size_t judge str.find(s); if (judge ! string::npos) { cout str[judge] endl; } //size_t find (const char* s, size_t pos 0) const; judge str.find(b); if (judge ! string::npos) { cout str[judge] endl; } //size_t find (const char* s, size_t pos, size_t n) const; judge str.find(b, 0, 1); if (judge ! string::npos) { cout str[judge] endl; } //size_t find (char c, size_t pos 0) const; judge str.find(b); if (judge ! string::npos) { cout str[judge] endl; } return 0; }代码结果我相信其他几个版本大家都可以看得懂就是size_t find (const char* s, size_t pos, size_t n) const;这个版本可能有点看不明白我这里再解释一下从string对象的pos位置开始查找查找的对象是s字符串数组的前n位rfind和find_first_of、find_last_of、find_first_not_of、find_last_not_ofrfind的作用从后往前查找find_first_of的作用从前往后查找只要查找到数据中的任意一个元素就返回下标find_last_of的作用从后往前查找只要查找到数据中的任意一个元素就返回下标find_first_not_of的作用从前往后查找除了数据中的元素查找到其他的任意元素就返回下标find_last_not_of从后往前查找除了数据中的元素查找到其他的任意元素就返回下标因为他们的参数列表都是一致的所以我就不一一演示了substrsubstr的作用将string对象的pos位置到poslen位置的数据区间拷贝出来构成一个子串#define _CRT_SECURE_NO_WARNINGS 1 #includeiostream using namespace std; int main() { string str(abcdef); string s str.substr(0,3); cout s endl; return 0; }代码结果string中iterator迭代器迭代器 iterator一般是做一个类型来创建对象或者是作为其他迭代器的返回值或者参数类型你可以理解iterator是一个被重命名的char*迭代器就是string中专门用来访问string对象数据的为什么明明有了[]还需要iterator迭代器呢这个也是为了和其他容器保持一致因为在内存空间连续存储的string和vector容器中确实感觉作用并不突出但是在内存空间不连续的链表结构和树结构上那就效果十分显著了我们只需要创建一个迭代器然后去根据自己的需求是修改还是迭代打印就可以不需要去关注他们之间的访问细节begin和end这里为了更好的理解我们先把上面这些迭代器分为两大类begin() end()cbegin() cend()rbegin() rend()crbegin() crend()我们先来了解一下begin和endbegin的作用是返回字符串的第一个元素的位置end的作用是返回字符串的最后一个元素的位置然后it指向该元素你可以暂时理解为是一个指针int main() { string s1(hello world); //要指定类域才可以直接访问,这个it可以自己去设置名字 string::iterator it s1.begin(); while (it ! s1.end()) { cout *it ; it; } return 0; }注意begin()和end()的也有const版本但是他们的返回值是const_iterator (这一点和iterator的普通版本和const版本是相对应的)之所以会引用iterator迭代器来遍历就是因为下标[]只适用于部分容器底层物理有一定连续的链式结构、树形结构、哈希结构只能用迭代器迭代器才是容器访问的主流形态每一个容器里面都有一个iterator迭代器但是iterator也分俩个版本一个是无const修饰的版本一个是有const修饰的版本const修饰的是this地址注意const_iterator不是const iteratoriterator()无const修饰const_iterator()const修饰*it不能修改const iterator()修饰it不能修改这里在讲一下const_iterator的使用场景#define _CRT_SECURE_NO_WARNINGS 1 #includeiostream using namespace std; void print(const string str) { //如果这里不使用const_iterator的话str.begin就会报错 string::const_iterator it str.begin(); while (it ! str.end()) { cout *it ; } cout endl; } int main() { string s(1234567890); print(s); return 0; }代码结果1 2 3 4 5 6 7 8 9 0这里在解释一下为什么会报错因为C的编译器在检测到str为const修饰的对象以后在str去调用begin迭代器就会去调用那个const_iterator begin()const版本的迭代器这个时候的返回值就是const_iterator类型的你用iterator类型的it去接收const_iterator的类型类型就会不匹配范围for其实范围for的原理也是迭代器的调用编译器会去调用迭代器去实现所需要的功能但是如果想验证这一观点的话现阶段最好的办法就是自己去模拟实现一个string类然后在迭代器的实现部分begin和end就先不实现然后去使用范围for看看他是否可以正常运行cbegin/rbegin/crbegin和cend/rend/crend除了begin/rbegin和end/rend其他这几个迭代器是C11中引入的其实在功能上他们之间没有什么区别begin cbegin end cend rbegin crbegin rend crend加c的前缀就是const版本但是begin、end、rbegin、rend都是自带const版本的所以特意分出来一个const版本意义不是特别大当然如果你使用了C11新引入的迭代器那么在代码的可读性上绝对是有提升的

相关文章:

STL中的string容器和迭代器iterator

前言 这一片博客开始,我们进入STL标准模板库的学习 什么是STL STL(Standard Template Library)是C标准库的核心组成部分,提供了一系列通用模板类和函数,实现了常见的数据结构和算法。它基于泛型编程思想&#xff0c…...

计算机毕业设计springboot新冠疫情校园防控系统 基于SpringBoot的高校疫情防控信息管理平台 SpringBoot校园新冠疫情综合防控服务系统

计算机毕业设计springboot新冠疫情校园防控系统46hqx (配套有源码 程序 mysql数据库 论文) 本套源码可以在文本联xi,先看具体系统功能演示视频领取,可分享源码参考。2020年初突如其来的新冠疫情让“健康绿码”成为日常通行证,也倒…...

GLM-ASR-Nano-2512实战教程:Python SDK封装与异步批量任务队列集成

GLM-ASR-Nano-2512实战教程:Python SDK封装与异步批量任务队列集成 1. 引言 如果你正在寻找一个既强大又高效的语音识别工具,GLM-ASR-Nano-2512绝对值得你花时间了解。这个拥有15亿参数的开源模型,在多个测试中表现超越了知名的Whisper V3&…...

Qwen3-ASR-1.7B在媒体融合场景应用:广播音频→新闻稿+关键人物提取

Qwen3-ASR-1.7B在媒体融合场景应用:广播音频→新闻稿关键人物提取 1. 媒体融合场景的语音转写挑战 在媒体融合的大背景下,广播音频内容的价值挖掘面临着巨大挑战。传统的语音转写系统往往在以下几个方面存在不足: 音频质量参差不齐&#x…...

GTE+SeqGPT部署避坑指南:modelscope版本冲突、依赖补齐与aria2c加速下载

GTESeqGPT部署避坑指南:modelscope版本冲突、依赖补齐与aria2c加速下载 1. 项目概述与环境准备 今天要跟大家分享一个非常实用的AI项目部署经验——如何快速搭建一个集成了语义搜索和文本生成功能的AI系统。这个项目结合了GTE-Chinese-Large语义向量模型和SeqGPT-…...

Qwen3-0.6B-FP8开源模型评测:FP8量化对逻辑推理、代码生成、多语言影响分析

Qwen3-0.6B-FP8开源模型评测:FP8量化对逻辑推理、代码生成、多语言影响分析 最近,一个只有6亿参数的小模型Qwen3-0.6B-FP8在开发者圈子里引起了不小的讨论。你可能会有疑问:现在动辄几百亿参数的大模型满天飞,一个6亿参数的小模型…...

Nanbeige4.1-3B详细步骤:从log路径排查WebUI无法响应的5类常见问题

Nanbeige4.1-3B详细步骤:从log路径排查WebUI无法响应的5类常见问题 你刚部署好Nanbeige4.1-3B的WebUI,兴致勃勃地打开浏览器,输入地址,结果页面一片空白,或者一直转圈圈,最后弹出一个“无法访问此网站”的…...

22 | 别再复制粘贴那 80% 的代码了:给你的流程装个“标准模具”——模板方法模式

我之前给一个做跨境电商的朋友帮忙,处理过一段让人特别心累的代码。 当时系统里有各种各样的“数据导出”功能:导出订单、导出库存、导出用户。 我发现代码里全是重复的影子:先查数据库,再格式化数据,最后生成文件。 虽…...

21 | 别再写那堆恶心的 if-else 了:给你的代码装个“插件盒”——策略模式

我之前接手过一个电商项目的促销模块,那段代码现在想起来还觉得头大。 当时的需求是:根据用户等级算折扣。 普通用户不打折,VIP 打 9 折,超级 VIP 打 8 折。 我当时写得特别顺手,直接一个 if-else 搞定。 结果后来业务…...

远程线程DLL注入

远程线程DLL注入 DLL注入是一项在Windows开发和安全研究中常见的技术,它允许一个进程将动态链接库加载到另一个进程的地址空间中。远程线程注入是其中最为经典和广泛应用的方法之一。这篇文章将深入探讨其原理、实现细节以及实际应用中的注意事项。 基本概念与原理 …...

基于YOLOv8的手势识别系统

基于 YOLOv8 目标检测框架的手势识别系统,支持图片、视频、摄像头实时检测,并提供训练、可视化与历史管理等功能。一、项目概述本系统采用 YOLOv8 作为检测骨干网络,对 18 类手势进行识别。系统包含完整的训练流程与桌面端应用,支…...

基于 Qt 5.12.2 实现 CAN 总线数据解析与可视化(规则配置 + 实时更新篇)

引言本文是我在学习 Qt 开发和 CAN 总线应用过程中的实践总结,基于 Qt 5.12.2 开发 CAN 总线数据分析软件。本文将聚焦软件核心功能 ——规则配置文件驱动的数据解析与QGraphicsScene 控件实时数据更新,同时说明当前功能进度与后续规划,为同领…...

基于Simulink的电网不平衡下正负序分离充电策略

目录 手把手教你学Simulink ——基于Simulink的电网不平衡下正负序分离充电策略 一、问题背景 二、正负序分离原理(DSOGI法) 1. 不平衡电压分解 2. DSOGI结构 三、系统整体控制架构 四、Simulink建模步骤 第一步:搭建不平衡电网与AFE…...

冯·诺依曼自复制自动机:从理论模型到C++/OpenCV实战

引言:探索自我复制的数字生命1940年代,数学家和计算机科学家约翰冯诺依曼提出了一个革命性的概念:自复制自动机。他设想了一种能够自我复制的机器,不仅能够复制自身,还能在复制过程中引入变化,从而实现类似…...

学Simulink--基于多能互补微电网系统的建模与优化场景实例:基于区块链的分布式能源交易与微电网调度仿真

目录 手把手教你学Simulink ——基于多能互补微电网系统的建模与优化场景实例:基于区块链的分布式能源交易与微电网调度仿真 一、背景介绍 二、系统结构设计 各模块具体功能如下: 三、建模过程详解 第一步:创建 Simulink 项目并导入基础模块 第二步:搭建微电网物理…...

Tomcat下载安装教程(附安装包)

Tomcat安装教程 (以tomcat-9.0.62为例:) 1.下载 安装包 官网需要注册登录,推荐直接百度网盘自提:链接:https://pan.baidu.com/s/1FA6m5o9VUdEccQ9KiuZHPA?pwd74i8提取码74i8 (1)从官网下载 输…...

SecureCRT下载、安装(附安装包)

一、安装步骤 这是我们接下来要用到的文件: 百度网盘链接: https://pan.baidu.com/s/196nrUkxrncxU0pWa9H9O0A?pwd1111 提取码: 11111、双击运行安装程序scrt-x64.8.5.4 .exe 2、按照安装向导完成安装(所有选项保持默认即可) 二、破解流程…...

2025_NIPS_CGBENCH: Benchmarking Language Model Scientific Reasoning for Clinical Genetics Research

核心结论 该文章提出临床遗传学领域的LLM评估基准CGBENCH,聚焦真实场景下的科学文献解读任务,揭示了现有模型在细粒度证据分析中的优势与不足,创新点集中在任务设计、数据来源和评估方法三方面。 一、主要内容总结 1. 研究背景与问题 临床遗传学中,基因和变异注释是个性…...

2025_NIPS_Compress, Gather, and Recompute: REFORMing Long-Context Processing in Transformers

文章核心总结与翻译 一、主要内容 本文针对大型语言模型(LLMs)处理超预训练上下文长度(如百万级token)时面临的计算成本高、内存消耗大、信息丢失等问题,提出了一种名为REFORM的新型推理框架。该框架融合循环压缩方法的效率优势与随机访问方法的召回能力,通过“压缩-收…...

2025_NIPS_MVU-Eval: Towards Multi-Video Understanding Evaluation for Multimodal LLMs

一、文章主要内容总结 该研究针对现有多模态大语言模型(MLLMs)评估基准局限于单视频理解、无法满足现实场景中多视频分析需求的问题,提出了首个全面的多视频理解评估基准 MVU-Eval。 核心内容: 基准设计:涵盖8项核心能力(4项基础感知任务+4项高阶推理任务),包含1824个…...

2025_NIPS_The Unreasonable Effectiveness of Entropy Minimization in LLM Reasoning

文章核心总结与翻译 主要内容 文章聚焦熵最小化(EM)在大语言模型(LLMs)推理任务中的应用,提出三种无需标注数据的方法,在数学、物理、编程等复杂任务中显著提升模型性能: 无监督微调(EM-FT):基于模型生成的无标注输出,最小化token级熵,效果对标有监督微调方法。 …...

SkillNet: Create, Evaluate, and Connect AI Skills

SkillNet 文章核心总结与关键翻译 一、主要内容总结 SkillNet 是一款面向 AI 技能的全生命周期开放基础设施,旨在解决当前 AI 智能体缺乏系统技能积累与迁移机制的核心痛点——智能体常陷入“重复造轮子”的困境,无法有效复用过往经验与策略。 该基础设施的核心架构包含三…...

微信运营数据化,这些报表不看就亏大了!

为了冲业绩,你带领团队在朋友圈社群里忙得脚不沾地,又是搞活动又是做一对一私聊。月底复盘时,老板问:“上个月我们加了多少好友?删了我们的人有多少?哪个员工偷偷摸鱼?那些加了微信的客户&#…...

2026 本科论文写作终极横评:9 大 AI 工具,从 0 到 1 搞定 1.2 万字初稿的高效密码

前言:本科论文的 “效率革命”,AI 工具正在重构毕业创作逻辑 对于本科毕业生而言,毕业论文从来不是 “写一篇长文”,而是一场横跨选题、文献、大纲、初稿、格式的全链路攻坚战。据《2026 本科毕业生学术创作调研》显示&#xff0…...

微信长按快速解锁沟通指法

日常用微信聊天、办公、刷朋友圈,你是否总在为找表情包、输长文本、解专业梗而烦恼?其实微信里藏着一套超实用的「长按指法」,只需轻轻按住 1 秒,就能解锁多种便捷功能,不管是摸鱼斗图还是职场办公,都能让你…...

网络程序设计入门第一章:Web、JSP、Tomcat 到底是什么?

一、前言 很多同学第一次上《网络程序设计》这门课,都会有一种很强的迷惑感: JSP 是什么? Tomcat 是什么? 浏览器为什么能打开我写的页面? HTML、JSP、Servlet 到底什么关系? 这门课和“计算机网络”到…...

火箭仿真系列-蒙特卡洛仿真与敏感性分析完整使用示例

以下是蒙特卡洛仿真与敏感性分析模块的完整使用示例,涵盖从不确定性定义到结果可视化的全过程。一、完整蒙特卡洛分析示例import numpy as np import matplotlib.pyplot as plt import pandas as pd from datetime import datetime import seaborn as sns from scip…...

TongWeb7在国产操作系统上的安装与配置实战指南

1. 环境准备:为TongWeb7铺好国产化“地基” 大家好,我是老张,在中间件和国产化环境里摸爬滚打了十来年。今天咱们不聊虚的,直接上手,把TongWeb7在国产操作系统(比如咱们熟悉的麒麟)上从零开始装…...

SpringBoot与RocketMQ深度整合:多连接配置与动态Topic处理实战

1. 为什么需要多连接与动态Topic处理? 在实际的企业级项目中,我们使用消息队列的场景往往不是单一的。比如,你的订单服务可能需要向一个RocketMQ集群发送订单创建消息,同时,你的物流服务又需要从另一个独立的RocketMQ…...

威联通QNAP通过Container快速部署Tranmission及美化UI实战

1. 为什么选择在威联通上跑Transmission? 如果你和我一样,是个喜欢折腾家庭影音库、有大量下载需求的人,那么一台威联通(QNAP)NAS绝对是你的好帮手。它不仅仅是个存储数据的“大硬盘”,更是一个功能强大的…...