C++ —— string类(上)

目录

string的介绍

string类功能的使用介绍

constructor —— 构造

介绍使用(1)(2)(4) :构造、拷贝构造、带参构造

 介绍(3):拷贝string类对象的一部分字符,从pos位置开始,拷贝len个字符

 npos

介绍(5):取字符串的前n个字符拷贝

介绍(6) :连续n个C字符初始化

介绍(7):用迭代器区间构造

destructor —— 析构

operator= —— 赋值重载

string类对象的容量操作

size()  length()    max_size()

capacity()

reserve() 和 resize()

clear()

empty()

遍历及访问string所需的一些接口

operator[] —— []运算符重载

iterator —— 迭代器 (正向)

begin()

end()

reverse_iterator —— 反向迭代器

rbegin和rend

const修饰的迭代器

范围for

auto

 typeid().name()


string的介绍

string严格来说是属于C++标准库的,不是属于STL(标准模板库)。

STL:

我们看到里面其实是没有string的,string产生的比STL较早的,在头文件中,会单独看到一个string的头文件。C++文档

所谓的string其实就是一个字符串 ,它要解决的就是要管理字符串。(日常当中字符串是很多的,如:身份证号码,家庭地址,电话号码等等)

打开string头文件可以看到:

 有4种,这个与所谓的编码有关系,这里我们先看string:

由于编码的原因,string是typedef出来的,它的原生类型是:

//原生类型
basic_string<char>

 除了char,还有其他字符的类型(编码的原因)

//原生类型
basic_string<char16_t>

//原生类型
basic_string<char32_t>basic_string<wchar_t>

注意:basic_string其实是一个模板,所以string底层还是一个模板。

 所以,string是一个管理字符串的类。

string的介绍:

总的来说,string是一个对象,是用一个字符的顺序表实现的(也就是字符数组实现的),所以它就是一个字符顺序表(或字符数组),它可以动态的增长。(可以主要兼容UTF-8)

 string底层大致成员变量如下:

class string
{
public:/*成员函数(功能接口)*/
private:char* str;   //指针指向堆上的空间,这些空间存储对应字符串size_t size;   //有效字符个数size_t capacity;  //容量
};

下面将介绍string类的常用接口说明。 

string类功能的使用介绍

string主要包含接口如下:

我们要使用string类要记得包含一个头文件:

#include <string>   //C++//C语言的是
#include<string.h>    //注意两者区分

constructor —— 构造

string类对象的常见构造
(constructor)函数名称功能说明
string()构造空的string类对象,即空字符串
string(const char* s) 用C-string来构造string类对象
string(size_t n, char c)string类对象中包含n个字符c
string(const string&s) 拷贝构造函数

但string构造总的来说是有七种构造方式的:

我们来看C++98版本的,string它有七种构造方式 ,下面来介绍一下:

default (1)	
string();        //无参构造(也是默认构造,构造一个空字符串,长度为0个字符)copy (2)	
string (const string& str);    //拷贝构造substring (3)	
string (const string& str, size_t pos, size_t len = npos);   //子串构造函数(复制str中,从字符位置pos开始,到len位置字符的部分)from c-string (4)	
string (const char* s);    //带参构造(用一个常量字符串构造)from sequence (5)	
string (const char* s, size_t n);    //拷贝前n个字符初始化fill (6)	
string (size_t n, char c);    //连续n个C的字符去初始化range (7)	
template <class InputIterator>
string  (InputIterator first, InputIterator last);    //迭代器区间初始化
介绍使用(1)(2)(4) :构造、拷贝构造、带参构造

我们先来介绍使用(1)(2)(4):

(string重载了流插入、流提取)

#include<iostream>
#include<string>using namespace std;int main()
{string s1;           //默认构造string s2("12345");  //带参构造string s3(s2);		 //拷贝构造//string也重载了流插入流提取(>>,<<)cout << s1 << endl;cout << s2 << endl;cout << s3 << endl;cin >> s1;cout << s1 << endl;return 0;
}

 介绍(3):拷贝string类对象的一部分字符,从pos位置开始,拷贝len个字符
