C++ STL之容器(使用方法)

news2024/11/24 0:00:42

目录

  • 1. 容器简介
  • 2. String
    • 2.1 构造操作
    • 2.2 赋值操作
    • 2.3 常用操作(存取字符串、拼接、 查找、替换、比较、插入、删除)
  • 3. Vector
    • 3.1 构造操作
    • 3.2 赋值操作
    • 3.3 常用操作(大小、 查找、替换、比较、插入、删除)
  • 4. Deque
    • 4.1 构造操作
    • 4.2 赋值操作
    • 4.3 常用操作(大小、插入、删除、存取)
  • 5. Stack
    • 5.1 构造操作
    • 5.2 赋值操作
    • 5.3 存取操作
    • 5.4 大小操作
  • 6. Queue
    • 6.1 构造操作
    • 6.2 赋值操作
    • 6.3 存取操作
    • 6.4 大小操作
  • 7. List
    • 7.1 构造操作
    • 7.2 赋值操作
    • 7.3 存取操作
    • 7.4 常用操作(插入、删除、大小、排序)
  • 8. Set/Multiset
    • 8.1 构造操作
    • 8.2 赋值操作
    • 8.3 常用操作(大小、插入、删除、查找)
  • 9. Map/Multimap
    • 9.1 构造操作
    • 9.2 赋值操作
    • 9.3 常用操作(大小、插入、删除、查找)
  • 10. unordered_set/multiset、unordered_map/multimap
  • 11. 容器使用时机

1. 容器简介

       容器就是数据结构,用来将数据元素按照一定的规则进行排列,不同的容器拥有不同的排列规则,不同的排列规则可以达到不同的数据操作特点。容器只需要提供迭代器 算法只需要拿到迭代器就可以完成容器和算法之间的关联和操作

  • 顺序容器:数组(array),动态数组(vector),双向队列(deque),双向链表(list),单向链表(forward_list),字符串(string)
  • 关联容器:map、set、multimap、multiset、unordered_set、unordered_map、unordered_multiset、unordered_multimap
  • 容器适配器:单向队列(queue),栈(stack)

Alt
Alt
alt

2. String

       string 封装了 char*,管理这个字符串,是一个 char*型的容器。string 管理 char*所分配的内存。每一次 string 的复制,取值都由 string 类负责维护,不用担心复制越界和取值越界等。

2.1 构造操作

string();//创建一个空的字符串 例如: string str;
string(const string& str);//使用一个 string 对象初始化另一个 string 对象
string(const char* s);//使用字符串 s 初始化
string(int n, char c);//使用 n 个字符 c 初始化
//例子:
//默认构造函数
string s1;
//拷贝构造函数
string s2(s1);
string s2 = s1;
//带参数构造函数
char* str = "itcast";
string s3(str);
string s4(10, 'a');

2.2 赋值操作

string& operator=(const char* s);//char*类型字符串 赋值给当前的字符串
string& operator=(const string &s);//把字符串 s 赋给当前的字符串
string& operator=(char c);//字符赋值给当前的字符串
string& assign(const char *s);//把字符串 s 赋给当前的字符串
string& assign(const char *s, int n);//把字符串 s 的前 n 个字符赋给当前的字符串
string& assign(const string &s);//把字符串 s 赋给当前字符串
string& assign(int n, char c);//用 n 个字符 c 赋给当前字符串
string& assign(const string &s, int start, int n);//将 s 从 start 开始 n 个字符赋值给字符串

2.3 常用操作(存取字符串、拼接、 查找、替换、比较、插入、删除)

//存取字符串
char& operator[](int n);//通过[]方式取字符,越界程序挂掉
char& at(int n);//通过 at 方法获取字符,越界会抛出异常

string s = "itcast";
char c = s[1];
c = s.at(1);

