C++新经典10--vector以及其使用

news2025/4/9 5:23:47

vector

vector类型是一个标准库中的类型,代表一个容器、集合或者动态数组这样一种概念。既然是容器,那就可以把若干个对象放到里面。当然,这些对象的类型必须相同。简单来说,可以把一堆int型数字放到vector容器中去,复杂点说,可以把一堆相同类型的类对象放到vector容器中去。

所以,如果换个角度考虑,vector能把其他对象装进来,所以称为容器非常合适。容器这个概念经常被提及,读者要知道和理解这个概念。

要想使用这种类型,需要在.cpp源文件开头包含vector头文件:
在这里插入图片描述
另外,为了方便引用这种类型,也要书写:
在这里插入图片描述
定义一个vector类型对象。显然,一旦定义出来,这个对象就是容器了。例如想在里面保存int型数据(容器里面所要装的元素类型),看如下代码:
在这里插入图片描述
上面的代码定义了一个vector类型的对象,名字叫作vjihe,这个对象里面保存的就是int型数据。为什么是int型数据呢?读者可以看到,vector后面有一对“<>”,“<>”里面是int,表示这个vector类型的对象(容器)里面存放的是int型对象(int型数据/元素)。

这个<int>的写法读者可能第一次见到,会觉得是一种奇怪的写法,在后面章节中会讲到“类模板”的概念,其实vector就是一个类模板,这里的“<>”实际上是类模板的一个实例化过程。但是类模板的实例化过程眼下对于读者来讲,理解起来还比较生涩,后面学习模板的时候再详细阐述,所以这里笔者换一种说法来帮助读者理解类模板。

vector理解成一个残缺的类类型,这意味着使用时光有类名vector还不够,还需要额外给vector类模板提供其要在其中保存什么类型数据的信息,这个信息就是通过<int>来提供(模板名后跟一对“<>”,“<>”内放入类型信息),所以,在使用vector时,一定要在它后面跟一对“<>”并在其中跟一个该vector容器中要保存的数据(元素)类型的信息,这才算一个完整的类型(完整的类类型)。例如,vector不是一个完整类型,而vector<int>却是一个完整的类型。看看如下范例:
在这里插入图片描述
一般来讲,vector容器里面可以装很多种不同类型的数据作为其元素(容器中装的内容简称“元素”)。看看如下范例:
在这里插入图片描述
但是vector不能用来装引用。请记住,引用只是一个别名,不是一个对象。所以,下面的写法会报语法错误:
在这里插入图片描述

定义和初始化vector对象

(1)空vector。
定义如下:

vector<string> mystr;
//创建一个string类型的空vector对象(容器),
//现在mystr里不包含任何元素

后续就可以用相关的一些操作函数往这个空对象里增加数据了。

例如,可以往这个容器的末尾增加一些数据。这里可以使用vector的成员函数push_back往容器末尾增加数据。看看如下范例,注意看它的下标[0],[1],[2],…不断增长,如图13.3所示。

mystr.push_back("abcd");
mystr.push_back("def");

(2)在vector对象元素类型相同的情况下,进行vector对象元素复制(新副本)。

vector<string> mystr2(mystr);	//把mystr元素复制给了mystr2
vector<string>mystr3 = mystr;	//把mystr元素复制给了mystr3

(3)在C++11中,还可以用初始化列表方法给初值,这个时候用“{}”括起来。

vector<string> def = {"aaa","bbb","ccc"};

当然“{}”里面为空也可以,那就相当于没有初始化,是一个空的vector了。

(4)创建指定数量的元素。请注意,有元素数量概念的初始化,用的都是“()”。

如果不给元素初值,那么元素的初值要根据元素类型而定,例如元素类型为int,系统给的初值就是0,元素类型为string,系统给的初值就是"",但也存在有些类型,必须给初值,否则就会报错。
如下范例演示不给元素初值的情况:

vector<int> ijihe2(20);	//20个元素,下标[0]~[19],每一个元素值都为0
vector<string> sjihe2(5);	//15个元素,下标[0]~[4],每一个元素值都为""

(5)多种初始化。“()”一般表示对象中元素数量这种概念,“{}”一般表示元素的内容这种概念,但又不是绝对。看看如下范例:
在这里插入图片描述

vector对象上的操作

