【string】基本用法

news2025/1/21 18:57:25

 

目录

前言:

 string常用接口

一、string的创建,拼接与拷贝构造

1.创建

2.拼接

3.拷贝构造

二、string遍历

方式一:operator[ ]重载

方式二:迭代器

1.正向迭代器:

2.反向迭代器

3.const正向迭代器

4.const反向迭代器

方式三:范围for

方式四:at()方法

三、容量与字符个数相关

 1. size()

2. capacity()

3. resize()

①n < size

②n >= size && n<= capacity<>

③n > capacity

4.reserve()

6.clear()

7.shrink_to_fit()

四、增删查改

1. push_back()

2. append()

①追加整个字符串

②追加字符串的一部分

3. +=

4. assign()

5. insert()

①插入单个字符

②插入字符串

6. erase()

7.replace()

8.查找系列

①find()

 ②rfind()

③find_first_of()

④find_last_of()

⑤find_first_not_of()

⑥find_last_not_of()

⑦substr()

五、输入( getline() )


前言:

STL是C++标准库的重要组成部分;STL有六大组件,其中有一大组件叫做容器,我们今天要介绍的string就是容器之一

1.string是表示字符串的字符串类

2.该类的接口与常规容器的接口基本相同,再添加了一些专门用来操作string的常规操作

3.string在底层实际是: basic_string模板类的别名    

4.不能操作多字节或者变长字符的序列

string文档:string接口文档

 string常用接口

值得一提的是,string比STL出现的要早一些,因此string的很多接口设计时没法参考标准,这就使得string的很多接口设计地有些冗余,我们只需要掌握最常用的一些就可以了~

一、string的创建,拼接与拷贝构造

1.创建

#include<iostream>
using namespace std;
int main()
{
	//字符串创建
	string s1; //没有显示初始化默认是空字符串
	string s2("hello world"); //带参数创建
	string s3 = "hello world"; //单参数的构造函数支持隐式类型转化
}

2.拼接

#include<iostream>
using namespace std;
int main()
{
	//字符串拼接
	//string + string
	string s1 = "hello ";
	string s2 = "world"; 
	string s3 = s1 + s2; 
	cout << s3 << endl; // hello world

	//自己和自己拼接
	string s6 = "hello ";
	string s7 = s6 + s6;
	cout << s7 << endl; //hello hello 
	 
	//string + "常量字符串"
	string s4 = "hello ";
	string s5 = s4 + "world";
	cout << s5 << endl; // "hello world"
}

3.拷贝构造

#include<iostream>
using namespace std;
int main()
{
	string s1 = "hello world";
	//完全拷贝
	string s2(s1); //s1对象完全拷贝给s2
	cout << s2 << endl; //hello world;

	//部分拷贝
	string s3(s1, 1, 3); //从s1下标为1的位置开始取3个字符拷贝给s3
	cout << s3 << endl; //ell

	string s4(s1, 1, 15); //15>字符串长度, 从1开始取整个字符串
	cout << s4 << endl; //ello world

	string s5(s1, 1); //第三个缺省参数默认是-1(size_t),因此取完整个字符串
	cout << s5 << endl; //ello world;

	//迭代器区间拷贝构造初始化
	string s6(s1.begin(), s1.end()); //s1.begin()获取的是字符串首位置,s1.end()获取的是字符串最后一个有效字符下一个位置('\0'的位置)
	cout << s6 << endl;  //hello world

	string s7(++s1.begin(), --s1.end());
	cout << s7 << endl; //	ello worl
}

二、string遍历

方式一:operator[ ]重载

#include<iostream>
using namespace std;
int main()
{
	string s1 = "hello world";
	//读
	for (size_t i = 0;i < s1.size();i++) //size()是用来获取字符串中有效字符个数(不含'\0')
	{
		cout << s1[i] << " ";
	}
	cout << endl;
	//写
	for (size_t i = 0;i < s1.size();i++) //size()是用来获取字符串中有效字符个数(不含'\0')
	{
		s1[i]++;
		cout << s1[i] << " ";
	}
	cout << endl;
}

方式二:迭代器

迭代器提供了一种遍历容器中元素的方法,我们无需关心容器内部的实现细节