//拼接
string& operator+=(const string& str);//重载+=操作符
string& operator+=(const char* str);//重载+=操作符
string& operator+=(const char c);//重载+=操作符
string& append(const char *s);//把字符串 s 连接到当前字符串结尾
string& append(const char *s, int n);//把字符串 s 的前 n 个字符连接到当前字符串结尾
string& append(const string &s);//同 operator+=()
string& append(const string &s, int pos, int n);//把字符串 s 中从 pos 开始的 n 个字符连接到当前字符串结尾
string& append(int n, char c);//在当前字符串结尾添加 n 个字符 c

//查找和替换
int find(const string& str, int pos = 0) const; //查找 str 第一次出现位置,从 pos 开始查找
int find(const char* s, int pos = 0) const; //查找 s 第一次出现位置,从 pos 开始查找
int find(const char* s, int pos, int n) const; //从 pos 位置查找 s 的前 n 个字符第一次位置
int find(const char c, int pos = 0) const; //查找字符 c 第一次出现位置
int rfind(const string& str, int pos = npos) const;//查找 str 最后一次位置,从 pos 开始查找
int rfind(const char* s, int pos = npos) const;//查找 s 最后一次出现位置,从 pos 开始查找
int rfind(const char* s, int pos, int n) const;//从 pos 查找 s 的前 n 个字符最后一次位置
int rfind(const char c, int pos = 0) const; //查找字符 c 最后一次出现位置
string& replace(int pos, int n, const string& str); //替换从 pos 开始 n 个字符为字符串 str
string& replace(int pos, int n, const char* s); //替换从 pos 开始的 n 个字符为字符串 s

//比较
int compare(const string &s) const;//与字符串 s 比较,等于时返回0
int compare(const char *s) const;//与字符串 s 比较,等于时返回0

//切割子串
string substr(int pos = 0, int n = npos) const;//返回由 pos 开始的 n 个字符组成的字符串

//插入删除
string& insert(int pos, const char* s); //插入字符串
string& insert(int pos, const string& str); //插入字符串
string& insert(int pos, int n, char c);//在指定位置插入 n 个字符 c
string& erase(int pos, int n = npos);//删除从 Pos 开始的 n 个字符

3. Vector

       vector 是个动态数组,连续内存空间,随机存取效率高。当空间不足的时候插入新元素,vector 会重新申请一块更大的内存空间(每次增长一倍),将旧空间数据拷贝到新空间,然后释放旧空间。vector 是单口容器,所以在尾端插入和删除元素效率较高,在指定位置插入,势必会引起数据元素移动,效率较低
在这里插入图片描述

3.1 构造操作

vector<T> v; //采用模板实现类实现,默认构造函数
vector(v.begin(), v.end());//将 v[begin(), end())区间中的元素拷贝给本身。
vector(n, elem);//构造函数将 n 个 elem 拷贝给本身。
vector(const vector &vec);//拷贝构造函数。
//例子 使用第二个构造函数 我们可以...
int arr[] = {2,3,4,1,9};
vector<int> v1(arr, arr + sizeof(arr) / sizeof(int));

3.2 赋值操作

assign(beg, end);//将[beg, end)区间中的数据拷贝赋值给本身。
assign(n, elem);//将 n 个 elem 拷贝赋值给本身。
vector& operator=(const vector &vec);//重载等号操作符
swap(vec);// 将 vec 与本身的元素互换,实际交换彼此的指针
//第一个赋值函数,可以这么写:
int arr[] = { 0, 1, 2, 3, 4 };
assign(arr, arr + 5);//使用数组初始化 vector

3.3 常用操作(大小、 查找、替换、比较、插入、删除)

//大小
size();//返回容器中元素的个数
empty();//判断容器是否为空
resize(int num);//重新指定容器的长度为 num,若容器变长,则以默认值填充新位置。如果容器变短,则末尾超出容器长度的元素被删除。
resize(int num, elem);//重新指定容器的长度为 num,若容器变长,则以 elem 值填充新位置。如果容器变短,则末尾超出容器长>度的元素被删除。
capacity();//容器的容量,因为当容空间器不够时会⾃动扩充空间 ,但不⼀定都会填满,所以可能与size()不等
reserve(int len);//容器预留 len 个元素长度,预留位置不初始化,元素不可访问。
//reserve 是容器预留空间,但在空间内不真正创建元素对象,所以在没有添加新的对象之前,不能引用容器内的元素
//resize 是改变容器的大小,且在创建对象,因此,调用这个函数之后,就可以引用容器内的对象了.

