【C++提高编程-03】----C++之STL常用容器基础实战

news2024/11/24 22:52:40

🎩 欢迎来到技术探索的奇幻世界👨‍💻

📜 个人主页:@一伦明悦-CSDN博客

✍🏻 作者简介: C++软件开发、Python机器学习爱好者

🗣️ 互动与支持💬评论      👍🏻点赞      📂收藏     👀关注+

如果文章有所帮助,欢迎留下您宝贵的评论,

点赞加收藏支持我,点击关注,一起进步!

前言

     STL(Standard Template Library)是C++标准库中的一个重要组成部分,提供了一系列通用的模板类和函数,用于实现常见的数据结构和算法。STL容器是STL中最常用的组件之一,用于存储和管理数据。以下是关于STL容器的详细介绍:

  1. 序列容器

    • vector:动态数组,支持随机访问和动态大小调整。
    • deque:双端队列,支持在两端快速插入和删除元素。
    • list:双向链表,支持高效的插入和删除操作。
  2. 关联容器

    • set:基于红黑树的有序集合。
    • map:基于红黑树的有序映射(键-值对)。
    • multiset:允许重复值的有序集合。
    • multimap:允许重复键的有序映射。
  3. 无序关联容器

    • unordered_set:基于哈希表的无序集合。
    • unordered_map:基于哈希表的无序映射。
    • unordered_multiset:允许重复值的无序集合。
    • unordered_multimap:允许重复键的无序映射。
  4. 容器适配器

    • stack:栈,基于deque或list实现。
    • queue:队列,基于deque或list实现。
    • priority_queue:优先队列,基于vector实现。
  5. 智能指针

    • shared_ptr:共享所有权的智能指针,基于引用计数实现。
    • unique_ptr:独占所有权的智能指针,禁止复制。
    • weak_ptr:弱引用智能指针,不增加引用计数。

        STL容器提供了丰富的接口和算法,使得数据的存储、操作和管理变得更加便捷和高效。在使用STL容器时,可以根据具体需求选择合适的容器类型,并结合迭代器、算法等功能来完成复杂的数据处理任务。STL容器的广泛应用也使得C++成为一种强大的编程语言,适用于各种领域的开发和编程。

正文

01-STL基础知识

        STL(Standard Template Library)是C++标准库的一部分,提供了一套通用的模板类和函数,用于实现常见的数据结构和算法。STL包括容器(Containers)、算法(Algorithms)和迭代器(Iterators)三大组件,为C++程序员提供了丰富、高效的数据结构和算法支持。

/*  长久以来,软件界一直希望建立一种可重复利用的东西
    C++的面向对象和泛型编程思想,目的就是复用性的提升
    大多情况下,数据结构和算法都未能有一套标准,导致被迫从事大量重复工作
    为了建立数据结构和算法的一套标准,诞生了STL
*/

//  STL(Standard Template Library,标准模板库)
//  STL广义上分为容器(container)、算法(algorithm)、迭代器(iterator)
//  容器和算法之间通过迭代器进行无缝连接。
//  STL 几乎所有的代码都采用了模板类或者模板函数

//  STL六大组件:容器,算法,迭代器,仿函数,适配器,空间配置器

/*  1、容器分为两种  12354
    序列式容器: 强调值的排序,序列式容器中的每个元素均有固定的位置。 12354   按初始位置
    关联式容器: 二叉树结构,各元素之间没有严格的物理上的顺序关系     12345   按顺序排序
*/


/*  2、质变算法和非质变算法。    12345
    质变算法:是指运算过程中会更改区间内的元素的内容。例如拷贝,替换,删除等等      1234  改变值
    非质变算法:是指运算过程中不会更改区间内的元素内容,例如查找、计数、遍历、寻找极值等等    12345  并未改变

*/