substring (3)	
string (const string& str, size_t pos, size_t len = npos);   //拷贝构造的一个变形//也就是拷贝一部分字符,从pos位置开始,拷贝len个字符
//接着上面演示的构造代码
int main()
{string s1;           //默认构造string s2("1234567");  //带参构造string s3(s2);		 //拷贝构造//string也重载了流插入流提取(cout,cin)cout << s1 << endl;cout << s2 << endl;cout << s3 << endl;cin >> s1;cout << s1 << endl;string s4(s2, 2, 4);  //这里就是让s4去拷贝s2的下标为2的位置开始,拷贝4个字符cout << s4 << endl;return 0;
}

我们观察输出结果,看到从3开始拷贝四个字符到6,3456四个字符就到s4里去了。若此时这里给的字符超过字符串长度,会不会报错呢?

string s2("1234567"); 
string s4(s2, 2, 15);   //让它从pos=2开始拷贝15个字符

我们观察结果,是没有报错的:

文档中: 

 

也就是说string太短了,不够len个字符,它就直到它结束为止(有多少拷贝多少 );这里还说或者为npos也是拷到它的结束。

第三个构造它的len是有缺省值npos的,如果不传第三个参数len,那么它就用这个缺省值,直到拷贝它的结束为止。

string s2("1234567"); 
string s4(s2, 2);
cout<<s2<<endl;
cout<<s4<<endl;

运行结果:

 下面对npos介绍一下

 npos

npos是一个string的const静态的成员变量,它可以直接在类里面用,若在外面用的时候,需要指定类域。

npos的值真实的值其实不是-1,在这里-1存的就是补码(-1补码是全1) ,这里又赋值给size_t类型,size_t是unsigned int(无符号整型),-1就会变成整型最大值。

所以这里npos要表达的是:从pos位置取len个字符,如果len给npos,就是要取整型的最大值,

字符串不可能有这么长(字符串中遇到\0会停止),且又给了整型的最大值了,就是要让它拷贝到字符串的结束。

介绍(5):取字符串的前n个字符拷贝
string (const char* s, size_t n);    //第(4)个(带参构造)的变形//取字符串的前n个字符拷贝

 

也就是取一个字符串的前n个字符初始化。

测试一下: 

int main()
{string s6("hello world", 5);cout << s6 << endl;return 0;
}

 运行结果:

介绍(6) :连续n个C字符初始化
string (size_t n, char c);    //n个C字符初始化

也就是连续n个C的字符初始化,例如:'X'就是一个C字符。

int main()
{string s7(10, 'X');    //用10个X字符初始化cout << s7 << endl;return 0;
}

运行结果: 

介绍(7):用迭代器区间构造
int main()
{string s0("Initial string");string s8(s0.begin(), s0.begin() + 7);  //迭代器区间构造cout <<"s0: "<< s0 << endl;cout <<"s8: " << s8 << endl;
}

运行结果:

可以看到s8中用了s0起始位置开始的7个字符初始化了 。

destructor —— 析构

string的析构函数会自动调用,string的底层是一个动态开辟的数组,构造和析构函数是自动调用的(类和对象这里有介绍)。

operator= —— 赋值重载

赋值运算符重载也是默认成员函数(类和对象有介绍)。

string (1)	
string& operator= (const string& str);  //支持string的赋值c-string (2)	
string& operator= (const char* s);      //支持char*的赋值character (3)	
string& operator= (char c);             //支持一个字符的赋值

 测试:

int main()
{string s1;           string s6("hello world", 5);s1 = s6;//本质就是调用了operator=cout << s1 << endl;s1 = "abcde";cout << s1 << endl;s1 = 'x';cout << s1 << endl;return 0;
}

运行结果:

string类对象的容量操作