//存取
at(int idx); //返回索引 idx 所指的数据,如果 idx 越界,抛出 out_of_range 异常。
operator[];//返回索引 idx 所指的数据,越界时,运行直接报错
front();//返回容器中第一个数据元素
back();//返回容器中最后一个数据元素

//插入和删除
insert(const_iterator pos, int count,ele);//迭代器指向位置 pos 插入 count 个元素 ele.
push_back(ele); //尾部插入元素 ele
pop_back();//删除最后一个元素
erase(const_iterator start, const_iterator end);//删除迭代器从 start 到 end 之间的元素
erase(const_iterator pos);//删除迭代器指向的元素
clear();//删除容器中所有元素

4. Deque

       deque 则是一种双向开口的连续性空间,所谓双向开口,意思是可以在头尾两端分别做元素的插入和删除操作,vector 当然也可以在头尾两端进行插入和删除操作,但是头部插入和删除操作效率奇差,无法被接受。deque是动态的以分段的连续空间组合而成,随时可以增加一段新的空间并链接起来,由中控器来维持连续的假象
在这里插入图片描述
在这里插入图片描述

4.1 构造操作

deque<T> deqT;//默认构造形式
deque(beg, end);//构造函数将[beg, end)区间中的元素拷贝给本身。
deque(n, elem);//构造函数将 n 个 elem 拷贝给本身。
deque(const deque &deq);//拷贝构造函数。

4.2 赋值操作

assign(beg, end);//将[beg, end)区间中的数据拷贝赋值给本身。
assign(n, elem);//将 n 个 elem 拷贝赋值给本身。
deque& operator=(const deque &deq); //重载等号操作符
swap(deq);// 将 deq 与本身的元素互换

4.3 常用操作(大小、插入、删除、存取)

//大小
deque.size();//返回容器中元素的个数
deque.empty();//判断容器是否为空
deque.resize(num);//重新指定容器的长度为 num,若容器变长,则以默认值填充新位置。如果容器变短,则末尾超出容器长度的元素被删除。
deque.resize(num, elem); //重新指定容器的长度为 num,若容器变长,则以 elem 值填充新位置,如果容器变短,则末尾超出容器长度的元素被删除。

//插入和删除
push_back(elem);//在容器尾部添加一个数据
push_front(elem);//在容器头部插入一个数据
pop_back();//删除容器最后一个数据
pop_front();//删除容器第一个数据
insert(pos,elem);//在 pos 位置插入一个 elem 元素的拷贝,返回新数据的位置。
insert(pos,n,elem);//在 pos 位置插入 n 个 elem 数据,无返回值。
insert(pos,beg,end);//在 pos 位置插入[beg,end)区间的数据,无返回值。
at(idx);//返回索引 idx 所指的数据,如果 idx 越界,抛出 out_of_range。
operator[];//返回索引 idx 所指的数据,如果 idx 越界,不抛出异常,直接出错。
front();//返回第一个数据。
back();//返回最后一个数据

//存取
at(idx);//返回索引 idx 所指的数据,如果 idx 越界,抛出 out_of_range。
operator[];//返回索引 idx 所指的数据,如果 idx 越界,不抛出异常,直接出错。
front();//返回第一个数据。
back();//返回最后一个数据

5. Stack

       stack是一种先进后出(first in last out,FILO)的数据结构,它只有一个出口,stack 只允许在栈顶新增元素,移除元素,获得顶端元素,但是除了顶端之外,其他地方不允许存取元素,只有栈顶元素可以被外界使用,也就是说stack不具有遍历行为,没有迭代器
在这里插入图片描述

5.1 构造操作