/*  3、提供一种方法,使之能够依序寻访某个容器所含的各个元素,而又无需暴露该容器的内部表示方式。
      每个容器都有自己专属的迭代器,迭代器使用非常类似于指针,初学阶段我们可以先理解迭代器为指针

      双向迭代器 读写操作,并能向前和向后操作 读写,支持++、--,

      随机访问迭代器  读写操作,可以以跳跃的方式访问任意数据,功能最强的迭代器
      读写,支持++、--、[n]、-n、<、<=、>、>=
      常用的容器中迭代器种类为双向迭代器,和随机访问迭代器

*/

        容器(Containers)

  • 容器是STL中最重要的组成部分之一,用于存储和管理数据。常见的STL容器包括 vector、deque、list、set、map 等。下面以 vector 和 map 容器为例进行具体的代码分析:

  • vector(动态数组):用于存储动态大小的元素序列,支持随机访问和动态增删操作,是使用最频繁的容器之一。

#include <iostream>
#include <vector>
using namespace std;

int main() {
    // 创建一个存储 int 类型数据的 vector
    vector<int> vec;

    // 向 vector 中添加数据
    vec.push_back(10);
    vec.push_back(20);
    vec.push_back(30);

    // 遍历 vector 中的数据
    for (int i = 0; i < vec.size(); ++i) {
        cout << vec[i] << " ";
    }

    return 0;
}

        map(映射):用于存储键值对的集合,支持快速的查找和插入操作,适合用于建立键到值的映射关系。

#include <iostream>
#include <map>
using namespace std;

int main() {
    // 创建一个存储 string 类型键和 int 类型值的 map
    map<string, int> myMap;

    // 插入键值对
    myMap["apple"] = 10;
    myMap["banana"] = 20;
    myMap["orange"] = 30;

    // 遍历 map 中的键值对
    for (const auto &pair : myMap) {
        cout << pair.first << ": " << pair.second << endl;
    }

    return 0;
}

        算法(Algorithms)

  • STL中还提供了丰富的算法函数,用于对容器中的数据进行操作,例如排序、查找、变换等。这些算法函数可以结合容器和迭代器进行灵活的数据处理。
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

int main() {
    vector<int> vec = {3, 1, 4, 1, 5, 9, 2, 6, 5};

    // 对 vector 中的数据进行排序
    sort(vec.begin(), vec.end());

    // 遍历排序后的 vector
    for (int num : vec) {
        cout << num << " ";
    }

    return 0;
}

         STL通过提供丰富、高效的容器和算法,简化了C++程序的开发过程,提高了代码的可读性和可维护性。程序员可以灵活运用STL中的容器和算法来处理数据,在实际开发中大大提高了开发效率。通过深入学习STL的使用,程序员能够更好地掌握C++编程技能,写出高质量的代码。

02-Vector数组-存放内置数据类型

        Vector是C++标准库中的一种容器,用于存储一组同类型的元素,其中也可以存放内置数据类型。下面详细解释Vector数组存放内置数据类型的相关内容:

  1. 定义和声明

    • 使用vector需要包含头文件 <vector>
    • 可以通过声明 vector<数据类型> 变量名 来定义一个vector。
  2. 初始化

    • 可以通过赋值语句、列表初始化、拷贝初始化等方式进行初始化。
  3. 插入和删除元素

    • 使用 push_back() 方法在vector末尾插入元素。
    • 使用 pop_back() 方法删除vector末尾的元素。
    • 使用 insert() 方法在指定位置插入元素。
    • 使用 erase() 方法删除指定位置或指定范围的元素。
  4. 访问元素

    • 可以使用下标访问 [] 或 at() 方法访问指定位置的元素。
    • 可以使用迭代器进行元素访问。
  5. 动态调整大小

    • Vector可以动态调整大小,即在运行时改变元素数量,使用 resize() 方法实现。
  6. 内存管理

    • Vector自动管理内存,当元素数量超过当前容量时,会自动扩展容量以容纳更多元素。
  7. 常用操作

    • size():返回vector中元素的个数。
    • empty():判断vector是否为空。
    • clear():清空vector中的所有元素。
    • swap():交换两个vector的内容。

示例代码

#include <iostream>
#include <vector>
using namespace std;