1.正向迭代器:
#include<iostream>
using namespace std;
int main()
{
	string s1 = "hello world";
	//iterator是迭代器的意思,封装在string内部
	string::iterator it = s1.begin(); //s1.begin()返回的是字符串起始位置地址
	//it是迭代器类型,但是我们可以类似认为是是指针变量
	while (it != s1.end())
	{
		cout << *it << " "; //类似于指针解引用
		it++; //类似于指针向后移动
	}
	cout << endl;
}

2.反向迭代器

除了正向迭代器之外,还有反向迭代器,借助反向迭代器,可以实现逆序遍历

#include<iostream>
using namespace std;
int main()
{
	string s1 = "hello world";
	string::reverse_iterator rit = s1.rbegin();
	while (rit != s1.rend())
	{
		cout << *rit << " ";
		rit++;
	}
	cout << endl;
}

3.const正向迭代器

若string对象被const修饰了,此时要正向遍历必须用const正向迭代器,否则权限放大会报错

#include<iostream>
using namespace std;
void func(const string& s)
{
	string::const_iterator it = s.begin();
	while (it != s.end())
	{
		cout << *it << " ";
		it++;
	}
	cout << endl;
}
int main()
{
	string s1 = "hello world";
	func(s1);
}
4.const反向迭代器
#include<iostream>
using namespace std;
void func(const string& s)
{
	string::const_reverse_iterator rit = s.rbegin(); 
	//上一行代码太冗余了,此时auto的价值就体现出来了
	//auto rit = s.rbegin();
	while (rit != s.rend())
	{
		cout << *rit << " ";
		rit++;
	}
	cout << endl;
}
int main()
{
	string s1 = "hello world";
	func(s1);
}

方式三:范围for

范围for的底层其实是借助迭代器实现的~

#include<iostream>
using namespace std;
int main()
{
	string s1 = "hello world";
	for (auto ch : s1)
	{
		cout << ch << " ";
	}
	cout << endl;
}

方式四:at()方法

at方法和operator[ ]无本质区别,且operator[ ]更加常用, at()方法很少用到

#include<iostream>
using namespace std;
int main()
{
	string s1 = "hello world";
	for (size_t i = 0;i < s1.size();i++)
	{
		cout << s1.at(i) << " ";
	}
	cout << endl;
}

三、容量与字符个数相关

 1. size()

size()用来计算字符串中有效字符的个数,不包含'\0'

#include<iostream>
using namespace std;
int main()
{
	string s1 = "hello world";
	cout << s1.size() << endl; //11 
	//ps: length也是求字符串长度的,可以和size()互换,但几乎不用
	cout << s1.length() << endl; //11 
}

2. capacity()

capacity() 用来计算当前字符串的容量,最多能够存放的有效字符的个数

同样的一个字符串, 不同编译器下给定的capacity的大小可能会不太一样,没有规律~

#include<iostream>
using namespace std;
int main()
{
	string s1 = "hello world";
	cout << s1.capacity() << endl; //15

	string s2 = "come up";
	cout << s2.capacity() << endl;  //15

	string s3 = "weclome to beijing";
	cout << s3.capacity() << endl; //31
}

3. resize()

 resize()是用来调整容器大小的,n制定了

①n < size

相当于尾删元素,size减小到n,capacity不变

#include<iostream>
using namespace std;
int main()
{
	//n < size
	string s1 = "hello world";
	cout << s1.size() << endl; //11
	cout << s1.capacity() << endl; //15
	s1.resize(5);
	cout << s1<< endl; //hello
	cout << s1.size() << endl; //5
	cout << s1.capacity() << endl; //15
}
②n >= size && n <= capacity

相当于尾插元素,size增加到n, capacity不变, resize()给定了第二个字符参数,就插入该字符,否则默认插入'\0'

#include<iostream>
using namespace std;
int main()
{
	//n >= size && n <capacity
	//resize不传字符参数
	string s1 = "hello world";
	cout << s1.size() << endl; //11
	cout << s1.capacity() << endl; //15
	s1.resize(13); //插入两个'\0'
	cout << s1 << endl; //hello world
	cout << s1.size() << endl; //13
	cout << s1.capacity() << endl; //15

	//resize()传字符参数
	string s1 = "hello world";
	s1.resize(13, 'x');
	cout << s1 << endl; //hello worldxx
}
③n > capacity

相当于插入元素,size增加到n, capacity增大(编译器决定增大到多少)