stack<T> stkT;//stack 采用模板类实现, stack 对象的默认构造形式:
stack(const stack &stk);//拷贝构造函数

5.2 赋值操作

stack& operator=(const stack &stk);//重载等号操作符

5.3 存取操作

push(elem);//向栈顶添加元素
pop();//从栈顶移除第一个元素
top();//返回栈顶元素

5.4 大小操作

empty();//判断堆栈是否为空
size();//返回堆栈的大小

6. Queue

       queue 是一种先进先出(first in first out, FIFO)的数据类型,他有两个口,数据元素只能从一个口进,从另一个口出。队列只允许从队尾加入元素,队头删除元素,必须符合先进先出的原则,queue 和 stack 一样不具有遍历行为。
在这里插入图片描述

6.1 构造操作

queue<T> queT;//queue 采用模板类实现,queue 对象的默认构造形式:
queue(const queue &que);//拷贝构造函数

6.2 赋值操作

queue& operator=(const queue &que);//重载等号操作符

6.3 存取操作

push(elem);//往队尾添加元素
pop();//从队头移除第一个元素
back();//返回最后一个元素
front();//返回第一个元素

6.4 大小操作

empty();//判断队列是否为空
size();//返回队列的大小

7. List

       链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。STL中的list为双向链表,索引时迭代器可前进或后退。

  • 采用动态存储分配,不会造成内存浪费和溢出
  • 链表执行插入和删除操作十分方便,修改指针即可,不需要移动大量元素
  • 链表灵活,但是空间和时间额外耗费较大
    在这里插入图片描述

7.1 构造操作

list<T> lstT;//list 采用采用模板类实现,对象的默认构造形式:
list(beg,end);//构造函数将[beg, end)区间中的元素拷贝给本身。
list(n,elem);//构造函数将 n 个 elem 拷贝给本身。
list(const list &lst);//拷贝构造函数。

7.2 赋值操作

assign(beg, end);//将[beg, end)区间中的数据拷贝赋值给本身。
assign(n, elem);//将 n 个 elem 拷贝赋值给本身。
list& operator=(const list &lst);//重载等号操作符
swap(lst);//将 lst 与本身的元素互换。

7.3 存取操作

front();//返回第一个元素。
back();//返回最后一个元素。

7.4 常用操作(插入、删除、大小、排序)

//插入和删除
push_back(elem);//在容器尾部加入一个元素
pop_back();//删除容器中最后一个元素
push_front(elem);//在容器开头插入一个元素
pop_front();//从容器开头移除第一个元素
insert(pos,elem);//在 pos 位置插 elem 元素的拷贝,返回新数据的位置。
insert(pos,n,elem);//在 pos 位置插入 n 个 elem 数据,无返回值。
insert(pos,beg,end);//在 pos 位置插入[beg,end)区间的数据,无返回值。
clear();//移除容器的所有数据
erase(beg,end);//删除[beg,end)区间的数据,返回下一个数据的位置。
erase(pos);//删除 pos 位置的数据,返回下一个数据的位置。
remove(elem);//删除容器中所有与 elem 值匹配的元素。

//大小
size();//返回容器中元素的个数
empty();//判断容器是否为空
resize(num);//重新指定容器的长度为 num,若容器变长,则以默认值填充新位置。

//反转排列排序
reverse();//反转链表,比如 lst 包含 1,3,5 元素,运行此方法后,lst 就包含 5,3,1 元素。
sort(); //list 排序

8. Set/Multiset

       set/multiset 的特性是所有元素会根据元素的值自动进行排序(默认从小到大排序)。set 是以 RB-tree(红黑树,平衡二叉树的一种)为底层机制,其查找效率非常好。set 容器中不允许重复元素,multiset 允许重复元素。set 集合是根据元素值进行排序,关系到 set 的排序规则,如果任意改变 set 的元素值,会严重破坏 set 组织。
在这里插入图片描述

8.1 构造操作