int main() {
    // 定义一个存放整数的vector
    vector<int> vec;

    // 向vector中插入元素
    vec.push_back(10);
    vec.push_back(20);
    vec.push_back(30);

    // 遍历vector并输出元素
    for (int i = 0; i < vec.size(); ++i) {
        cout << vec[i] << " ";
    }
    cout << endl;

    // 使用迭代器访问元素
    vector<int>::iterator it;
    for (it = vec.begin(); it != vec.end(); ++it) {
        cout << *it << " ";
    }
    cout << endl;

    // 删除末尾的元素
    vec.pop_back();

    // 重新遍历vector并输出元素
    for (int num : vec) {
        cout << num << " ";
    }
    cout << endl;

    return 0;
}

        下面给出具体代码分析应用过程:这段代码主要展示了使用vector存放内置数据类型(这里是整型数据)并遍历输出的过程。以下是对这部分代码的简要分析:

        头文件引入和命名空间声明:引入了 <iostream><vector> 和 <algorithm> 头文件。使用了 std 命名空间,可以直接使用 std::cout 和 std::endl 等符号,避免了在代码中频繁写 std::

        定义了自定义函数 myPrint:函数 myPrint 的作用是输出传入的整数参数,并换行。该函数用于 for_each 算法的回调函数。

   test01 函数:在函数 test01 中,首先创建了一个 vector<int> 容器 v,并向其中插入了四个整数元素(10、20、30、40)。注释掉了使用迭代器进行遍历的代码,通过两种不同的注释掉代码段可以看到迭代器遍历方式的不同,包括 while 和 for 循环遍历方式。使用 for_each 算法对 v 容器中的元素进行遍历,并通过回调函数 myPrint 输出每个元素。

   main 函数:在 main 函数中调用了 test01 函数,展示了如何使用 vector 存放数据并进行遍历输出。最后通过 system("pause") 命令使程序在执行完毕后暂停,防止窗口一闪而过。

        总体来说,这段代码通过展示了使用 vector 存放整型数据并使用不同的方法进行遍历输出,同时使用 for_each 算法简化了遍历的过程。通过这段代码可以了解如何使用 vector 容器和一些基本的STL算法,提高代码的可读性和简洁性。

#include <iostream>
using namespace std;
#include <vector>     // 包含数组容器的头文件
#include <algorithm>   // 使用STL中包含的算法时,必须包含这个头文件

// vector 存放内置数据类型   和模板那里很像

void myPrint(int val)
{
	cout << val << endl;
}

void test01()
{
	// 创建一个int类型的vector容器,数组
	vector<int> v;

	// 向容器中插入数据
	v.push_back(10);
	v.push_back(20);
	v.push_back(30);
	v.push_back(40);

	// 通过迭代器访问元素   iterator 迭代器相当于一个指针,因此取出数据时使用解引用方式
// 	vector<int>::iterator itBegin = v.begin();  // 起始迭代器,指向容器中第一个元素
// 	vector<int>::iterator itEnd = v.end();      // 结束迭代器,指向容器中最后一个元素的后面一个位置,相当于指向空元素
// 
// 	// 第一种遍历方式
// 	while (itBegin!=itEnd)     // 这里需要加一个判断语句,当元素指向到于itEnd相同时,则不再进行输出
// 	{
// 		cout << *itBegin << endl;  // 容器相当于一个指针,使用解引用的方式取出数据
// 		itBegin++;            // 指针遍历数组,需要对指针进行++操作,因为数组中一个元素占有4个字节,而指针也是占有4个字节
// 
// 	}

	// 第二种方式,使用for循环  第一种太过于复杂
// 	for (vector<int>::iterator it = v.begin(); it != v.end();it++)
// 	{
// 		cout << *it << endl;
// 	}
	// 第三中使用算法  遍历算法 for_each 
	for_each(v.begin(), v.end(), myPrint);   // 算法中传入三个参数  起始迭代器,结束迭代器,函数回调
	//  这里myPrint()函数传入参数为使用指针的主要原因,是因为,算法内部已经做了解引用的操作,因此返回的就是一个整型数据,并不是地址,
	//  那么函数中传入参数,也不需要在加指针



}

int main() {
    
	test01();
	system("pause");
	return 0;
}