函数名称功能说明
size返回字符串有效字符长度
length返回字符串有效字符长度
max_size获取最大长度(能最大开多长)
capacity返回空间容量的大小
empty检查字符串释放为空串,若是空串返回true,否则返回false
clear清空有效字符
reserve为字符串预留空间
resize将有效字符的个数改成n个,多出的空间用字符c填充

size()  length()    max_size()

size()和 length()它们两个功能上完全一致,只是一般size用的比较多,是为了与其他容器接口保持一致。

这里拿size()来说,string提供了一个size的接口,它是用来获取string的长度(有多少个字符)。

 max_size()是用来获取它最大的长度,就是它最大能开多长

int main()
{string s("FFDUST");cout << s.length() << endl;cout << s.size() << endl;cout << s.max_size() << endl;
}

capacity()

 capacity()接口也就是返回该string当前空间容量的大小是多少

int main()
{string s("FFDUST");cout << "s的空间大小为:"<<s.capacity() << endl;
}

 

(注意它和size,length接口的区别)

这里还要注意容量扩容问题(每个编译器处理扩容几倍不一致),观察下面程序:

int main()    
{string s;size_t sz = s.capacity();cout << "capacity : " << sz << '\n';cout << "making s grow:\n";for (int i = 0; i < 100; ++i){s.push_back('c');if (sz != s.capacity()){sz = s.capacity();cout << "capacity changed: " << sz << '\n';}}return 0;
}

 VS下结果:

 所以VS下,扩容是先扩2倍,再后面扩1.5倍。

reserve() 和 resize()

 reserve()接口就是先给该对象预留多少空间,不改变有效元素个数,若reserve的参数小于string的底层空间总大小时,reserve不会改变容量大小(这里VS下不会缩容,其他编译器可能会缩容,C++规定没有约束)。

int main()
{string s("FFDUST");cout << "s的空间大小为:" << s.capacity() << endl;s.reserve(100);cout << "s的空间大小为:" << s.capacity() << endl;s.reserve(1);cout << "s的空间大小为:" << s.capacity() << endl;return 0;
}

VS这里会做整数倍对齐,所以这里capacity可能会比传的参数较大一些。

注意:谈string容量的时候默认不包含\0的,所以开空间实际上会多1位用来放\0,但capacity返回的是不带\0的。

reserve的用法:提前开空间,避免扩容,提高效率。

int main()
{string s;s.reserve(100);size_t sz = s.capacity();cout << "making s grow:\n";for (int i = 0; i < 100; ++i){s.push_back('c');if (sz != s.capacity()){sz = s.capacity();cout << "capacity changed: " << sz << '\n';}}return 0;
}

这里就是给s预留了足够大的空间,再插入时候不会发生扩容。 

resize()接口(将有效字符的个数改成n个,多出的空间用字符c填充),相当于扩容插入。

这里它是有两个版本的:resize(size_t n) 与 resize(size_t n, char c)都是将字符串中有效字符个数改变到n个,不同的是当字符个数增多时:resize(n)用0(也就是\0)来填充多出的元素空间,resize(size_t n, char c)用字符c来填充多出的元素空间。注意的是:resize若比size小的话会删除数据(缩容不确定),比capacity大就会扩容。

int main()
{string s("ffdust");cout << s << endl;cout << "s的空间大小为:" << s.capacity() << endl;s.resize(100);      //默认插入\0cout << s << endl;cout << "s的空间大小为:" << s.capacity() << endl;
}