set<T> st;//set 默认构造函数:
set<T,func> st;//当T为对象时,需要指定针对于该对象的排序规则,即传入仿函数func
mulitset<T> mst; //multiset 默认构造函数:
set(const set &st);//拷贝构造函数

8.2 赋值操作

set& operator=(const set &st);//重载等号操作符
swap(st);//交换两个集合容器

8.3 常用操作(大小、插入、删除、查找)

//大小
size();//返回容器中元素的数目
empty();//判断容器是否为空

//插入和删除
insert(elem);//在容器中插入元素。
clear();//清除所有元素
erase(pos);//删除 pos 迭代器所指的元素,返回下一个元素的迭代器。
erase(beg, end);//删除区间[beg,end)的所有元素 ,返回下一个元素的迭代器。
erase(elem);//删除容器中值为 elem 的元素。

//查找
find(key);//查找键 key 是否存在,若存在,返回该键的元素的迭代器;若不存在,返回 map.end();
lower_bound(keyElem);//返回第一个 key>=keyElem 元素的迭代器。
upper_bound(keyElem);//返回第一个 key>keyElem 元素的迭代器。
equal_range(keyElem);//返回容器中 key 与 keyElem 相等的上下限的两个迭代器。
pair<set<int>::iterator,set<int>::iterator> ret = equal_range(2);
ret.first//第一个迭代器
ret.second//第二个迭代器

9. Map/Multimap

       map 相对于 set 区别,map 具有键值和实值,所有元素根据键值自动排序。pair 的第一元素被称为键值,第二元素被称为实值。map 也是以红黑树为底层实现机制。

9.1 构造操作

map<T1, T2> mapTT;//map 默认构造函数,key:value
map(const map &mp);//拷贝构造函数

9.2 赋值操作

map& operator=(const map &mp);//重载等号操作符
swap(mp);//交换两个集合容器

9.3 常用操作(大小、插入、删除、查找)

//大小
size();//返回容器中元素的数目
empty();//判断容器是否为空

//插入和删除
map.insert(...); //往容器插入元素,返回 pair<iterator,bool>
map<int, string> mapStu;
// 第一种 通过 pair 的方式插入对象
mapStu.insert(pair<int, string>(3, "小张"));
// 第二种 通过 pair 的方式插入对象
mapStu.inset(make_pair(-1, "校长"));
// 第三种 通过 value_type 的方式插入对象
mapStu.insert(map<int, string>::value_type(1, "小李"));
// 第四种 通过数组的方式插入值
mapStu[3] = "小刘";
mapStu[5] = "小王";
clear();//删除所有元素
erase(pos);//删除 pos 迭代器所指的元素,返回下一个元素的迭代器。
erase(beg,end);//删除区间[beg,end)的所有元素 ,返回下一个元素的迭代器。
erase(keyElem);//删除容器中 key 为 keyElem 的对组。

//查找
find(key);//查找键 key 是否存在,若存在,返回该键的元素的迭代器;/若不存在,返回 map.end();
count(keyElem);//返回容器中 key 为 keyElem 的对组个数。对 map 来说,要么是 0,要么是 1。对
multimap 来说,值可能大于 1lower_bound(keyElem);//返回第一个 key<=keyElem 元素的迭代器。
upper_bound(keyElem);//返回第一个 key>keyElem 元素的迭代器。
equal_range(keyElem);//返回容器中 key 与 keyElem 相等的上下限的两个迭代器。

10. unordered_set/multiset、unordered_map/multimap

       unordered_set/multiset、unordered_map/multimap是无序的,底层实现结构为哈希表(hash table),使用方法与8,9相似。唯独需要注意的就是unordered_set/multiset的元素是非C++内建类型时、unordered_map/multimap的key是非C++内建类型时,需要传入一个计算hash值的仿函数(hash function)
alt

//unordered_map模板定义
template<//key:value
    class Key,//键值,key
    class T,//实值,value,
    class Hash = std::hash<Key>,//计算hash值,当key为C++内建类型时,有默认计算hash值得函数对象使用;否则需要自己传入计算hash值的新规则函数对象(仿函数)
    class KeyEqual = std::equal_to<Key>,//判断索引值相等的函数对象,与hash值类似,可能需要自定义
    class Allocator = std::allocator<std::pair<const Key, T>>