#include<iostream>
using namespace std;
int main()
{
	string s1 = "hello world";
	cout << s1.capacity() << endl; //15
	s1.resize(20, 'x');
	cout << s1 << endl; //hello worldxxxxxxxxx
	cout << s1.capacity() << endl; //31
}

4.reserve()

 reserve是用来提前申请空间的,有些情况下使用reserve可以很好地避免频繁扩容

系统实际分配的空间都是略大于我们指定的n个字符的~

#include<iostream>
using namespace std;
int main()
{
	string s1 = "hello world";
	cout << s1.capacity() << endl; //15
	s1.reserve(20);
	cout << s1.capacity() << endl; //31
}

ps:我们来观察一下VS2022环境下string扩容的规律

#include<iostream>
using namespace std;
int main()
{
	string s;
	s.reserve(20);
	size_t old = s.capacity();
	for (size_t i = 0;i < 1000;i++)
	{
		s.push_back(i);
		if (old != s.capacity())
		{
			cout << "扩容到:" << s.capacity() << endl;
			old = s.capacity();
		}
	}
}

5.empty()

empty()用于判断字符串是否为空,为空返回1,不为空返回0

#include<iostream>
using namespace std;
int main()
{
	string s1 = "hello world";
	string s2 = "";
	cout << s1.empty() << endl; //0
	cout << s2.empty() << endl; //1
}

6.clear()

clear用于清空字符串,使得字符串中有效字符的个数为0,因此size为0,capacity不变

#include<iostream>
using namespace std;
int main()
{
	string s1 = "hello world";
	cout << s1.size() << endl; //11
	cout << s1.capacity() << endl; //15
	s1.clear();
	cout << s1.size() << endl; //0
	cout << s1.capacity() << endl; //15
}

7.shrink_to_fit()

shrink_to_fit()是用来向系统请求把容量capacity减小到和有效字符个数size一样大

ps:注意,这只是一个请求,实际情况下即使用了该方法,capacity也不一定改变

#include<iostream>
using namespace std;
int main()
{
	string s1 = "hello world";
	cout << s1.size() << endl; //11
	cout << s1.capacity() << endl; //15
	s1.shrink_to_fit();
	cout << s1.size() << endl; //11
	cout << s1.capacity() << endl; //15
}

clear()只能清空字符串,不会改变容量,这时再用shrink_to_fit就可以完美地将capacity置成0

四、增删查改

1. push_back()

push_back是用于尾插单个字符的~

#include<iostream>
using namespace std;
int main()
{
	string s;
	s.push_back('h');
	s.push_back('e');
	s.push_back('l');
	cout << s << endl; //hel
}

2. append()

append是追加的意思,也就是尾插

①追加整个字符串
#include<iostream>
using namespace std;
int main()
{
	//尾插整个字符串
	string s1 = "hello ";
	s1.append("w");
	cout << s1 << endl; //hello w

	string s2 = "hello ";
	s2.append("world");
	cout << s2 << endl; //	hello world

	string s3 = "hello ";
	string s4 = "world";
	s3.append(s4);
	cout << s3 << endl; //hello world
}
②追加字符串的一部分
#include<iostream>
using namespace std;
int main()
{
	//尾插字符串一部分
	string s1 = "hello ";
	string s2 = "world";
	s1.append(s2, 0, 2); //尾插s2从下标0开始的2个字符
	cout << s1 << endl; //hello wo

	string s3 = "hello ";
	s3.append(2, 'w'); //追加2个'w'字符在s3后面
	cout << s3 << endl; //hello ww
}

3. +=

 +=本质也是一种追加字符串的方式,尾插字符串或者字符到string对象末尾

#include<iostream>
using namespace std;
int main()
{
	//+=字符
	string s1 = "hello ";
	s1 += 'w';
	cout << s1 << endl; //hello w

	//+=字符串
	string s2 = "hello ";
	s2 += "world";
	cout << s2 << endl; //hello world

	string s3 = "hello ";
	string s4 = "world";
	s3 += s4;
	cout << s3 << endl; //hello world
}

4. assign()

 assign本质就是赋值