03-Vector存放自定义数据类型

        当向vector容器中存放自定义的数据类型时,通常需要注意以下几个方面:

  1. 定义自定义数据类型

    • 首先需要定义一个自定义的数据类型,可以是类或结构体。这个数据类型可以包含多个不同类型的成员变量,表示自定义的数据结构。
    • 在定义类或结构体时,通常需要重载比较运算符或提供自定义的排序规则,以便在vector中对自定义数据类型进行排序和查找操作。
  2. vector中存储自定义数据类型

    • 创建一个vector容器,容器的模板参数为自定义的数据类型。
    • 使用push_back()函数向vector容器中添加自定义数据类型的对象。
  3. 遍历和访问

    • 可以通过下标操作或迭代器遍历vector中存储的自定义数据类型对象。
    • 也可以使用算法函数对vector中的自定义数据类型对象进行处理,比如排序、查找等操作。

        下面是一个简单的示例代码,展示了如何在vector容器中存储自定义的数据类型(这里以学生类为例)并遍历输出:

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

// 自定义学生类
class Student {
public:
    string name;
    int age;

    Student(string n, int a) : name(n), age(a) {}
};

// 打印学生信息的函数
void printStudent(const Student &s) {
    cout << "Name: " << s.name << ", Age: " << s.age << endl;
}

int main() {
    // 创建一个存放学生对象的vector
    vector<Student> students;

    // 向vector中插入学生对象
    students.push_back(Student("Alice", 20));
    students.push_back(Student("Bob", 22));
    students.push_back(Student("Cathy", 21));

    // 遍历vector并输出学生信息
    for_each(students.begin(), students.end(), printStudent);

    return 0;
}

        下面给出具体代码分析应用过程:这段代码演示了在vector容器中存放自定义数据类型(Person类)的两种方式:一种是存放对象本身,另一种是存放对象的指针。接下来是对这段代码的简要解释:

  1. 定义自定义数据类型 Person

    • Person 类包括 m_Name 和 m_Age 两个成员变量,分别表示人的姓名和年龄。
    • 类中定义了构造函数,用来初始化 Person 对象的姓名和年龄。
  2. test01 函数

    • 首先创建一个vector<Person>类型的容器v
    • 实例化了五个 Person 对象,并通过push_back方法将它们添加到容器中。
    • 使用迭代器遍历容器中的元素,通过 it->m_Name 和 it->m_Age 访问每个 Person 对象的姓名和年龄进行输出。
  3. test02 函数

    • 创建了一个vector<Person*>类型的容器v,存放的是 Person 对象的指针。
    • 将五个 Person 对象的地址添加到容器中。
    • 使用迭代器遍历容器中的元素,通过 (*it)->m_Name 和 (*it)->m_Age 访问每个 Person 对象的姓名和年龄进行输出,这里使用指针的箭头操作符 -> 来访问指针指向的对象的成员变量。
  4. main 函数

    • 在 main 函数中依次调用了 test01 和 test02 函数,展示了两种不同存储方式的遍历输出结果。
    • 最后通过 system("pause"); 命令使程序在执行完毕后暂停,防止窗口一闪而过。

        通过这段代码,展示了如何在vector容器中存放自定义数据类型对象或指针,并通过迭代器遍历容器中的元素进行访问和输出。同时也展示了对象指针和对象本身在vector中的存储和访问方式的差异。

#include <iostream>
using namespace std;
#include<vector>
#include<string>

// vector存放自定义数据类型   自定义person类型

class Person
{


public:

	// 使用构造函数赋初值
	Person(string name, int age)
	{
		this->m_Name = name;
		this->m_Age = age;
	}
	

	string m_Name;
	int m_Age;
};