其实,在使用vector时,最常见的情况是并不知道vector里会有多少个元素,使用时会根据需要动态地增加和减少。所以一般来讲,使用者是先创建一个空的vector对象,然后通过代码向这个vector里增加或减少元素。这里将要介绍一些vector类型提供的常用方法。vector上很多的操作和string很相似。
(1)判断是否为空empty(),返回布尔值。

   vector<int> ivec;
    if (ivec.empty())   //条件成立
    {   
        cout<<"ivec为空"<<endl;
    }

(2)push_back:一个非常常用的方法,用于向vector末尾增加一个元素。

    vector<int> ivec;  //先声明成空的vector对象
    ivec.push_back(1);
    ivec.push_back(2);
    for (int i=3;i<=100;i++)
    {
    ivec.push_back(i);
    }

在上面的范例中,注意观察,能够发现,值2在值1的后面(最后插入的元素在vector容器的最末尾)。调试结果如下图所示。

(3)size:返回元素个数。
(4)clear:移除所有元素,将容器清空。
(5)v[n]:返回v中的第n个字符(n是一个整型值),位置从0开始计算,位置值n也必须小于.size(),如果下标引用超过这个范围,或者用下标访问一个空的vector,都会产生不可预测的结果(因为编译器可能发现不了这种错误)
在这里插入图片描述
(6)赋值运算符(=)。

    vector<int> ivec;
    //先声明成空的vector对象
    ivec.push_back(1);
    ivec.push_back(2);
    for (int i=3;i<=100;i++)
    {
        ivec.push_back(i);
    }
    vector<int> ivec2;
    ivec2.push_back(111);
    ivec2=ivec;//也得到了100个元素,用ivec中的内容取代了ivec2中原有内容,上行这个111就
               //被冲掉了
    ivec2={12,13,14,15};
    //用{}中的值取代了ivec2原有值
    cout<<ivec2.size()<<endl;  //4

(7)相等和不等(==和!=)。
两个vector对象相等:元素数量相同,对应位置的元素值也都相同。否则就是不相等。
在这里插入图片描述
(8)范围for的应用:和讲解string时对范围for的应用类似

    vector<int> vecvalue{1,2,3,4,5 };
    for(auto& vecitem:vecvalue)  //为了修改vecvalue内部值,这里是引用,引用会绑定到元素上,达
                                //到通过引用改变元素值的目的
    
        vecitem *= 2;       //扩大一倍
        
    for (auto vecitem : vecvalue)
    cout << vecitem << endl;

针对范围for语句,这里希望引申一步进行讲解。如果在范围for中,增加改变vector容量的代码,则输出就会变得混乱:

    vector<int> vecvalue{1,2,3,4,5 };
    for (auto vecitem : vecvalue)
    {
        vecvalue.push_back(888);
        cout << vecitem << endl;

    }

范围for,在这里用来遍历vector容器中的元素。这里的vecitem是定义的一个变量,后面的vecvalue是一个序列(容器),for语句中使用auto来确保序列中的每个元素都能够转换成变量vecitem对应的类型,所以一般在范围for语句中习惯使用auto(编译器来指定合适的vecitem类型)。

那为什么上述代码会产生混乱的输出呢?

因为每次执行for循环,都会重新定义vecitem,并且把它的值初始化成vecvalue序列中的下一个值。在刚刚进入这个for循环时,在系统内部会记录序列结束的位置值,但一旦在这个范围for里面改动这个序列的容量(如增加/删除元素),那么这个序列结束的位置值就肯定会发生改变,这个改变会导致for语句的混乱,其输出的值也就乱了。

所以,请记住一个结论,在for语句中,不要改变vector的容量,增加、删除元素都不可以。请读者千万千万不要写出这种错误代码,否则隐患无穷,切记切记!

迭代器精彩演绎、失效分析及弥补、实战

迭代器简介

迭代器是一个经常听到和用到的概念。上一节学习了vector,笔者说过,这是一个容器,里面可以容纳很多对象。那迭代器是什么呢?迭代器是一种遍历容器内元素的数据类型。这种数据类型感觉有点像指针,读者就理解为迭代器是用来指向容器中的某个元素的。

string可以通过“[]”(下标)访问string字符串中的字符,vector可以通过“[]”访问vector中的元素。但实际上,在C++中,很少通过下标来访问它们,一般都是采用迭代器来访问。