#include<iostream>
using namespace std;
int main()
{
	//赋值 string对象
	string s1 = "hello";
	string s2 = "world";
	s1.assign(s2); //将s2赋值给s1
	cout << s1 << endl; //world

	//赋值 常量字符串
	string s3 = "hello";
	s3.assign("world"); //将"world"赋值给s3
	cout << s3 << endl; //world

	//赋值 常量字符串的前n个字符
	string s4 = "hello";
	s4.assign("world", 2); //将"world"的前2个字符赋值给s4
	cout << s4 << endl; //wo

	//赋值 n个字符
	string s5 = "hello ";
	s5.assign(2, 'w'); //赋值2个'w'字符给s5
	cout << s5 << endl; //ww

	//赋值 string的子串
	string s6 = "hello";
	string s7 = "handsome boy";
	s6.assign(s7, 3, 5); //赋值s7从下标为3的位置开始的5个字符给s6
	cout << s6 << endl; //dsome

	string s8 = "hello";
	string s9 = "world";
	s8.assign(s9, 2); //赋值s9从下标为2开始的子串赋值给s8
	cout << s8 << endl; //rld
}

5. insert()

 insert()是在指定位置插入字符或者字符串

①插入单个字符
#include<iostream>
using namespace std;
int main()
{
	//插入单个字符
	string s1 = "hello world";
	s1.insert(2, 3, '*'); //下标为0的位置插入2个'*'
	cout << s1 << endl; //he*** llo world

	string s2 = "hello world";
	s2.insert(s2.begin(), 'w'); //开始位置插入字符'w'
	cout << s2 << endl; //whello world

	string s3 = "hello world";
	s3.insert(s3.begin(), 2, 'w'); //开始位置插入2个字符'w'
	cout << s3 << endl; //wwhello world
}
②插入字符串
#include<iostream>
using namespace std;
int main()
{
	//插入字符串
	//插入整个字符串
	string s1 = "hello world";
	s1.insert(2, "come"); //下标为2位置开始插入字符串"come"
	cout << s1 << endl; //hecomello world

	//插入字符串的一部分
	string s2 = "hello world";
	string s3 = "Never give up";
	s2.insert(2, s3, 2, 6); //取s3字符串下标从2开始的6个字符插入s2下标为2的位置
	cout << s2 << endl; //hever gillo world

	string s4 = "hello world";
	s4.insert(2, "world", 2); //取world下标为0(默认)开始的2个字符插入到s4中下标为2的位置
	cout << s4 << endl; //hewollo world
}

6. erase()

 erase()是用于删除指定位置起的一个或若干个字符

#include<iostream>
using namespace std;
int main()
{
	string s1 = "hello world";
	s1.erase(2, 5); //删除s1下标从2开始的5个字符
	cout << s1 << endl; //heorld

	string s2 = "hello world";
	s2.erase(7); //删除s1下标从7开始的剩余字符
	cout << s2 << endl; //hello w

	string s3 = "hello world";
	s3.erase(); //删除整个字符串
	cout << s3 << endl; //空
}

7.replace()

 replace是用新的字符或者字符串替换原字符串部分字符

#include<iostream>
using namespace std;
int main()
{
	string s1 = "hello world";
	s1.replace(2, 5, "xxxxxxxxxxxx"); //将s1从下标2开始的5个字符替换成"xxxxxxxxxxxx"
	cout << s1 << endl; //hexxxxxxxxxxxxorld

	string s2 = "hello world";
	s2.replace(++s2.begin(), --s2.end(), "xxxxxx"); //将s1第2个字符的位置到倒数第二个字符位置的子串替换成"xxxxxx"
	cout << s2 << endl; //hxxxxxxd

	string s3 = "hello world";
	s3.replace(2, 5, "xxx***&&&", 3, 4); //将s3下标从2开始的5个字符替换成"xxx***&&&"下标从3开始的4个字符
	cout << s3 << endl; //he***&orld

	string s4 = "hello world";
	s4.replace(2, 5, 3, '*'); //将s4下标从2开始的5个字符替换成3个'*'
	cout << s4 << endl; //he***orld

	string s5 = "hello world";
	s5.replace(2, 5, "&*@!", 4); //将s5下标从2开始的5个字符替换成"&*@!"的前两个字符
	cout << s5 << endl; //he&*orld
}

8.查找系列

①find()