int main()
{string s("ffdust");cout << s << endl;cout << "s的空间大小为:" << s.capacity() << endl;s.resize(100,'1');        //用字符1填充多出的元素空间,注意这里会扩容cout << s << endl;cout << "s的空间大小为:" << s.capacity() << endl;}

 

 clear()

clear()也就是清空有效字符,一般严格来说不会清理掉容量,只是把数据清理掉了

int main()
{string s("ffdust");cout << s << endl;cout << &s << endl;cout << "s的空间大小为:" << s.capacity() << endl;s.clear();cout << s << endl;cout << &s << endl;cout << "s的空间大小为:" << s.capacity() << endl;return 0;
}

 运行结果:

 empty()

empty()接口时用来判空的(有没有字符),也就是检测字符串是否为空串,若是返回true,否则返回false。

int main()
{string s("ffdust");cout << s << endl;if (s.empty()){cout << s << ",是空串" << endl;}else{cout << s << ",不是空串" << endl;}cout << "s的空间大小为:" << s.capacity() << endl;s.clear();cout << s << endl;if (s.empty()){cout << s << ",是空串" << endl;}else{cout << s << ",不是空串" << endl;}cout << "s的空间大小为:" << s.capacity() << endl;return 0;
}

运行结果:

遍历及访问string所需的一些接口

函数功能功能说明
operator[]返回pos位置的字符,const string类对象也以调用
begin()+end()begin获取第一个字符的迭代器 + end获取最后一个字符下一个位置的迭代器
rbegin()+rend()rbegin获取最后一个字符迭代器 + rend获取第一个字符前一个位置的迭代器
范围forC++11支持更简洁的范围for的新遍历方式

遍历string有三种方式:

  1. 下标+[]
  2. 迭代器
  3. 范围for

operator[] —— []运算符重载

string重载operator[],访问pos位置的字符,返回这个字符的引用。 (可以读和修改)

string重载了[],这样就可以让string当成数组一样使用下标访问。string底层意思大致理解是有一个指针,指针指向一个数组,是动态开辟的,它还要有size和capacity,重载operator[],就可以让它去访问第i个位置的字符:

class string
{
public:char& operator[](size_t i){return _str[i];           //返回第i字符的引用(这里引用返回,不只是可以减少拷贝,还能让它被修改)}
private:char* str;size_t size;size_t capacity;
};

使用如下:

int main()
{string s6("hello world");cout << s6 << endl;s6[5] = 'a';     //将下标为5的字符修改成acout << s6 << endl;return 0;
}

运行结果:

就相当于用数组一样,可以获取这个位置的字符,也可以修改这个位置的字符,但这里的底层就是函数调用,调用的operator[],注意:这里越界了可以检查出来的。 

char& operator[](size_t i)
{assert(i < _size);   //这里断言,只要越界了就直接报错return _str[i];
}

我们看到这里15位置越界访问了,就报错了。

所以,我们可以搭配着size接口防止越界访问来一个一个字符的遍历:

int main()
{string s6("hello world1111");//下标+[]for (int i = 0; i < s6.size(); i++){cout << s6[i] << " ";}cout << endl;return 0;
}

 运行结果:

iterator —— 迭代器 (正向)

 迭代器遍历:

int main()
{string s6("hello world");//迭代器遍历——正向string::iterator it = s6.begin();while (it != s6.end()){cout << *it << " ";++it;}cout << endl;return 0;
}

正向遍历(begin+end) :

注:迭代器是STL六大组件之一,迭代器是用来遍历和访问这些容器的 。(迭代器有可能是原生指针,也有可能不是)。 

迭代器是类似于一个指针一样的东西,通过解引用可以访问对应位置的数据,迭代器还规定,不管它底层是怎么定义的,它是属于对应容器的类域。(上面string的迭代器属于string的类域,所以要写成 string::iterator),所以所有的容器都可以通过迭代器来访问(通用的访问容器的方式)。

 begin()

begin()就是返回开始位置的迭代器。

string这里就是返回的是第一个有效字符的位置的迭代器。

注:这里有两个版本,第一个就是普通对象用来调用的,第二个是const修饰的对象的const迭代器所调用(这里普通对象也能调用,但是只能读,不能写)。

end()

end()返回的是最后一个有效数据的下一个位置的迭代器。

string这里就是返回最后一个有效字符的下一个位置的迭代器。

注:这里有两个版本,第一个就是普通对象用来调用的,第二个是const修饰的对象的const迭代器所调用(这里普通对象也能调用,但是只能读,不能写)。

reverse_iterator —— 反向迭代器

 这里就与iterator完全相反着了

 反向遍历(rbegin+rend): 

int main()
{//反向迭代器遍历// string::reverse_iterator rit = s6.rbegin();// C++11之后,直接使用auto定义迭代器,让编译器推到迭代器的类型auto rit = s6.rbegin();while (rit != s6.rend()){cout << *rit <<" ";++rit;}cout << endl;
}

 运行结果:

rbegin和rend

这两个接口就相当于begin与end接口相反的。  

也就是rbegin获取最后一个字符迭代器 , rend获取第一个字符前一个位置的迭代器

const修饰的迭代器

 const修饰的对象,要用迭代器遍历时,是需要const修饰的迭代器的,它不能使用普通迭代器,

const迭代器修饰的是迭代器的指向,而不是迭代器的本身(类似于const修饰指针)

如下所示:

int main()
{//const对象const string cs("const hello world");//const修饰的(正向)迭代器string::const_iterator cit = cs.begin();  //这里也可以用cbegin接口,不过begin接口有提供的const修饰的版本,这就已经够用了while (cit != cs.end())     //cend同上也可以用{//错误	C3892	“cit” : 不能给常量赋值//*cit += 'x';cout << *cit << " ";++cit;}cout << endl;//const修饰的反向迭代器string::const_reverse_iterator crit = cs.rbegin();   //这里也可以用crbegin接口,不过rbegin接口有提供的const修饰的版本,这就已经够用了while (crit != cs.rend())    //crend同上也可以用{//错误	C3892	“crit” : 不能给常量赋值//*crit += 'x';cout << *crit << " ";++crit;}cout << endl;return 0;
}

 运行结果:

const修饰的迭代器,普通对象也是可以使用的(也就是权限可以缩小,但不能放大),不过只能读,不能写。

int main()
{//普通对象string s("hello world");//const修饰的迭代器string::const_iterator it = s.begin();while (it != s.end()){//错误	C3892	“it” : 不能给常量赋值//*it += 'x';cout << *it << " ";++it;}cout << endl;//const修饰的反向迭代器string::const_reverse_iterator rit = s.rbegin();while (rit != s.rend()){//错误	C3892	“rit” : 不能给常量赋值//*rit += 'x';cout << *rit << " ";++rit;}cout << endl;return 0;
}

运行结果:

 (这里也可以用auto自动推导它的类型,方便代码的编写)

范围for

  • 对于一个有范围的集合而言,C++11中引入了基于范围的for循环。for循环后的括号由冒号分为两部分:第一部分是范围内用于迭代的变量,第二部分则表示被迭代的范围,自动迭代,自动取数据,自动判断结束。
  • 范围for可以作用到数组和容器对象上进行遍历。
auto
在早期 C/C++ auto 的含义是:使用 auto修饰的变量,是具有自动存储器的局部变量。 C++11 中,赋予了 auto 全新的含义即: auto 不再是一个存储类型 指示符,而是作为一个新的类型指示符来指示编译器, auto 声明的变量必须由编译器在编译时期 推导而得

范围for和auto就可以配合使用来遍历string:
int main()
{string s6("hello world");//字符赋值,自动迭代,自动判断结束for (auto e : s6)  //auto这里自动推导类型为char{cout << e << " ";}cout << endl;return 0;
}

 运行结果:

所以这里范围for想表达的是:

  • 注意:范围for的底层角度是跟迭代器一样的,也就是说范围for这段代码被编译了之后会被替换成迭代器。(所以要支持范围for前提是要支持迭代器遍历)

从汇编层可以看到,这里就是被替换成了迭代器: 

 范围for跟迭代器就相当于没有区别,范围for只是方便编写代码。这里对比迭代器,也展示出auto的价值就是缩短代码(简化代码),不过这样会使代码可读性降低。

//这两个it的类型是一致的
string::iterator it = s6.begin();//auto会自动推导成上面的string::iterator
auto it = s6.begin();

  • 迭代器是可以修改的。
int main()
{string::iterator it = s6.begin();cout << s6 << endl;while (it != s6.end()){*it += 2;           //让里面的每一个值都加等2cout << *it << " ";++it;}cout << endl;for (auto e : s6){cout << e << " ";}cout << endl;return 0;
}

 运行结果对比一下:

可以看到每一个值都被改变了,范围for打印数据也受到影响。范围for里也是可以修改数据的,下面在范围for里面打印原来的值:

int main()
{string::iterator it = s6.begin();cout << s6 << endl;while (it != s6.end()){*it += 2;           //让里面的每一个值都加等2cout << *it << " ";++it;}cout << endl;for (auto e : s6){e -= 2;           //只需要让e减等2即可cout << e << " ";}cout << endl;return 0;
}

运行结果:

  •  注意:这里有坑的是,范围for打印出来的结果看似把s6恢复原状了,这时cout一下s6可以看到s6还是没有变回去的。这个原因是:

这里若想在范围for里修改,只需要加& 符号,也就是引用

for (auto& e : s6)    //这里auto自动推导为char类型,//若想是char的引用,就需要主动添加一个&
//这时e就是s6里面(*it)的别名,也就是取它每个字符的别名
{e -= 2;           //这时修改e,就修改了string里的值cout << e << " ";
}
cout << endl;

注意:用auto声明指针类型时,用auto和auto*没有任何区别(也就是当是一个指针类型时,可以直接写auto即可),但用auto声明引用类型时则必须加上&(auto &)。 

 typeid().name()

 typeid()可以帮助我们观察类型

typeid(变量名).name()   //可以看到该变量的类型
int func1()
{return 10;
}int main()
{int a = 10;auto b = a;auto c = 'a';auto d = func1();cout << typeid(b).name() << endl;cout << typeid(c).name() << endl;cout << typeid(d).name() << endl;int x = 10;auto y = &x;auto* z = &x;auto& m = x;cout << typeid(x).name() << endl;cout << typeid(y).name() << endl;cout << typeid(z).name() << endl;return 0;
}

运行结果: 

 

这里auto使用时还需要注意一些事项: 

// 编译报错:rror C3531: “e”: 类型包含“auto”的符号必须具有初始值设定项
auto e;

不能这样定义,它不知道e到底是多大,auto定义的变量类型一定是由右边的变量或者函数调用表达式的返回值推导的。

// 不能做参数
void func2(auto a) //这里就算给了缺省值也不支持的
{}

 auto不能做参数类型,但auto可以做返回值。

// 可以做返回值,但是建议谨慎使用
auto func3()
{return 3;
}

// 编译报错:error C3538: 在声明符列表中,“auto”必须始终推导为同一类型
auto cc = 3, dd = 4.0;

注意在一行里面定义,定义时要用同一类型

// 编译报错:error C3318: “auto []”: 数组不能具有其中包含“auto”的元素类型
auto array[] = { 4, 5, 6 };

auto不能定义一个数组(C++规定)

在这篇先总结一部分string的接口使用,剩下的部分接口总结使用在后续文章介绍。

制作不易,若有不足之处或出问题的地方,请各位大佬多多指教 ,感谢大家的阅读支持!!!   

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

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

相关文章

Python小白学习教程从入门到入坑------第三十二课 生成器(语法进阶)

目录 一、生成器 generator 1.1 生成器表达式 1.1.1 表达式一 1.1.2 表达式二 二、可迭代对象、迭代器、生成器三者之间的关系 2.1 定义与特性 2.2 关系与区别 一、生成器 generator 在Python中&#xff0c;生成器&#xff08;Generators&#xff09;是一种用于迭代对象…

商业iOS端路由架构演进

背景 目前商业SDK中的点击事件&#xff0c;会根据不同的「事件类型」「业务类型」&#xff0c;去执行不同的路由跳转逻辑&#xff0c;然而不同的跳转事件内部又有着很复杂的跳转逻辑&#xff0c; 痛点 不同的跳转逻辑之间存在耦合 例如&#xff0c;在deeplink的跳转逻辑之中…

数据结构(单向链表——c语言实现)

链式存储的优缺点&#xff1a; 优点&#xff1a; 1、动态分配内存&#xff1a; 链式存储不需要在数据插入之前分配固定大小的数组或内存块&#xff0c;因此它更适合存储动态变化的数据 2、高效的插入和删除操作&#xff1a; 在链表中插入或删除元素只需要调整相邻节点的指…

【SQL】E-R模型(实体-联系模型)

目录 一、介绍 1、实体集 定义和性质 属性 E-R图表示 2. 联系集 定义和性质 属性 E-R图表示 一、介绍 实体-联系数据模型&#xff08;E-R数据模型&#xff09;被开发来方便数据库的设计&#xff0c;它是通过允许定义代表数据库全局逻辑结构的企业模式&#xf…

Pytest-Bdd-Playwright 系列教程(12):步骤参数 parsers参数解析

Pytest-Bdd-Playwright 系列教程&#xff08;12&#xff09;&#xff1a;步骤参数 & parsers参数解析 前言一、什么是步骤参数&#xff1f;二、pytest-bdd 的步骤参数用法2.1 简单字符串解析2.2 自定义正则表达式解析2.3 参数类型转换 三、案例&#xff1a;基于 pytest-bdd…

vscode 快捷键生成代码

1. &#xff01;Tab/回车键 便捷生成html初始结构代码&#xff08;注意&#xff01;是英文字符&#xff09; 2. Alt B 快捷默认浏览器打开 3. Ctrl / 增加注释 4. 光标放到该行即可&#xff0c;直接ctrlC&#xff0c;ctrlv&#xff0c;即可在下面复制一行 5. 选中要修改的标签…

前端接入Paymax支付请求

材料指南 开发者平台 &#xff1a;配置开发必备信息&#xff08;appid&#xff0c;商户号&#xff0c;公钥私钥&#xff09;,此处与请求参数appId、merchantNo有关。 PayerMax Apis&#xff1a;各支付接口信息,本文以收银台支付API为请求展开,请求url为orderAndPay,测试环境基…

Jmeter的后置处理器(二)

5--JSR223 PostProcessor 功能特点 自定义后处理逻辑&#xff1a;使用脚本语言编写自定义的后处理逻辑。支持多种脚本语言&#xff1a;支持 Groovy、JavaScript、BeanShell 等脚本语言。动态参数传递&#xff1a;将提取的数据存储为变量&#xff0c;供后续请求使用。灵活性高…

CSS遮罩:mask

CSS属性 mask 允许使用者通过遮罩或者裁切特定区域的图片的方式来隐藏一个元素的部分或者全部可见区域。 // 一般用位图图片做遮罩 mask: url(~/assets/images/mask.png); mask-size: 100% 100%;// 使用 SVG 图形中的形状来做遮罩 mask: url(~/assets/images/mask.svg#star);…

Zmap+python脚本+burp实现自动化Fuzzing测试

声明 学习视频来自 B 站UP主泷羽sec&#xff0c;如涉及侵权马上删除文章。 笔记的只是方便各位师傅学习知识&#xff0c;以下网站只涉及学习内容&#xff0c;其他的都与本人无关&#xff0c;切莫逾越法律红线&#xff0c;否则后果自负。 ✍&#x1f3fb;作者简介&#xff1a;致…

15. Python中的os.path模块/路径操作相关

这个专栏记录我学习/科研过程中遇到的一些小问题以及解决方案&#xff0c;一些问题可能比较蠢请见谅。自用&#xff0c;仅供参考。 ------------------------------------------------------------------------------------ Python中的os.path模块详解&#xff08;包括一些常…

鸿蒙实战:页面跳转传参

文章目录 1. 实战概述2. 实现步骤2.1 创建鸿蒙项目2.2 编写首页代码2.3 新建第二个页面 3. 测试效果4. 实战总结 1. 实战概述 本次实战&#xff0c;学习如何在HarmonyOS应用中实现页面间参数传递。首先创建项目&#xff0c;编写首页代码&#xff0c;实现按钮跳转至第二个页面并…

NLP论文速读(EMNLP 2024)|动态奖励与提示优化来帮助语言模型的进行自我对齐

论文速读|Dynamic Rewarding with Prompt Optimization Enables Tuning-free Self-Alignment of Language Models 论文信息&#xff1a; 简介: 本文讨论的背景是大型语言模型&#xff08;LLMs&#xff09;的自我对齐问题。传统的LLMs对齐方法依赖于昂贵的训练和人类偏好注释&am…

Label-studio-ml-backend 和YOLOV8 YOLO11自动化标注,目标检测,实例分割,图像分类,关键点估计,视频跟踪

这里写目录标题 1.目标检测 Detection2.实例分割 segment3.图像分类 classify4.关键点估计 Keypoint detection5.视频帧检测 video detect6.视频帧分类 video classify7.旋转目标检测 obb detect8.替换yolo11模型 给我点个赞吧&#xff0c;谢谢了附录coco80类名称 笔记本 华为m…

图像处理学习笔记-20241118

文章目录 霍夫变换基本原理霍夫变换的步骤使用 OpenCV 实现直线检测示例&#xff1a;标准霍夫变换 示例&#xff1a;概率霍夫变换参数解释霍夫变换检测圆 基于GAN的样本生成GAN的基本原理基于GAN的数据增广流程实现代码示例 同态滤波&#xff08;Homomorphic Filtering&#xf…

视频融合×室内定位×数字孪生

随着物联网技术的迅猛发展&#xff0c;室内定位与视频融合技术在各行各业中得到了广泛应用。不仅能够提供精确的位置信息&#xff0c;还能通过实时视频监控实现全方位数据的可视化。 与此同时&#xff0c;数字孪生等技术的兴起为智慧城市、智慧工厂等应用提供了强大支持&#…

当科技照进现实 机器人带着机器狗乘空轨

湖北日报讯&#xff08;记者魏铼、通讯员张璨龙&#xff09;11月14日&#xff0c;武汉东湖高新区空轨高新大道站&#xff0c;在光谷装上“智慧大脑”的人形机器人&#xff0c;乘空轨&#xff0c;看AI展&#xff0c;与小朋友在生态大走廊斗舞。 京天博特&#xff1a;光谷“智慧大…

freertos任务调度学习

首先创建任务&#xff0c;创建好任务后&#xff0c;开启任务调度器&#xff0c;任务才能执行 1.开启任务调度器 2.启动第一个任务 3.任务切换

蓝桥杯每日真题 - 第16天

题目&#xff1a;&#xff08;卡牌&#xff09; 题目描述&#xff08;13届 C&C B组C题&#xff09; 解题思路&#xff1a; 题目分析&#xff1a; 有 n 种卡牌&#xff0c;每种卡牌的现有数量为 a[i]&#xff0c;所需的最大数量为 b[i]&#xff0c;还有 m 张空白卡牌。 每…

MySQL系列之数据授权(privilege)

导览 前言Q&#xff1a;如何对MySQL数据库进行授权管理一、MySQL的“特权”1. 权限级别2. 权限清单 二、授权操作1. 查看权限2. 分配权限3. 回收权限 结语精彩回放 前言 看过博主上一篇的盆友&#xff0c;可以Get到一个知识点&#xff1a;数据授权&#xff08;eg&#xff1a;g…