void test01()
{

	vector<Person>v;

	// 创建实例化对象
	Person p1("A", 10);
	Person p2("B", 20);
	Person p3("C", 30);
	Person p4("D", 40);
	Person p5("E", 50);

	// 向容器中插入数据
	v.push_back(p1);
	v.push_back(p2);
	v.push_back(p3);
	v.push_back(p4);
	v.push_back(p5);

	// 遍历容器中元素

	for (vector<Person>::iterator it = v.begin(); it != v.end();it++)// 这里直接it++
	{
		// *it解引用出来的就是Person数据类型,如果需要用的话直接查找类里的成员属性即可
//		cout << "姓名:"<<(*it).m_Name <<" 年龄:"<<(*it).m_Age<< endl;   // 这里相当于又创建了实例化对象,需要取出成员属性
		cout << "姓名:" << it->m_Name << " 年龄:" << it->m_Age << endl;  // 因为it就是指针,也可以这样使用
	}


}

// 存放自定义数据类型   指针

void test02()
{
	vector<Person*>v;

	// 创建实例化对象
	Person p1("A", 10);
	Person p2("B", 20);
	Person p3("C", 30);
	Person p4("D", 40);
	Person p5("E", 50);

	// 向容器中插入数据
	v.push_back(&p1);
	v.push_back(&p2);
	v.push_back(&p3);
	v.push_back(&p4);
	v.push_back(&p5);

	// 现在存放进去的是一个地址,遍历方式
	for (vector<Person*>::iterator it = v.begin(); it != v.end();it++)
	{
		// 上面(*it)返回就是一个Person数据类型,相当于实例化对象,直接.成员属性就行
		// 而这里(*it)返回的是一个Person*数据类型,(*it)是Person类的指针,使用->取出数据
		cout << "姓名:" << (*it)->m_Name << " 年龄:" << (*it)->m_Age << endl;
	}
}


int main() {

	test01();
	test02();
	system("pause");
	return 0;
}

04-Vector容器嵌套容器

       当涉及到在vector容器中嵌套另一个容器时,通常会有一些需要注意的方面。这种情况下,你可以创建一个容器,该容器的元素是另一个容器,从而实现嵌套的效果。下面是关于在vector容器中嵌套容器的详细解释:

  1. 定义嵌套容器

    • 首先,需要定义内部容器和外部容器的数据类型。内部容器可以是任何STL容器,比如vectorlist等。
    • 外部容器的元素类型是内部容器,因此外部容器的模板参数是内部容器的类型。
  2. 操作嵌套容器

    • 创建外部容器时,需要指定内部容器的类型。
    • 向外部容器中添加元素时,每个元素都是一个内部容器的实例。
    • 可以通过外部容器的迭代器来遍历外部容器,并通过内部容器的迭代器来访问和操作内部容器中的元素。

        下面是一个简单的示例代码,演示了如何在vector容器中嵌套vector容器,并对嵌套容器进行操作:

        在这个示例代码中,nestedVector是一个vector容器,其中每个元素都是一个vector<int>类型的容器。通过将内部vector容器作为外部vector容器的元素,实现了嵌套容器的效果。通过两层循环,可以遍历外部容器和内部容器,并访问内部容器中的元素。

        嵌套容器提供了一种组织数据的方式,特别适用于需要多维数据结构的场景,如二维矩阵、多级索引等。

#include <iostream>
#include <vector>
using namespace std;

int main() {
    // 定义外部容器,元素类型是内部容器
    vector<vector<int>> nestedVector;

    // 添加内部容器到外部容器中
    nestedVector.push_back(vector<int>{1, 2, 3});
    nestedVector.push_back(vector<int>{4, 5});
    nestedVector.push_back(vector<int>{6, 7, 8, 9});

    // 遍历外部容器并访问内部容器中的元素
    for (const auto& innerVec : nestedVector) {
        for (int num : innerVec) {
            cout << num << " ";
        }
        cout << endl;
    }

    return 0;
}

        下面给出代码详细分析一下应用过程:这段代码演示了在vector容器中嵌套另一个vector容器的情况。下面是对代码的简要解释:

  1. 定义嵌套容器

    • 创建了一个外部vector<vector<int>>类型的容器v,其中每个元素都是一个内部vector<int>类型的容器。
    • 同时,定义了四个内部vector<int>类型的容器v1v2v3v4
  2. 操作内部容器

    • 在内部容器中,使用push_back方法向每个容器中插入一些整数数据。
  3. 将内部容器添加到外部容器

    • 将四个内部容器v1v2v3v4添加到外部容器v中,这样外部容器中就包含了四个内部容器。
  4. 遍历嵌套容器

    • 使用外部容器的迭代器遍历外部容器,得到内部容器。
    • 对于每个内部容器,再次使用内部容器的迭代器遍历,输出其中的元素。

        通过这段代码,展示了如何在vector容器中嵌套另一个vector容器,并且使用迭代器对嵌套容器进行遍历和访问。