除了vector容器外,C++标准库中还有几个其他种类的容器。这些容器都可以使用迭代器来遍历其中的元素内容。string其实是字符串,不属于容器,但string也支持用迭代器遍历。

通过迭代器,可以读取容器中的元素值、修改容器中某个迭代器所代表(所指向)的元素值。此外,迭代器可以像指针一样——通过++、–等运算符从容器中的一个元素移动到另一个元素。

许多容器如上述的vector,在C++标准库中,还有其他容器如list、map等都属于比较常用的容器,C++标准库为每个这些容器都定义了对应的一种迭代器类型,有很多容器不支持“[]”操作,但容器都支持迭代器操作。写C++程序时,笔者也强烈建议读者不要用下标访问容器中的元素,而是用迭代器来访问容器中的元素。

容器的迭代器类型

刚刚讲过,C++标准库为每种容器都定义了对应的迭代器类型。这里就以容器vector为例,演示一下:

    vector<int> iv = {100,200,300};     //定义一个容器
    vector<int >:: iterator iter;       //定义迭代器,也必须是以vector<int>开头

上面的语句是什么意思呢?后面这条语句定义了一个名为iter的变量(迭代器),这个变量的类型是vector<int>::iterator类型,请注意这种写法“::iterator”。iterator是什么?它是每个容器(如vector)里面都定义了的一个成员(类型名),这个名字是固定的,请牢记。
在理解的时候,就把整个vector<int>::iterator理解成一种类型,这种类型就专门应用于迭代器,当用这个类型定义一个变量的时候,这个变量就是一个迭代器。

迭代器begin/end、反向迭代器rbegin/rend操作

1.迭代器

每一种容器,如vector,都定义了一个叫begin的成员函数和一个叫end的成员函数。这两个成员函数正好用来返回迭代器类型。看看如下范例。
(1)begin返回一个迭代器类型(就理解成返回一个迭代器)。
在这里插入图片描述
(2)end返回一个迭代器类型(就理解成返回一个迭代器)。
在这里插入图片描述
对上面的代码进行跟踪调试,观察begin和end结果可以看到,end()指向了一个乱数字,如图13.5所示。

    vector<int> iv = {100,200,300};     //定义一个容器
    vector<int >::iterator iter;       //定义迭代器,也必须是以vector<int>开头
    iter = iv.begin();
    iter = iv.end();

在这里插入图片描述
(3)如果容器为空,则begin返回的迭代器和end返回的迭代器相同。看看如下范例:

    vector<int> iv2;
    vector<int>::iterator iterbegin = iv2.begin();
    vector<int>::iterator iterend = iv2.end();
    if (iterbegin == iterend)   //条件成立
    {
        cout << "容器为空" << endl;
    }

在这里插入图片描述

所以,end返回的迭代器并不指向容器vector中的任何元素,它起到实际上是一个标志(岗哨)作用,如果迭代器从容器的begin位置开始不断往后游走,也就是不断遍历容器中的元素,那么如果有一个时刻,iter走到了end位置,那就表示已经遍历完了容器中的所有元素。
(4)写一段代码,传统的通过迭代器访问容器中元素的方法如下:

    vector<int>iv={100,200,300};    //定义一个容器
    //经典传统用法,这里用++、!=等运算符来对迭代器进行操作
    for (vector<int>::iterator iter = iv.begin();iter != iv.end();iter++)
    {
        cout << *iter << endl;
    }

运行起来看结果:100、200、300。

2.反向迭代器

如果想从后面往前遍历一个容器,那么,用反向迭代器就比较方便。反向迭代器使用的是rbegin成员函数和rend成员函数。
(1)rbegin返回一个反向迭代器类型,指向容器的最后一个元素。
(2)rend返回一个反向迭代器类型,指向容器的第一个元素的前面位置。
rbegin和rend成员函数指向的容器位置示意图如图13.7所示。
在这里插入图片描述
看看如下范例:

    vector<int>iv={100,200,300};
    for (vector<int>::reverse_iterator riter = iv.rbegin(); riter != iv.rend(); riter++)
    {
        cout<<*riter<<endl;
    }
    

运行起来看结果:300、200、100。

迭代器运算符