#include<iostream>
using namespace std;
int main()
{
	//find会返回找到的字符串的首字符或者字符的下标
	string s1 = "hello world";
	size_t pos1 = s1.find("llo", 1); //从s1下标为2开始查找字符串"llo"
	cout << pos1 << endl; //2
	size_t pos2 = s1.find("llx", 1);
	cout << pos2 << endl; //找不到返回npos(size_t类型,值为-1,是一个很大的整数)

	string s2 = "hello world";
	size_t pos3 = s1.find('l'); //默认从s2的第一个位置开始找'l'字符首次出现的位置
	cout << pos3 << endl; //2
}
 ②rfind()

 find()是从左到右查找,而rfind()是从右到左查找

#include<iostream>
using namespace std;
int main()
{
	//find会返回找到的字符串的首字符或者字符的下标
	string s1 = "hello world";
	size_t pos1 = s1.rfind("wor", -3); //从s1倒数第3个位置开始查找"wor"
	cout << pos1 << endl; //6

	string s2 = "hello world";
	size_t pos3 = s1.rfind('l'); //默认从s2的倒数第一个位置开始从右向左找'l'字符首次出现的位置
	cout << pos3 << endl; //9
}
③find_first_of()

#include<iostream>
using namespace std;
int main()
{
	//find_first_of用于查找指定字符串的所有字符在原字符串中最先出现的字符的位置
	string s1 = "hello world";
	string s2 = "aeiou";
	size_t pos = s1.find_first_of(s2); //查找s2中的所有字符中最先在s1中出现的字符的位置
	cout << pos << endl; //1
	 
	//find_first_of有何意义?
	//假如说想要把s3中的所有元音字母替换成'*'
	string s3 = "hello world";
	size_t found = s3.find_first_of("aeiou");
	while (found != string::npos) //查找完find_first_of会返回npos
	{
		s3[found] = '*';
		found = s3.find_first_of("aeiou", found + 1); //从下标为found+1的位置继续寻找
	}
	cout << s3 << endl; //h*ll* w*rld
}
④find_last_of()

 与find_first_of功能是一样的,不过find_first_of从左往右找,find_last_of从右往左找

⑤find_first_not_of()

 从左向右找的不在指定字符串中的字符

#include<iostream>
using namespace std;
int main()
{
	//find_first_not_of用于查找不在指定字符串的所有字符在原字符串中最先出现的字符的位置
	string s1 = "hello world";
	string s2 = "aeiou";
	size_t pos = s1.find_first_not_of(s2); //查找不在s2中的所有字符中最先在s1中出现的字符的位置
	cout << pos << endl; //0

	string s3 = "hello world";
	size_t found = s3.find_first_not_of("aeiou");
	while (found != string::npos) 
	{
		s3[found] = '*';
		found = s3.find_first_not_of("aeiou", found + 1); //从下标为found+1的位置继续寻找
	}
	cout << s3 << endl; //*e**o**o***
}
⑥find_last_not_of()

从右往左找不在指定字符串中的字符

⑦substr()

 substr()用于获取子串,返回获取到的子串

#include<iostream>
using namespace std;
int main()
{
	string s1 = "hello world";
	string s2 = s1.substr(1, 3); //获取从下标为1开始的3个字符作为原字符串子串返回
	cout << s2 << endl; //ell

	string s3 = s1.substr(1); //s1从下标为0开始取完赋值给s3
	cout << s3 << endl; //ello world

	string s4 = s1.substr(); //取完整个s1
	cout << s4 << endl; //hello world
}

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

查找系列综合题目:获取网址的三部分

ps:网址有三部分构成:协议,域名,资源名;    ( : 和 / 将网址划分为了三部分)

#include<iostream>
using namespace std;
int main()
{
	string s1 = "https://legacy.cplusplus.com/reference/string/string/rfind/";
	string sub1, sub2, sub3;
	size_t i1 = s1.find(':');
	if (i1 != string::npos)
		sub1 = s1.substr(0, i1);
	size_t i2 = s1.find('/', i1 + 3);
	if (i2 != string::npos)
		sub2 = s1.substr(i1 + 3, i2 - (i1 + 3));
	sub3 = s1.substr(i2 + 1);
	cout << sub1 << endl; //https
	cout << sub2 << endl; //legacy.cplusplus.com
	cout << sub3 << endl; //reference/string/string/rfind/
}

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

五、输入( getline() )

C++中关于输入我们最常用的是cin, 但是cin有个缺陷,就是无法读取到空格和换行,因此cin输入默认输入的内容是以字符或者换行分割的

因此有些场景下必须用getline()进行输入,getline()可以直接读取一整行

①不指定分隔符,默认以回车结束,因此可以直接读取一行