#include <iostream>
using namespace std;
#include<vector>
#include<string>


// 容器嵌套容器


void test01()
{
	vector<vector<int>>v;   // 这里就相当于在大容器中,又加入了小容器,为int类型的数组

	// 在定义小容器
	vector<int>v1;
	vector<int>v2;
	vector<int>v3;
	vector<int>v4;
	// 小容器中插入数据   这一步是向小容器中插入数据,
	for (int i = 0; i < 4;i++)
	{
		v1.push_back(i + 1);
		v2.push_back(i + 2);
		v3.push_back(i + 3);
		v4.push_back(i + 4);
	}
	// 将容器元素插入到大容器中   这一步大容器中也需要有数据
	v.push_back(v1);
	v.push_back(v2);
	v.push_back(v3);
	v.push_back(v4);

	// 使用大容器遍历小容器
	for (vector<vector<int>>::iterator it = v.begin(); it != v.end();it++)
	{
		// 这个时候可以看出来 *it 返回的是一个vector<int> 也就是有时一个容器,因此还需要一次遍历
		for (vector<int>::iterator vit = (*it).begin(); vit != (*it).end();vit++)
		{
			cout << *vit << " ";
		}
		cout << endl;

	}


}

int main() {

	test01();
	system("pause");
	return 0;
}

        实例结果如下图所示: 

总结

     STL(Standard Template Library,标准模板库)是 C++ 标准库的一部分,提供了一组通用的模板类和函数,用于实现常见的数据结构和算法。以下是关于STL基础知识的总结:

  1. 容器(Containers)

    • 向量(Vector):动态数组,支持快速随机访问和在末尾插入元素。
    • 链表(List):双向链表,支持在任意位置进行插入和删除操作。
    • 队列(Queue):先进先出的队列。
    • 栈(Stack):后进先出的栈。
    • 映射(Map):关联数组,存储键-值对,并根据键快速查找值。
  2. 迭代器(Iterators)

    • 迭代器用于遍历容器中的元素,提供了统一的访问容器元素的接口。
    • 包括输入迭代器、输出迭代器、前向迭代器、双向迭代器和随机访问迭代器。
  3. 算法(Algorithms)

    • STL提供了各种算法,如排序、查找、变换和合并等。
    • 可以通过算法与迭代器结合对容器进行各种操作。
    • 一些常见算法包括sortfindtransformmerge等。
  4. 函数对象(Functors)

    • 函数对象是重载了operator()的类,可以像函数一样调用。
    • 可以自定义函数对象,并将其用于算法中,比如排序或查找。
  5. 适配器(Adapters)

    • 堆栈适配器(Stack Adapter):基于vectordeque实现的栈。
    • 队列适配器(Queue Adapter):基于dequelist实现的队列。
  6. 分配器(Allocators)

    • 分配器用于管理内存分配。
    • 可以自定义分配器并用于 STL 容器。
  7. 内置类型(Basic Types)

    • STL包含了一些内置类型,如pair用于存储一对值、tuple用于存储任意数量的值。

        总的来说,STL提供了一组灵活、高效且通用的工具,能够帮助我们更方便地实现各种数据结构和算法。熟练掌握STL的基础知识对于C++编程是非常重要的。   

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

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

相关文章

智简云携手云器Lakehouse打造一体化大数据平台,释放数据价值

导读 本篇分享的是智简云使用云器Lakehouse升级数据平台的实践总结。 智简云&#xff0c;是一家拥有十余年历史的科技公司&#xff0c;专注于企业服务领域&#xff0c;开发了两款核心产品&#xff1a;基于PASS平台的客户关系管理&#xff08;CRM&#xff09;系统和为中小型用…