(1)iter:返回迭代器iter所指向元素的引用。必须要保证该迭代器指向的是有效的容器元素,不能指向end,因为end是末端元素后面的位置,也就是说,end已经指向了一个不存在元素。前面的cout≪iter≪endl;就是使用*iter的演示范例,这里不做进一步演示了。
(2)++iter:和iter++是同样的功能——让迭代器指向容器中的下一个元素。但是已经指向end的迭代器,不能再++,否则运行时报错。
(3)–iter:和iter–是同样的功能——让迭代器指向容器中的前一个元素。了解++自然也就能了解–。看看如下范例:
在这里插入图片描述
(4)iter1==iter2或iter1!=iter2:判断两个迭代器是否相等。如果两个迭代器指向的是同一个元素,就相等,否则就不相等。
(5)结构成员的引用。看看如下范例:
在这里插入图片描述
请注意,一定要确保迭代器指向有效的容器中的元素,否则范例中的这些行为可能会导致意想不到的结果。还有很多其他运算符,例如迭代器之间可以相减表示两个迭代器之间的距离,迭代器加一个数字表示跳过多少个元素,不过这些都不常用,不准备逐一介绍,意义也不大。读者如果以后遇到,有了现在所学的基础,再简单学习一下即可。

const_iterator迭代器

前面学习了iterator这种迭代器类型,实际上每种容器还有另外一种迭代器类型,叫作const_iterator,从名字上能感觉到其含义:有const在,一般都表示常量,也就是说值不能改变的意思。这里的值不能改变表示该迭代器指向的元素的值不能改变,并不表示该迭代器本身不能改变,该迭代器本身是能改变的,也就是说,该迭代器是可以不断地指向容器中的下一个元素的。

所以该迭代器只能从容器中读元素,不能通过该迭代器修改容器中的元素。所以说,从感觉上来讲,const_iterator更像一个常量指针,而iterator迭代器是能读能写的。看看如下范例:

在这里插入图片描述
什么时候用const_iterator呢?如果这个容器对象是一个常量,那么就必须使用const_iterator,否则报错:
在这里插入图片描述
这里再额外看一看cbegin和cend成员函数。这是C++11引入的两个新函数,与begin、end非常类似。但是,不管容器是否是常量容器,cbegin、cend返回的都是常量迭代器const_iterator。看看如下范例:
在这里插入图片描述

迭代器失效

上一节在讲vector容器时谈过范围for循环语句——在遍历容器的时候,如果在for循环中,通过push_back等手段往容器中增加元素,范围for循环输出的容器中元素就会混乱。其实,范围for语句等价于常规的用迭代器对容器进行操作。看如下代码:

    vector<int> vecvalue{1,2,3,4,5 };
    for (auto vecitem:vecvalue)
    {
        cout << vecitem <<endl;
    }

等价于迭代器这种操作方式:
在这里插入图片描述
但如果一旦在for循环中增删容器中的元素,就会导致迭代器失效,整个结果就混乱了。
其实,任何一种能够改变vector对象容量的操作,如push_back,都会使当前的vector对象迭代器失效,所以请读者谨记:在操作迭代器的过程中(使用了迭代器的这种循环体),千万不要改变vector对象的容量,也就是不要增加或者删除vector容器中的元素。看如下代码:
在这里插入图片描述
对于向容器中添加元素和从容器中删除元素操作要小心,因为这些操作可能都会使指向容器元素的迭代器(也包括指针、引用等)失效。这种失效就表示它不能再代表任何容器中的元素,一旦使用这种失效的迭代器,就表示程序的书写犯了严重错误,很多情况下都会导致程序崩溃,就好比使用了没有被初始化的指针一样。

不同的容器实现机理不同(例如有的容器内部数据是连续存储的,插入元素时一旦原有内存不够用,则可能就会导致容器中原有数据全部迁移到一个新内存去,如vector等容器),不同的插入操作、不同的插入位置,会导致迭代器、指针、引用部分或者全部失效,甚至在循环体中的诸如vecvalue.end()代码都会因为插入数据操作导致失效。

另一种情况是删除操作。如果从容器中删除一个元素,那么,当前指向这个被删除元素的迭代器、指针、引用肯定是立即失效,绝不能再引用它们。

此外,不同的容器,针对删除操作,不同的删除位置,也会导致迭代器、指针、引用部分或者全部失效,甚至在循环体中的诸如vecvalue.end()代码都会因为删除数据操作导致失效。