>
class unordered_map;
#include <iostream>
#include <string>
#include <unordered_map>
 
int main()
{
    // 创建包含三个字符串的(映射到字符串的) unordered_map
    std::unordered_map<std::string, std::string> u =
    {
        {"红色", "#FF0000"},
        {"绿色", "#00FF00"},
        {"蓝色", "#0000FF"}
    };
 
    // 用于打印键值对的辅助 lambda 函数
    auto print_key_value = [](const auto& key, const auto& value)
    {
        std::cout << "键:[" << key << "] 值:[" << value << "]\n";
    };
 
    std::cout << "遍历并打印 unordered_map 的键值对,显式指定类型:\n";
    for (const std::pair<const std::string, std::string>& n : u)
        print_key_value(n.first, n.second);
 
    std::cout << "\n通过 C++17 的结构化绑定来遍历并打印 unordered_map 的键值对:\n";
    for (const auto& [key, value] : u)
        print_key_value(key, value);
 
    // 向 unordered_map 中添加两项
    u["黑色"] = "#000000";
    u["白色"] = "#FFFFFF";
 
    std::cout << "\n通过键输出值:\n"
                 "红色的十六进制表示:[" << u["红色"] << "]\n"
                 "黑色的十六进制表示:[" << u["黑色"] << "]\n\n";
 
    std::cout << "通过以先前不存在的键使用 operator[] 来插入新的键值对:\n";
    print_key_value("新键", u["新键"]);
 
    std::cout << "\n通过使用 auto 来遍历并打印键值对;\n"
                 "现在`新键`是映射中的一个键:\n";
    for (const auto& n : u)
        print_key_value(n.first, n.second);
}
//unordered_set模板定义
template<
    class Key,//元素的类型
    class Hash = std::hash<Key>,//计算hash值,当key为C++内建类型时,有默认计算hash值得函数对象使用;否则需要自己传入计算hash值的新规则函数对象(仿函数)
    class KeyEqual = std::equal_to<Key>,//判断索引值相等的函数对象,与hash值类似,可能需要自定义
    class Allocator = std::allocator<Key>//空间分配器,一般情况下无需修改
>
class unordered_set;
//unordered_set示例
#include <iostream>
#include <unordered_set>
 
void print(const auto& set)
{
    for (const auto& elem : set)
        std::cout << elem << ' ';
    std::cout << '\n';
}
 
int main()
{
    std::unordered_set<int> mySet{2, 7, 1, 8, 2, 8}; // 创建 int 的集合
    print(mySet);
 
    mySet.insert(5); // 将元素 5 加入集合
    print(mySet);
 
    if (auto iter = mySet.find(5); iter != mySet.end())
        mySet.erase(iter); // 移除 iter 指向的元素
    print(mySet);
 
    mySet.erase(7); // 移除元素 7
    print(mySet);
}

11. 容器使用时机

  • vector 的使用场景:比如软件历史操作记录的存储,我们经常要查看历史记录,比如上一次的记录,上上次的记录,但却不会去删除记录,因为记录是事实的描述。
  • deque 的使用场景:比如排队购票系统,对排队者的存储可以采用 deque,支持头端的快速移除,尾端的快速添加。如果采用 vector,则头端移除时,会移动大量的数据,速度慢。
  • vector 与 deque 的比较
    (1)vector.at()比 deque.at()效率高,比如 vector.at(0)是固定的,deque 的开始位置
    却是不固定的。
    (2)如果有大量释放操作的话,vector 花的时间更少,这跟二者的内部实现有关。
    (3)deque 支持头部的快速插入与快速移除,这是 deque 的优点。
  • list 的使用场景:比如公交车乘客的存储,随时可能有乘客下车,支持频繁的不确实位置元素的移除插入。
  • set 的使用场景:比如对手机游戏的个人得分记录的存储,存储要求从高分到低分的顺序排列。
  • map 的使用场景:比如按 ID 号存储十万个用户,想要快速要通过 ID 查找对应的用户。二叉树的查找效率,这时就体现出来了。如果是 vector 容器,最坏的情况下可能要遍历完整个容器才能找到该用户。