加密与解密(第四版)】第二十三章笔记

第二十三章 代码的二次开发 23.1 数据对齐 23.2 增加空间 利用区块空隙&#xff08;注意区块属性&#xff09; 增加区块&#xff08;增加一个块头、增加块头指向的数据段、调整文件映像的尺寸&#xff08;SizeOfImage&#xff09;&#xff09; 23.3 获得函数的调用信息 修…

用Python的PyAutoGUI库控制鼠标滚轮

哈喽&#xff0c;大家好&#xff0c;我是木头左&#xff01; 轻松上手&#xff1a;安装与导入 要开始使用pyautogui库&#xff0c;你需要做的第一件事就是确保它已经被安装在你的Python环境中。你可以通过运行以下命令来安装&#xff1a; pip install pyautogui安装完成后&am…

【Web】CISCN 2024初赛 题解(全)

目录 Simple_php easycms easycms_revenge ezjava mossfern sanic Simple_php 用php -r进行php代码执行 因为ban了引号&#xff0c;考虑hex2bin&#xff0c;将数字转为字符串 php -r eval(hex2bin(16进制)); 注意下面这段报错&#xff0c;因为加不了引号&#xff0c;开…

稳定性大升级!EMCS全球服务网络携手NineData实现数据实时同步

易客满&#xff08;ECMS Express&#xff09;专注于提供全球化的国际物流解决方案和经济快递服务&#xff0c;服务网络覆盖全球主要贸易市场的国际物流公司。ECMS拥有国际快递、国际货代、仓储供应链全球覆盖服务能力。 1. 易客满&#xff08;ECMS&#xff09;数据复制的技术挑…

初始Java篇(JavaSE基础语法)—— 内部类

找往期文章包括但不限于本期文章中不懂的知识点&#xff1a; 个人主页&#xff1a;我要学编程(ಥ_ಥ)-CSDN博客 所属专栏&#xff1a;JavaSE 目录 内部类的概念 内部类的种类 使用举例&#xff1a; 1. 静态内部类&#xff1a; 2. 实例内部类 3. 局部内部类 4. 匿名内部…

跨境电商赛道,云手机到底能不能化繁为简?

当下国内电商背景&#xff1a; 从零售额的数据来看&#xff1a;随着互联网的普及和消费者购物习惯的改变&#xff0c;国内电商市场规模持续扩大。据相关数据显示&#xff0c;网络消费亮点纷呈&#xff0c;一季度全国网上零售额达到了3.3万亿元&#xff0c;同比增长12.4%。这表…

linux 上除了shell、python脚本以外,还有什么脚本语言用得比较多?

在开始前我有一些资料&#xff0c;是我根据网友给的问题精心整理了一份「 Linux的资料从专业入门到高级教程」&#xff0c; 点个关注在评论区回复“888”之后私信回复“888”&#xff0c;全部无偿共享给大家&#xff01;&#xff01;&#xff01;说到在 Linux下的编程&#xf…

TECHNIUM INTERNATIONAL: 利用 AI 和 TECHNIUM 矩阵协议引领区块链创新

在充满活力的加密货币和区块链技术领域&#xff0c;Technium International 以领军者的姿态迅速崛起&#xff0c;跻身科技巨头的顶尖行列。Technium International 成立于 2018 年&#xff0c;总部设于塞席尔&#xff0c;透过人工智慧&#xff08;AI&#xff09;和区块链技术的…

云计算-基础设施和管理机制(Infrastructure and Management Mechanisms)

逻辑网络边界&#xff08;Logical Network Perimeter&#xff09; 逻辑网络边界是软件控制的虚拟网络&#xff0c;它是物理网络的一部分。其主要思想是隔离逻辑网络&#xff0c;防止不希望的访问&#xff0c;同时仍然为合法用户提供访问权限。下图显示了云系统中一个简单的逻辑…

Windws MySQL 8.4 LTS的安装(保姆级教程)