#include<iostream>
using namespace std;
#include<string>
int main()
{
	//getline读取一整行
	string s1;
	getline(cin, s1);
	cout << s1 << endl;
}

②若想要读入回车,则需要手动指定分割符为'\r',要使输入结束: ctrl + z

#include<iostream>
using namespace std;
#include<string>
int main()
{
	
	//如何让getline读取回车呢?
	//std::istream& getline(std::istream & is, std::string & str, char delim);
	string s1;
	getline(cin, s1, '\r'); //第三个参数指定输入内容之间的分隔符
	cout << s1 << endl;
}

本篇关于string接口的设计讲解的是非常详细的,这将为下面要学习的string的模拟实现打下坚实的基础~

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

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

相关文章

PyQt5资源的加载和使用,即如何使用Pyrcc

1、打开QtDesigner&#xff0c;选择编辑资源 2、新建资源文件&#xff0c;随便找个地方保存 3、按照自己的喜好命名&#xff0c;然后添加资源 4、保存并退出 5、我们创建一个QLabel&#xff0c;在这里添加资源 6、我们保存界面文件&#xff0c;并编译为py文件&#xff0c;然后…

【C语言】调试技巧

目录 一、什么是bug? 二、调试 1.一般调试的步骤 2.Debug 和 Release 三、调试环境准备 四、调试时要查看的信息 1.查看临时变量的值 2.查看内存信息 3.查看调用堆栈 4.查看反汇编信息 5.查看寄存器 五、练习 六、常见的coding技巧 七、const的作用 八、编程常见…

时序预测 | MATLAB实现基于RF随机森林的时间序列预测-递归预测未来(多指标评价)

时序预测 | MATLAB实现基于RF随机森林的时间序列预测-递归预测未来(多指标评价) 目录 时序预测 | MATLAB实现基于RF随机森林的时间序列预测-递归预测未来(多指标评价)预测结果基本介绍程序设计参考资料 预测结果 基本介绍 MATLAB实现基于RF随机森林的时间序列预测-递归预测未来…

Linux命令200例:kill用来终止或者结束进程(常用)

&#x1f3c6;作者简介&#xff0c;黑夜开发者&#xff0c;全栈领域新星创作者✌。CSDN专家博主&#xff0c;阿里云社区专家博主&#xff0c;2023年6月csdn上海赛道top4。 &#x1f3c6;数年电商行业从业经验&#xff0c;历任核心研发工程师&#xff0c;项目技术负责人。 &…

服务链路追踪

一、基础概念 1.背景 对于一个大型的几十个、几百个微服务构成的微服务架构系统&#xff0c;通常会遇到下面一些问题&#xff0c;比如&#xff1a; 如何串联整个调用链路&#xff0c;快速定位问题&#xff1f;如何理清各个微服务之间的依赖关系&#xff1f;如何进行各个微服…

uniapp-微信小程序篇

uniapp-微信小程序篇 一、创建项目(以Vue3TS 项目为示例) 可以通过命令行的方式创建也可以通过HBuilderX进行创建&#xff08;通过HBuilderX创建的项目建议选择最简单的模板&#xff09;&#xff0c;个人建议使用命令行方式。 (1) 命令行方式&#xff1a; npx degit dcloudio…

WebRTC音视频通话-WebRTC视频自定义RTCVideoCapturer相机

WebRTC音视频通话-WebRTC视频自定义RTCVideoCapturer相机 在之前已经实现了WebRTC调用ossrs服务&#xff0c;实现直播视频通话功能。但是在使用过程中&#xff0c;RTCCameraVideoCapturer类提供的方法不能修改及调节相机的灯光等设置&#xff0c;那就需要自定义RTCVideoCaptur…

认识excel篇2之如何快速输入数据

一、快速输入数据&#xff08;快捷键功能的使用&#xff09; 1、鼠标左键填充&#xff1a;复制填充、等差序列填充&#xff08;行、列是一样的&#xff09; 步骤&#xff1a;选中单元格&#xff0c;鼠标放置到单元格右下角待鼠标箭头变成实心十字架&#xff0c;左键向下拖拽&…

List和ObservableCollection和ListBinding在MVVM模式下的对比

List和ObservableCollection和ListBinding在MVVM模式下的对比 List 当对List进行增删操作后&#xff0c;并不会对View进行通知。 //Employee public class Employee : INotifyPropertyChanged {public event PropertyChangedEventHandler? PropertyChanged;public string N…