在这里插入图片描述




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

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

相关文章

Android Studio新建项目教程

Android Studio新建项目教程 一、创建新项目 二、选择空白页项目类型 配置然后finish 等待项目完成初试化 等待初始化结束&#xff0c;创建完成 三、运行创建的APP

统信UOS1060设置自动关机01

原文链接&#xff1a;统信UOS1060设置自动关机01 hello&#xff0c;大家好啊&#xff0c;今天给大家介绍一篇如何在统信UOS 1060上实现自动关机的文章&#xff0c;本篇文章采用两种方式&#xff0c;第一种使用的是crontab定时任务的方式&#xff0c;第二种是使用at命令的方式&a…

frp隧道(流量代理)

代理 代理使用场景 拿下远程web服务器webshell连接不稳定&#xff0c;需要使用稳定的木马程序远程服务器无法直接连接攻击者电脑&#xff08;内网IP&#xff09;需要借助公网vps转发来自失陷服务器的木马流量借助frp服务器&#xff08;vps&#xff09;和客户端&#xff08;内…

基于SSM的班级事务管理系统

基于SSM的班级事务管理系统 开发语言&#xff1a;Java数据库&#xff1a;MySQL技术&#xff1a;SpringSpringMVCMyBatisVue工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 系统展示 前台界面 登录界面 班委界面 学生界面 管理员界面 摘要 基于SSM&#xff08;Spring、Spring…

EMC Unity存储(VNXe) service Mode和Normal Mode的一些说明

本文介绍下EMC unity存储设备&#xff08;也包含VNXe存储设备&#xff09;的两种工作模式&#xff1a; Service mode&#xff1a;也叫做rescue mode&#xff0c;存储OS工作不正常或者有其他故障&#xff0c;就会进入这个模式&#xff0c;无法对外提供服务Normal mode&#xff…

图文并茂手把手教你在MAC配置Android,nodejs,git,brew环境,配置安卓真机支持投屏以及测试

先说nodejs和npm 这个很简单&#xff0c;只需要点击下面链接&#xff0c;安装node.js环境即可 https://nodejs.org/zh-cn/ Android Android Studio 下载地址及版本说明 Android 开发者官网&#xff1a;https://developer.android.com/index.html &#xff08;全球&#xff…

大数据可视化模块竞赛Vue项目文件结构与注意事项

1.vue项目src目录下只有两个文件夹与两个js文件,如图所示: 2.asseets目录存放包或其他外部资料 注意 :echarts采用的是引用外部文件导入 let echarts = require(@/assets/echarts.min.js) 3.components目录存放绘制页面的vue文件(我这里示例创建了一个newPage.vue)…

彩票系统java

【题目要求】&#xff1a; 设计实现一种彩票系统&#xff0c;根据彩票规则&#xff0c;进行开奖和公布开奖结果&#xff0c;设计报告中给出彩票的规则。 【彩票规则】&#xff1a; 系统会随机生成一个四位的号码作为此次的中奖号码&#xff0c;用户根据系统的文字提示输入自…

树莓派玩转openwrt软路由:11.OpenWrt安装NodeRed

1、更新软件源 opkg update2、安装nodered docker run -it -p 1880:1880 --name mynodered nodered/node-red3、安装完整性测试 实现一个打印hello world的demo&#xff0c;每隔1秒打印一次

2.9 深入GPU硬件架构及运行机制

五、GPU技术要点 1.SMID和SIMT SIMD&#xff08;Single Instruction Multiple Data&#xff09;是单指令多数据&#xff0c;在GPU的ALU&#xff08;在Core内&#xff09;单元内&#xff0c;一条指令可以处理多维向量&#xff08;一般是4D&#xff09;的数据。比如&#xff0c…