解决方法就是:如果在一个使用了迭代器的循环中插入元素到容器,那只插入一个元素后就应该立刻跳出循环体,不能再继续用这些迭代器操作容器。看看如下范例:
在这里插入图片描述
下面将进行一些灾难程序演示。
(1)灾难程序演示1
下面代码目前一切没有问题:
在这里插入图片描述
接着,往循环中增加代码,注意while循环体中代码的变化:
在这里插入图片描述
有些人可能有更多需求,例如就是想不断地插入多条数据,并且还希望迭代器不失效,那就得查资料研究,如研究针对vector容器,如何写insert这段代码,才能让迭代器不失效,让程序安全地运行。看如下代码,是一种满足连续插入多条数据的解决方案:
在这里插入图片描述

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

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

相关文章

量化交易全流程(一)

-----------------------------------前沿介绍-------------------------------------- 量化投资基本概念&#xff1a;凡是借助于数学模型和计算机实现的投资方法都可以成为量化投资&#xff0c;多因子策略&#xff0c;期货CTA策略&#xff0c;套利策略和高频交易策略。 量化…

一片编程文章

前言&#xff1a;相信看到这篇文章的小伙伴都或多或少有一些编程基础&#xff0c;懂得一些linux的基本命令了吧&#xff0c;本篇文章将带领大家服务器如何部署一个使用django框架开发的一个网站进行云服务器端的部署。 文章使用到的的工具 Python&#xff1a;一种编程语言&…

QQ聊天记录删除了怎么恢复?果粉都是这么做的

QQ自1999年推出以来就广受欢迎&#xff0c;在这二十多年里&#xff0c;QQ已经建立起了庞大的用户基础。即使微信崛起&#xff0c;仍旧有很多小伙伴不愿“抛弃”QQ。在使用QQ的过程中&#xff0c;您是否会遇到误删聊天记录的情况&#xff1f;qq聊天记录删除了怎么恢复&#xff1…

赋能工业物联网 | 数据驱动,加速智能制造

行业背景 工业物联网场景下&#xff0c;随着智能设备及物联网技术的广泛应用&#xff0c;数据是最重要的资源之一&#xff0c;企业需要对各种机器、设备和传感器产生的时序数据进行采集、存储与分析。 因此&#xff0c;何为行之有效的数据库解决方案&#xff1f;企业普遍更为…

Charles基础使用指南

##Charles 基本使用指南 Charles 在本地构建一个HTTP代理服务器&#xff0c;可以实现对HTTP、HTTPS请求的抓取&#xff0c;也就是我们常说的抓包&#xff0c;以及对请求响应的修改等。 Charles 官网地址 https://www.charlesproxy.com/ ###一、移动端的抓包实现 1. PC端开启…

3招“挽回”:微信怎么恢复聊天记录

由于工作需要&#xff0c;经常使用微信与客户对接。害怕内存不足&#xff0c;所以我每个月都会清理一些不需要的文件&#xff0c;结果却不小心误删了与客户的聊天记录&#xff0c;有什么方法能够恢复回来吗&#xff1f; 聊天记录是微信的一个重要组成部分&#xff0c;里面保存着…

基于javaweb的CT图像管理系统(servlet+jsp)

系统简介 本项目采用eclipse工具开发&#xff0c;jspservletjquery技术编写&#xff0c;数据库采用的是mysql&#xff0c;navicat开发工具。 三个角色&#xff1a;管理员&#xff0c;普通用户&#xff0c;医生 模块简介 管理员&#xff1a; 1、登录 2、用户管理 3、医生管…

科技部副部长:以负责任的态度推动大模型发展,加强国际交流合作

源自&#xff1a;澎湃新闻 ChatGPT大模型技术拉开了迈向通用人工智能的序幕&#xff0c;通用人工智能将引发经济、社会、文化等领域的变革&#xff0c;有望推进人类社会迈向智能增强的时代。 要坚持开源协作&#xff0c;加强大模型技术持续创新&#xff0c;协同解决透明性、稳…

SEO优化的优势(让你的网站脱颖而出)

随着互联网技术的快速发展&#xff0c;现如今每个企业或个人都拥有自己的网站。然而&#xff0c;要想在竞争激烈的网络世界中脱颖而出并吸引更多的用户&#xff0c;SEO优化就显得尤为重要。在本文中&#xff0c;我们将详细介绍SEO优化所带来的优势。 一&#xff1a;提高网站排名…