VMware vCenter 低版本存在未授权任意文件读取漏洞

VMware vCenter 低版本存在未授权任意文件读取漏洞,Arbitrary File Read vulnerability in VMware vCenter(Unauthenticated)。 Poc from:https://twitter.com/ptswarm/status/1316016337550938122 Name :VMware vCenter Server Arbitrary File Read Vulnerability Categor…

STM32F4X NVIC中断概念

STM32F4X NVIC中断概念 CPU查询状态两种方式轮询查询中断查询 STM32有关中断的概念中断向量表系统中断外设中断中断号中断优先级 STM32F4X NVIC控制器NVIC控制器简介NVIC寄存器优先级分组 STM32F4X中断配置优先级分组设置配置外设中断 CPU查询状态两种方式 在讲解中断的概念之…

软件测试常用工具总结(测试管理、单元测试、接口测试、自动化测试、性能测试、负载测试等)

前言 在软件测试的过程中&#xff0c;多多少少都是会接触到一些测试工具&#xff0c;作为辅助测试用的&#xff0c;以提高测试工作的效率&#xff0c;使用好了测试工具&#xff0c;能对测试起到一个很好的作用&#xff0c;同时&#xff0c;有些公司&#xff0c;也会要求掌握一…

docker 学习--03 环境安装(本人使用的win10 Linux也是在win10下模拟)

docker 学习–03 环境安装&#xff08;本人使用的win10 Linux也是在win10下模拟&#xff09; 文章目录 docker 学习--03 环境安装&#xff08;本人使用的win10 Linux也是在win10下模拟&#xff09;[TOC](文章目录) 1. windows10 安装docker1.1 访问官网 点击下载1.2.点击下载的…

算法通关村第九关 | 有序数组转搜索二叉树

有序数组转搜索二叉树 二叉搜索树概念&#xff1a; 若它的左子树不为空&#xff0c;则左子树上的所有节点的值均小于它根节点的值&#xff1b; 若它的右子树不为空&#xff0c;则右子树上所有节点的值均大于它的根节点的值&#xff1b; 它的左右子树也分别为二叉树。下面给出…

ORB_SLAM3 Relocalization

Relocalization Relocalization主要的作用是在跟踪失败时&#xff0c;通过词袋在关键帧数据库KeyFrameDatabase中寻找和当前帧相似的关键帧作为匹配帧&#xff0c;进而恢复当前帧的位姿 计算当前帧的Bow&#xff0c;参考ORB_SLAM3 TrackReferenceKeyFrame中计算当前帧的描述子…

【SLAM】ORBSLAM34macOS: ORBSLAM3 Project 4(for) macOS Platform

文章目录 配置ORBSLAM34macOS 版本运行步骤&#xff1a;版本修复问题记录&#xff1a;编译 fix运行 fix 配置 硬件&#xff1a;MacBook Pro Intel CPU 系统&#xff1a;macOS Ventura 13.4.1 ORBSLAM34macOS 版本 https://github.com/phdsky/ORB_SLAM3/tree/macOS 运行步骤&…

TALKS:解决模型-数据差异的系统框架

资料收集于网络&#xff0c;仅供学习使用 TALKS: A systematic framework for resolving model-data discrepancies https://doi.org/10.1016/j.envsoft.2023.105668 问题现状 TALKS框架 TALKS(Trigger, Articulate, List, Knowledge elicitation, Solve)&#xff0c;作为解…

SpringBoot引入外部jar打包失败解决,SpringBoot手动引入jar打包war后报错问题

前言 使用外部手动添加的jar到项目&#xff0c;打包时出现jar找不到问题解决 处理 例如项目结构如下 引入方式换成这种 <!-- 除了一下这两种引入外部jar&#xff0c;还是可以将外部jar包添加到maven中&#xff08;百度查&#xff09;--><!-- pdf转word --><…

时间序列数据的预处理方法总结

时间序列数据随处可见&#xff0c;要进行时间序列分析&#xff0c;我们必须先对数据进行预处理。时间序列预处理技术对数据建模的准确性有重大影响。 在本文中&#xff0c;我们将主要讨论以下几点&#xff1a; 时间序列数据的定义及其重要性。 时间序列数据的预处理步骤。 构…