python+大数据校园卡数据分析 计算机竞赛

0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; 基于yolov5的深度学习车牌识别系统实现 &#x1f947;学长这里给一个题目综合评分(每项满分5分) 难度系数&#xff1a;4分工作量&#xff1a;4分创新点&#xff1a;3分 该项目较为新颖&am…

3.MySQL数据类型详解

个人主页&#xff1a;Lei宝啊 愿所有美好如期而遇 目录 1.数据类型分类 2.数值类型 (1).tinyint&#xff0c;smallint类型等 (2)bit类型 (3)小数类型 1).float 2).decimal 3.字符串类型 (1)char (2)varchar (3)char和varchar比较 (4)日期和时间类型 (5)enum和se…

Vue3<script setup>语法糖下,实现父子组件通信以及数据监听。

在Vue3的script setup语法糖中&#xff0c;没有办法通过Vue2的ref、props、parent、中央时间总线等等众多方法&#xff0c;通过this指针简单的实现父子组件的通信&#xff0c;网络上也很少有关于script setup语法糖的相关教程&#xff0c;所以决定自己写一个详细教程&#xff0…

创建IDEA模板

将常用的配置文件内容、模板框架等放到IDEA的模板中保存&#xff0c;方便以后使用。以mybatis-config.xml和一个映射文件为例&#xff08;这是我自己学习SSM时用到的&#xff0c;后面学习SpringBoot时发现配置都只需要写到application.yml中就ok了&#xff0c;配置变得非常简单…

07_03文件系统怎么玩的

文件系统 Linux将文件系统分为了两层&#xff1a;VFS&#xff08;虚拟文件系统&#xff09;、具体文件系统&#xff0c;如下图所示&#xff1a; VFS&#xff08;Virtual Filesystem Switch&#xff09;称为虚拟文件系统或虚拟文件系统转换&#xff0c;是一个内核软件层&#…

【计算机网络】IP协议详解

文章目录 一、引入 二、简单认识IP协议 2、1 IP协议基本概念 2、2 IP协议报文格式 2、3 分片与组装 2、3、1 MTU 与 MSS 2、4 网段划分 2、4、1 简单理解路由 2、4、2 IP地址 2、4、3 IP地址的划分 2、4、4 CIDR&#xff08;无类别域间路由&#xff09; 2、4、5 特殊的IP地址 …

磁盘非跨盘访问算法实现

1. 背景说明 本算法基于已将磁盘分布合并并排序为升序线性表。实现示例为&#xff1a;磁盘扇区大小&#xff1a;32&#xff08;可自定义&#xff09;&#xff0c;待拆分磁盘内存&#xff1a; [0 - 50]&#xff0c;[60 - 100]&#xff08;可增加&#xff09;。示意图如下&#x…

【电机控制】FOC电机控制

FOC&#xff08;Field-Oriented Control&#xff0c;磁场定向控制&#xff09;是一种电机控制策略&#xff0c;又称矢量控制&#xff0c;是通过控制变频器输出电压的幅值和频率控制三相直流无刷电机的一种变频驱动控制方法。 FOC 的实质是运用坐标变换将三相静止坐标系下的电机…

什么是 CSRF 、原理及其解决方式

什么是 CSRF &#xff1f; 跨站请求伪造&#xff08;CSRF&#xff0c;Cross-site request forgery&#xff09;&#xff0c;也称为 XSRF&#xff0c;Sea Surf 或Session Riding&#xff0c;是一个攻击向量&#xff0c;它欺骗 Web 浏览器在登录用户的应用程序中执行不需要的动作…

如何处理前端国际化和本地化?

聚沙成塔每天进步一点点 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 欢迎来到前端入门之旅&#xff01;感兴趣的可以订阅本专栏哦&#xff01;这个专栏是为那些对Web开发感兴趣、刚刚踏入前端领域的朋友们量身打造的。无论你是完全的新手还是有一些基础的开发…