Windws MySQL 8.4 LTS的安装&#xff08;保姆级教程&#xff09; 一、Mysql版本二、Mysql下载三、Mysql安装3.1 Mysql安装3.2 Mysql配置 四、Mysql环境变量配置五、验证Mysql 一、Mysql版本 美国时间 2024 年 4 月 30 日&#xff0c;Oracle正式发布了MySQL数据库8.0.37版本的更…

初步学习pygame,使用pygame搭建简单的窗口效果

在VSCode上使用pygame 第一步&#xff1a;创建 Python 虚拟环境 打开 VSCode 中的 Terminal&#xff08;在菜单栏中选择 View > Terminal&#xff09;使用 cd 命令切换到你的项目文件夹输入以下命令来创建一个新的虚拟环境&#xff1a; python3 -m venv env这将在你的项目…

机械臂与Realsense D435 相机的手眼标定ROS包

本教程主要介绍机械臂与 Realsense D435 相机手眼标定的配置及方法。 系统&#xff1a;Ubuntu 20.0.4 ◼ ROS&#xff1a;Noetic ◼ OpenCV 库&#xff1a;OpenCV 4.2.0 ◼ Realsense D435&#xff1a;librealsense sdk&#xff08;2.50.0&#xff09;、realsense-ros 功能包&…

electron调试自动更新,不触发下载进度解决方案

调试时候删除掉后缀是.blockmap的文件。如果你的代码在改动不大的情况下发布一个新版本。那个安装器可能会根据这个数据自动合成一个包&#xff0c;而不走网络路径。从而不触发下载进度。

初阶数据结构之双向链表详解

目录 一&#xff1a;双向链表的概念 1.什么是双向链表&#xff1f; 2.双向链表的优点 3.双向链表的结构 二&#xff1a;双向链表的实现 1.定义链表结点 2.初始化双向链表 3.添加结点 4.尾插 5.头插 6.打印双向链表 7.查找链表结点 8.在指定结点后插入新结点 9.删…

KMP算法【C++】

KMP算法测试 KMP 算法详解 根据解释写出对应的C代码进行测试&#xff0c;也可以再整理成一个函数 #include <iostream> #include <vector>class KMP { private:std::string m_pat;//被匹配的字符串std::vector<std::vector<int>> m_dp;//状态二维数组…

【iceberg】数据湖与iceberg调研与实战

文章目录 一. 为什么现在要强调数据湖1. 大数据架构发展历史2. Lambda架构与kappa架构3. 数据湖所具备的能力 二. iceberg是数据湖吗1. iceberg的诞生2. iceberg设计之table format从如上iceberg的数据结构可以知道&#xff0c;iceberg在数据查询时&#xff0c;1.查找文件的时间…

三、自定义信号和槽函数(无参和有参)

需求&#xff1a; 下班后&#xff0c;小明说请小红吃好吃的&#xff0c;随便吃&#xff0c;吃啥买啥 无参&#xff1a;小红没有提出吃啥 有参&#xff1a;小红提出自己想吃的东西&#xff0c;吃啥取决于一时兴起&#xff08;emit触发&#xff09; 思路&#xff1a; 1&#xff…

【数据结构】排序详解(希尔排序,快速排序,堆排序,插入排序,选择排序,冒泡排序)

目录 0. 前情提醒&#xff1a; 1. 插入排序 1.1 基本思想&#xff1a; 1.2 直接插入排序 实现步骤&#xff1a; 动图演示&#xff1a; 特性总结&#xff1a; 代码实现&#xff1a; 1.3 希尔排序&#xff08;缩小增量排序&#xff09; 基本思想&#xff1a; 步骤演示&…

谷歌上架,个人号比企业号好上?“14+20”封测如何解决,你知道了吗

在Google Play上架应用&#xff0c;对开发者而言&#xff0c;既是挑战也是机遇。随着谷歌政策的不断更新&#xff0c;特别是要求2023年11月13日后注册的个人开发者账号在发布正式版应用前&#xff0c;必须经过20人连续14天的封闭测试。 这一政策的改变使得许多开发者开始考虑使…