电子电路学习笔记之NCV84120DR2G——车规级单通道高压侧驱动器

关于车规级芯片&#xff1a; 关于车规级芯片&#xff08;Automotive Grade Chip&#xff09;&#xff0c;车规级芯片是专门用于汽车行业的芯片&#xff0c;具有高可靠性、高稳定性和低功耗等特点&#xff0c;以满足汽车电子系统的严格要求。这些芯片通常用于车载电子控制单元&…

数据库深分页介绍及优化方案 | 京东云技术团队

在前端页面显示&#xff0c;为了避免一次性展示全量数据&#xff0c;通过上下翻页或指定页码的方式查看部分数据&#xff0c;就像翻书一样&#xff0c;这就利用了MySQL的分页查询。 一、MySQL的深分页 查询偏移量过大的分页会导致数据库获取数据性能低下&#xff0c;以如下SQ…

vue设置全局变量:让你的数据无处不在!

前言 在 vue 开发中&#xff0c;如何设置全局变量是一个关键问题。本文将介绍多种方法&#xff0c;帮助大家轻松实现全局变量的共享&#xff0c;提升 vue 项目的开发效率。让我们一起来探索这些方法&#xff0c;为你的 vue 项目带来更好的开发体验。 方法一&#xff1a;使用 Vu…

Simulink搭建C语言仿真模型*

Simulink搭建C语言仿真模型 1、 在library库中查找S-Function Builder模块&#xff0c;拖入到空白区&#xff1b; 2、 该模块即为C语言代码模块&#xff0c;双击该模块&#xff0c;在Initialization栏&#xff0c;设置sample mode为离散采样&#xff0c;采样时间间隔Sample ti…

fastjson(反序列化)漏洞复现

fastjson 1. 漏洞描述 ​ FastJson是Alibaba的一款开源Json解析库&#xff0c;可用于将Java对象转换为其Json表示形式&#xff0c;也可以用于将Json字符串转换为等效的Java对象。近几年来FastJson漏洞层出不穷。RCE漏洞的源头&#xff1a;17年FastJson爆出的1.2.24反序列化漏…

软件测试报告加盖和不加盖CMA/CNAS标识的区别有哪些?

一、CNAS是什么&#xff1f; “CNAS”是China National Accreditation Service for Conformity Assessment&#xff08;ZG合格评定国家认可委员会&#xff09;的英文缩写。zg合格评定国家认可委员会的规定&#xff0c;由国家认证认可监督管理委员会批准设立并授权的国家认可机…

在群晖上安装Nextcloud-AIO详解

本文是应网友 刘源 的要求折腾的&#xff1b; 什么是 Nextcloud AIO &#xff1f; Nextcloud AIO 就是 Nextcloud All-in-One &#xff0c;顾名思义就是一个 Nextcloud 的 All-in-One 版本&#xff0c;这是一个基于 Docker 的项目&#xff0c;它允许仅安装一个容器&#xff0c;…

苹果铃声怎么设置?3招教你设置个性化铃声!

苹果手机因其颜值、性能与生态吸引了一大批粉丝用户。在拿到新手机后&#xff0c;大家第一时间就是给手机设置好听的铃声。那么&#xff0c;苹果铃声怎么设置呢&#xff1f;手机铃声能设置成自己喜欢的歌曲吗&#xff1f;当然可以了&#xff01;本文将给大家介绍3种轻松设置苹果…

文件上传16.17关

二次渲染-Pass-16 直接看源码&#xff1a; 我们还是按照13&#xff0c;14&#xff0c;15的思路进行上传&#xff1a;发现没有info信息了。 二次渲染的时候把码的信息给干掉了。怎么办呢&#xff1f; 把原图和他修改过的图片进行比较&#xff0c;看看哪个部分没有被修改。将p…

轻松整理文件,让你的电脑更有条理!尝试按名称归类方法

文件管理是我们日常计算机使用中经常面临的一项任务。有时候&#xff0c;我们可能需要对电脑中大量的文件进行分类整理&#xff0c;而手动一个个处理无疑是繁琐且耗时的。为了提高效率&#xff0c;许多文件批量高手软件应运而生。 文件批量高手软件是一种能够按文件名称批量归…

常见气体摩尔体积

参考链接 固体和气体的摩尔体积 - 百度文库 (baidu.com) 特此记录 anlog 2023年8月7日