当前位置: 首页 > news >正文

C++——string的模拟实现(下)

目录

成员函数

3.4 修改操作

(3)insert()函数

(4)pop_back()函数

(5)erase()函数

(6)swap()函数

3.5 查找操作

(1)find()函数

 (2)substr()函数

3.6 重载函数

(1)operator=赋值函数

(2)其他比较函数

(3)流插入和流提取

完整代码

结束语


第一篇链接:C++——string的模拟实现(上)

成员函数

3.4 修改操作
(3)insert()函数

insert() 函数用于在字符串的指定位置插入一个字符或字符串。

注意事项:

在移动字符串内容时,需要确保不会覆盖或丢失任何字符。

使用 memcpy() 时,要确保源和目标内存区域不重叠,否则可能导致未定义行为。

string.h:

	// insert()函数 void insert(size_t pos, char ch);	//插入字符void insert(size_t pos, const char* str);	//插入字符串

string.cpp:

// insert()函数
// 插入字符
void string::insert(size_t pos, char ch)
{assert(pos <= _size);if (_capacity == _size){size_t newcapacity = _capacity == 0 ? 4 : 2 * _capacity;reserve(newcapacity);}size_t end = _size + 1;// 挪动元素while (pos < end){_str[end] = _str[end - 1];end--;}_str[pos] = ch;		//将ch放置到pos这个位置++_size;			//更新_size
}// 插入字符串
void string::insert(size_t pos, const char* str)
{assert(pos <= _size);size_t len = strlen(str);	// 要插入的字符串长度if (_size + len > _capacity){reserve(_size + len);}// 从后向前移动字符串内容以腾出空间  for (size_t i = _size; i >= pos; --i){_str[i + len] = _str[i];}// 复制新字符串到指定位置  memcpy(_str + pos, str, len);// 添加新的字符串结束符  _str[_size + len] = '\0';// 更新字符串长度  _size += len;
}

来个简单的代码测试一下:

(4)pop_back()函数

pop_back() 函数用于移除字符串末尾的字符。

实现:将字符串末尾的字符设置为 '\0'。 更新字符串长度 _size。

string.h:

// pop_back()函数
void pop_back();

string.cpp:

// pop_back()函数
void string::pop_back()
{_str[_size - 1] = '\0';--_size;
}
(5)erase()函数

erase() 函数用于从字符串中移除指定位置的字符或子字符串。

string.h:

// erase()函数
void erase(size_t pos = 0, size_t len = npos);

string.cpp:

// erase()函数
void string::erase(size_t pos,size_t len)
{assert(pos < _size);				 if (len == npos || len >= _size - pos){_str[pos] = '\0';		// 位置pos置为'\0'_size = pos;			// 有效元素个数为pos个}else	// len小于后面的字符个数{// 将后面的字符拷贝到pos位置strcpy(_str + pos, _str + pos + len);_size -= len;			// 更新有效元素}
}

erase()需要额外定义一个类成员变量npos来实现,它为无符号数的-1,一般为整型的最大值。

string.h:

public:static const size_t npos;

string.cpp:

const size_t string::npos = -1;

简单的对上面两个函数进行测试:

(6)swap()函数

swap() 函数用于交换两个字符串的内容。

string.h:

// swap()函数
void swap(string& str);

string.cpp:

// swap()函数
void string::swap(string& str)
{// 这里我们调用std库中的swap()函数std::swap(_str, str._str);std::swap(_capacity, str._capacity);std::swap(_size, str._size);
}

测试:

3.5 查找操作
(1)find()函数

find() 函数用于在字符串中查找指定字符或子字符串的位置。

我们在这里实现从指定位置开始向后遍历查找指定字符或者子字符串。

如果找到,则返回子字符串在字符串中的起始位置;否则返回 npos。

string.h:

// find()函数
size_t find(char ch, size_t pos);
size_t find(const char* str, size_t pos);

string.cpp:

// find()函数
// 寻找字符
size_t string::find(char ch, size_t pos)
{for (int i = pos; i < _size; i++){if (_str[i] == ch){return i;}}return npos;
}// 从pos开始寻找字符串
size_t string::find(const char* str, size_t pos)
{char* p = strstr(_str + pos, str);if (p){return p - _str;}else{return npos;}
}
 (2)substr()函数

substr() 函数用于获取字符串的子字符串。

string.h:

// substr()函数
string substr(size_t pos = 0, size_t len = npos);

string.cpp:

// substr()函数
string string::substr(size_t pos, size_t len)
{string str;if (len == npos || len >= _size - pos){for (size_t i = pos; i < _size; i++){str += _str[i];}}else{for (size_t i = pos; i < pos + len; i++){str += _str[i];}}return str;
}
3.6 重载函数

在C++中,函数重载允许我们为同一函数名创建多个版本,这些版本可以有不同的参数列表(参数的数量或类型不同)。通过这种方式,我们可以使代码更加简洁和易于理解。

(1)operator=赋值函数

赋值运算符(operator=)用于将一个对象的内容复制到另一个对象中。对于自定义的字符串类,我们需要自己实现这个运算符,以确保正确地管理内存。

string.h:

// operator=赋值函数
string& operator=(const string& s);

string.cpp:

// operator= 函数
string& string::operator=(const string& str)
{if (this != &str){char* tmp = new char[str._capacity + 1];strcpy(tmp, str._str);delete[] _str;_str = tmp;_size = str._size;_capacity = str._capacity;}return *this;
}

来测试一下:

这里我们可以对以上的代码进行优化:

// operator= 函数
string& string::operator=(const string& str)
{if (this != &str){string tmp(str._str);	// 调用构造函数swap(tmp);				// 将tmp与this交换}return *this;
}

原始实现中,我们首先检查自赋值(即对象试图将自己赋值给自己),然后分配足够的内存来存储新字符串,复制内容,并释放旧内存。这种方法虽然有效,但可能会导致性能问题,特别是当字符串很长时,因为涉及到多次内存分配和释放。

优化后的实现采用了“拷贝-交换”技术。这种方法通过创建一个临时对象来存储要赋值的字符串,然后使用swap函数交换临时对象和当前对象的内容。由于swap函数通常实现得非常高效(只需交换指针),这种方法可以显著提高性能,并减少内存分配的次数。

(2)其他比较函数

每个比较运算符都基于strcmp函数的返回值来实现。

这些函数之间是可以复用的。

string.h:

// 比较函数
bool operator<(const string& s)const;
bool operator<=(const string& s)const;
bool operator>(const string& s)const;
bool operator>=(const string& s)const;
bool operator==(const string& s)const;
bool operator!=(const string& s)const;

string.cpp:

// 比较函数
bool string::operator<(const string& str) const
{return strcmp(_str, str._str) < 0;
}
bool string::operator<=(const string& str) const
{return *this < str || *this == str;
}
bool string::operator>(const string& str) const
{return !(*this <= 0);
}
bool string::operator>=(const string& str) const
{return !(*this <= str);
}
bool string::operator==(const string& str)const
{return strcmp(_str, str._str) == 0;
}
bool string::operator!=(const string& str)const
{return !(*this == str);
}void string::clear()
{_str[0] = '\0';_size = 0;
}
(3)流插入和流提取

我们接下来试着实现流插入和流提取:

注意,我们不能将这两个函数定义放在string类里

在 C++ 中,当我们使用 std::cout << d1 或 std::cin >> d1 这样的表达式时,左侧的 std::cout 或 std::cin 是对象,而右侧的 d1 是我们想要输出或输入的数据。运算符函数需要能够接受这两个对象作为参数。 如果 << 或 >> 运算符被定义为 std::string 的成员函数,那么它们将需要额外的 this 指针来访问类的成员变量,这将导致需要三个参数(this 指针,左操作数,右操作数),这与标准的运算符用法不兼容。

string.h:

//流插入和流提取
istream& operator>>(istream& is, string& str);
ostream& operator<<(ostream& os, const string& str);

string.cpp:

// 流输入
istream& operator>>(istream& is, string& str)
{// 清除字符串 str 中的现有内容  str.clear();char ch;// 从输入流 is 中读取第一个字符到 ch 中  ch = is.get();// 定义一个字符数组(缓冲区)buffchar buff[128];size_t i = 0;// 循环读取字符,直到遇到空格或换行符为止  while (ch != ' ' && ch != '\n'){// 将字符 ch 存储到缓冲区 buff 的当前位置  buff[i++] = ch;  if (i == 127){// 在缓冲区末尾添加字符串结束符 '\0'buff[i++] = '\0';str += buff;// 重置索引 i,为下一轮存储字符做准备  i = 0;}// 从输入流中读取下一个字符到 ch 中  ch = is.get();}// 循环结束后,检查缓冲区中是否还有未处理的字符  if (i > 0){// 在缓冲区末尾添加字符串结束符 '\0'  buff[i] = '\0';// 将缓冲区的内容追加到字符串 str 中  str += buff;}return is;
}
// 流提取
ostream& operator<<(ostream& os, const string& str)
{for (size_t i = 0; i < str.size(); i++){os << str[i];}return os;
}

测试一下:

完整代码

string.h:

#include<iostream>
#include<assert.h>
#include<stdbool.h>
using namespace std;namespace My_string
{class string{public:typedef char* iterator;			//将char*重命名为iteratortypedef const char* const_iterator;//const版本的iteratorconst_iterator begin() const;	//提供const_iterator begin()函数const_iterator end() const;		//提供const_iterator end()函数//非const版本的iteratoriterator begin();				//提供iterator begin()函数iterator end();					//提供iterator end()函数string(const char* str = " ");	//构造函数~string();						//析构函数string(const string& str);		//拷贝构造函数const char* c_str() const;		// c_str()函数size_t size() const;			// size()函数size_t capacity() const;		// capacity()函数bool empty() const;				// empty()函数// resize()函数void resize(size_t n, char ch = '\0');// 非const版本char& operator[](size_t pos);	//operator[]函数// const版本const char& operator[](size_t pos)const;// 预留空间void reserve(size_t n);// 尾插一个字符void push_back(char ch);// 尾插一个字符串void append(const char* str);//operator+=函数可以构成重载,函数名相同,参数不同string& operator+=(char ch);			// 字符相加string& operator +=(const char* str);	// 字符串相加// insert()函数 void insert(size_t pos, char ch);	//插入字符void insert(size_t pos, const char* str);	//插入字符串// erase()函数void erase(size_t pos = 0, size_t len = npos);// pop_back()函数void pop_back();// find()函数size_t find(char ch, size_t pos);size_t find(const char* str, size_t pos);// substr()函数string substr(size_t pos = 0, size_t len = npos);// operator=赋值函数string& operator=(const string& s);// swap()函数void swap(string& str);// 比较函数bool operator<(const string& s)const;bool operator<=(const string& s)const;bool operator>(const string& s)const;bool operator>=(const string& s)const;bool operator==(const string& s)const;bool operator!=(const string& s)const;// clear()函数void clear();public:static const size_t npos;private:char* _str;			// 指向字符串的指针size_t _size;		// 有效字符个数size_t _capacity;	// 有效空间个数};//流插入和流提取istream& operator>>(istream& is, string& str);ostream& operator<<(ostream& os, const string& str);
}

string.cpp:

#include"string.h"
namespace My_string 
{const size_t string::npos = -1;string::iterator string::begin(){return _str;}string::iterator string::end(){return _str + _size;}string::const_iterator string::begin() const{return _str;}string::const_iterator string::end() const{return _str + _size;}// 构造函数string::string(const char* str){_size = strlen(str);_capacity = _size;_str = new char[_capacity + 1];		// +1用于储存'\0'strcpy(_str, str);}// 析构函数string::~string(){delete[] _str;_str = nullptr;_size = _capacity = 0;}// 拷贝构造函数(1)string::string(const string& str){_str = new char[str._capacity + 1];	//额外多给一个空间,用于存放'/0'strcpy(_str, str._str);		//拷贝数据_capacity = str._capacity;	//设置容量_size = str._size;			//设置有效数据个数}// 拷贝构造函数(2)//string::string(const string& str)//{//	string tmp(str._str);//	std::swap(tmp._str, _str);//	std::swap(tmp._size, _size);//	std::swap(tmp._capacity, _capacity);//}// 拷贝构造函数(3)//string::string(const string& str)//{//	string tmp(str._str);//	swap(tmp);			// 这里的swap我们接下来会定义//}// c_str()函数const char* string::c_str() const{return _str;}// size()函数size_t string::size() const{return _size;}// capacity()函数size_t string::capacity() const{return _capacity;}// empty()函数bool string::empty() const{return _size == 0;}// operator[]函数char& string::operator[](size_t pos){assert(pos < _size);return _str[pos];}// const版本const char& string::operator[](size_t pos)const{assert(pos < _size);return _str[pos];}// 预留空间void string::reserve(size_t n){if (n > _capacity){char* tmp = new char[n + 1];strcpy(tmp, _str);delete[] _str;_str = tmp;_capacity = n;}}// resize()函数void string::resize(size_t n, char ch){if (n > _size){if (n > _capacity){reserve(n);}// 使用 memset 函数将字符 ch // 填充到新添加的空间中memset(_str + _size, ch, n - _size);}_size = n;_str[n] = '\0';}//尾插一个字符void string::push_back(char ch){if (_capacity == _size){size_t newcapacity = _capacity == 0 ? 4 : 2 * _capacity;reserve(newcapacity);}_str[_size] = ch;_str[_size + 1] = '\0';_size++;}//尾插一个字符串void string::append(const char* str){size_t len = strlen(str);if (_size + len > _capacity) {reserve(_size + len);}strcpy(_str+_size, str);_size += len;			}string& string::operator+=(char ch){// 调用push_back()函数push_back(ch);		return *this;}string& string::operator+=(const char* str){append(str);return *this;}// insert()函数// 插入字符void string::insert(size_t pos, char ch){assert(pos <= _size);if (_capacity == _size){size_t newcapacity = _capacity == 0 ? 4 : 2 * _capacity;reserve(newcapacity);}size_t end = _size + 1;// 挪动元素while (pos < end){_str[end] = _str[end - 1];end--;}_str[pos] = ch;		//将ch放置到pos这个位置++_size;			//更新_size}// 插入字符串void string::insert(size_t pos, const char* str){assert(pos <= _size);size_t len = strlen(str);	// 要插入的字符串长度if (_size + len > _capacity){reserve(_size + len);}// 从后向前移动字符串内容以腾出空间  for (size_t i = _size; i >= pos; --i){_str[i + len] = _str[i];}// 复制新字符串到指定位置  memcpy(_str + pos, str, len);// 添加新的字符串结束符  _str[_size + len] = '\0';// 更新字符串长度  _size += len;}// erase()函数void string::erase(size_t pos,size_t len){assert(pos < _size);				 if (len == npos || len >= _size - pos){_str[pos] = '\0';		// 位置pos置为'\0'_size = pos;			// 有效元素个数为pos个}else	// len小于后面的字符个数{// 将后面的字符拷贝到pos位置strcpy(_str + pos, _str + pos + len);_size -= len;			// 更新有效元素}}// pop_back()函数void string::pop_back(){_str[_size - 1] = '\0';--_size;}// find()函数// 寻找字符size_t string::find(char ch, size_t pos){for (int i = pos; i < _size; i++){if (_str[i] == ch){return i;}}return npos;}// 从pos开始寻找字符串size_t string::find(const char* str, size_t pos){char* p = strstr(_str + pos, str);if (p){return p - _str;}else{return npos;}}// substr()函数string string::substr(size_t pos, size_t len){string str;if (len == npos || len >= _size - pos){for (size_t i = pos; i < _size; i++){str += _str[i];}}else{for (size_t i = pos; i < pos + len; i++){str += _str[i];}}return str;}// operator= 函数//string& string::operator=(const string& str)//{//	if (this != &str)//	{//		char* tmp = new char[str._capacity + 1];//		strcpy(tmp, str._str);//		delete[] _str;//		_str = tmp;//		_size = str._size;//		_capacity = str._capacity;//	}//	return *this;//}// operator= 函数string& string::operator=(const string& str){if (this != &str){string tmp(str._str);	// 调用构造函数swap(tmp);				// 将tmp与this交换}return *this;}// swap()函数void string::swap(string& str){// 这里我们调用std库中的swap()函数std::swap(_str, str._str);std::swap(_capacity, str._capacity);std::swap(_size, str._size);}// 比较函数bool string::operator<(const string& str) const{return strcmp(_str, str._str) < 0;}bool string::operator<=(const string& str) const{return *this < str || *this == str;}bool string::operator>(const string& str) const{return !(*this <= 0);}bool string::operator>=(const string& str) const{return !(*this <= str);}bool string::operator==(const string& str)const{return strcmp(_str, str._str) == 0;}bool string::operator!=(const string& str)const{return !(*this == str);}void string::clear(){_str[0] = '\0';_size = 0;}// 流输入istream& operator>>(istream& is, string& str){// 清除字符串 str 中的现有内容  str.clear();char ch;// 从输入流 is 中读取第一个字符到 ch 中  ch = is.get();// 定义一个字符数组(缓冲区)buffchar buff[128];size_t i = 0;// 循环读取字符,直到遇到空格或换行符为止  while (ch != ' ' && ch != '\n'){// 将字符 ch 存储到缓冲区 buff 的当前位置  buff[i++] = ch;  if (i == 127){// 在缓冲区末尾添加字符串结束符 '\0'buff[i++] = '\0';str += buff;// 重置索引 i,为下一轮存储字符做准备  i = 0;}// 从输入流中读取下一个字符到 ch 中  ch = is.get();}// 循环结束后,检查缓冲区中是否还有未处理的字符  if (i > 0){// 在缓冲区末尾添加字符串结束符 '\0'  buff[i] = '\0';// 将缓冲区的内容追加到字符串 str 中  str += buff;}return is;}// 流提取ostream& operator<<(ostream& os, const string& str){for (size_t i = 0; i < str.size(); i++){os << str[i];}return os;}
}

test.cpp:

#include"string.h"
#include<iostream>using namespace std;void test1()
{// 测试构造函数  My_string::string s1("Hello");cout << "s1: " << s1.c_str() << endl;// 测试拷贝构造函数  /*My_string::string s2(s1);cout << "s2 (s1): " << s2.c_str() << endl;	*/
}void test2()
{My_string::string str("Hello");str[0] = 'h';cout << str.c_str() << endl;//使用operator[]函数打印for (size_t i = 0; i < str.size(); i++){cout << str[i] << " ";}cout << endl;
}void test3()
{My_string::string str("hello");for (auto i : str){cout << i << " ";}cout << endl;My_string::string::iterator it1 = str.begin();while (it1 != str.end()){cout << *it1 << " ";++it1;}cout << endl;My_string::string::iterator it2 = str.end();if (it2 != str.begin()) { // 检查避免直接解引用 end()  --it2; // 先移动到一个有效的位置  while (it2 != str.begin()){std::cout << *it2 << " ";--it2;}std::cout << *it2 << " "; // 输出最后一个字符(begin() 之前的字符)  }std::cout << std::endl;
}void test4()
{My_string::string str("hello");cout << str.c_str() << endl;str.push_back('A');cout << str.c_str() << endl;str.append("world");cout << str.c_str() << endl;str += 'C'; cout << str.c_str() << endl;
}void test5()
{My_string::string str("hello world");str.insert(6, 'x');cout << str.c_str() << endl;str.insert(6, "yyyyy");cout << str.c_str() << endl;str.insert(0, 'X');cout << str.c_str() << endl;
}void test6()
{My_string::string str("hello world");str.pop_back();cout << str.c_str() << endl;str.erase(2, 3);cout << str.c_str() << endl;
}void test7()
{My_string::string str("hello world");cout << str.find('l', 0) << endl;cout << str.find("ld", 0) << endl;
}void test8()
{My_string::string str1("hello");My_string::string str2("world");cout << str1.c_str() << endl;cout << str2.c_str() << endl;str1.swap(str2);cout << str1.c_str() << endl;cout << str2.c_str() << endl;
}void test9()
{My_string::string str("hello World");cout << str.substr(2, 2) << endl;cout << str.substr(7, 3) << endl;
}void test10()
{My_string::string str1("hello world");My_string::string str2("xxxxxxxxxxx");str1 = str2;cout << str1.c_str() << endl;cout << str2.c_str() << endl;My_string::string str3("yyyyy");str1 = str3;cout << str1.c_str() << endl;cout << str3.c_str() << endl;
}void test11()
{My_string::string str("hello");str.resize(10, '*');cout << str.c_str() << endl;str.reserve(15);cout << str.c_str() << endl;
}void test12()
{My_string::string str("XXX");cin >> str;cout << str << endl;
}int main()
{//test1();//test2();//test3();//test4();//test5();//test6();//test7();//test8();//test9();//test10();//test11();test12();return 0;
}

结束语

实验周太忙啦!!!一直没时间写。。。

感谢各位大佬的阅读!!!

求点赞收藏评论关注!!!

相关文章:

C++——string的模拟实现(下)

目录 成员函数 3.4 修改操作 (3)insert()函数 (4)pop_back()函数 (5)erase()函数 (6)swap()函数 3.5 查找操作 (1)find()函数 (2)substr()函数 3.6 重载函数 (1)operator赋值函数 (2)其他比较函数 (3)流插入和流提取 完整代码 结束语 第一篇链接&#xff1a;C——…...

面试 Java 基础八股文十问十答第二十九期

面试 Java 基础八股文十问十答第二十九期 作者&#xff1a;程序员小白条&#xff0c;个人博客 相信看了本文后&#xff0c;对你的面试是有一定帮助的&#xff01;关注专栏后就能收到持续更新&#xff01; ⭐点赞⭐收藏⭐不迷路&#xff01;⭐ 1&#xff09;类加载过程 类加载…...

454.四数相加||

题目: 454. 四数相加 II - 力扣&#xff08;LeetCode&#xff09; 思路: 考虑到时间复杂度问题&#xff0c;本题最重要的是要将四个数组划分成两个部分&#xff0c;每个部分(n^2)的时间复杂度&#xff0c;选取数据结构时&#xff0c;考虑到既要存储元素(key),又要有元素次数…...

禅道源码部署

文章目录 禅道部署1.环境部署安装httpd和mariadb安装php 2.安装禅道首先进行httpd服务的配置安装禅道 禅道部署 1.环境部署 安装lamp环境 组件版本httpdyum安装mariadbyum安装phpphp-7.4.33 选择一个php版本就行&#xff0c;我们这里选择的是7.4.33 安装httpd和mariadb [r…...

️ Vulnhuntr:利用大型语言模型(LLM)进行零样本漏洞发现的工具

在网络安全领域&#xff0c;漏洞的发现和修复是保护系统安全的关键。今天&#xff0c;我要向大家介绍一款创新的工具——Vulnhuntr&#xff0c;这是一款利用大型语言模型&#xff08;LLM&#xff09;进行零样本漏洞发现的工具&#xff0c;能够自动分析代码&#xff0c;检测远程…...

【Android】多渠道打包配置

目录 简介打包配置签名配置渠道配置配置打包出来的App名称正式包与测试包配置 打包方式开发工具打包命令行打包 优缺点 简介 多渠道打包 是指在打包一个 Android 应用时&#xff0c;一次编译生成多个 APK 文件&#xff0c;每个 APK 文件针对一个特定的渠道。不同的渠道可能代表…...

Spring Boot Configuration和AutoConfiguration加载逻辑和加载顺序调整

在spring中, AutoConfiguration也是一个种Configuration,只是AutoConfiguration是不能使用proxy的。 而且spring对于两者的加载顺序也不是一视同仁,是有顺序的。spring会先加载@SpringBootApplication可达的且标注了@Configuration的类,这个过程会将@AutoConfiguration标注…...

点餐系统需求分析说明书(软件工程分析报告JAVA)

目录 1 引言 4 1.1 编写目的 4 1.2 项目背景 4 1.3 定义 4 1.4 预期的读者 5 1.5 参考资料 5 2 任务概述 5 2.1 目标 5 2.2 运行环境 5 2.3 条件与限制 6 3 数据描述 6 3.1 静态数据 6 3.2 动态数据 6 3.3 数据库介绍 6 3.4 对象模型 6 3.5 数据采集 7 4 动态模型 7 4.1 脚本 …...

Python条形图 | 指标(特征)重要性图的绘制

在数据科学和机器学习的工作流程中&#xff0c;特征选择是一个关键步骤。通过评估每个特征对模型预测能力的影响&#xff0c;我们可以选择最有意义的特征&#xff08;指标&#xff09;&#xff0c;从而提高模型的性能并减少过拟合。本文将介绍如何使用 Python 的 Seaborn 和 Ma…...

危险物品图像分割系统:一键训练

危险物品图像分割系统源码&#xff06;数据集分享 [yolov8-seg-GFPN&#xff06;yolov8-seg-CSwinTransformer等50全套改进创新点发刊_一键训练教程_Web前端展示] 1.研究背景与意义 项目参考ILSVRC ImageNet Large Scale Visual Recognition Challenge 项目来源AAAI Global…...

城市景色视频素材下载好去处

在制作短视频、Vlog 或商业宣传片时&#xff0c;城市景色视频素材能为作品增添现代感与活力。繁华都市、流光溢彩的夜景、清晨街道等都是展现城市魅力的好素材。那么城市景色视频素材去哪里下载呢&#xff1f; 蛙学网 是专为短视频创作者打造的素材平台&#xff0c;城市景色素材…...

基于SSM美容院管理系统的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;用户管理&#xff0c;套餐类型管理&#xff0c;美容预约管理&#xff0c;生日提醒管理&#xff0c;管理员管理&#xff0c;系统管理 员工账号功能包括&#xff1a;系统首页&#xff0c;个人中心&#…...

Threejs 实现3D 地图(04)3d 地图的柱状图和文字显示

3d 地图的数据展示 代码仓库&#xff1a; King/threejs-3d-map 核心代码&#xff1a; function createText(feature, level, font) {if (feature.properties.name) {const [x_XYZ, y_XYZ] handleProject(feature.properties.center)// 缺点&#xff1a;首次渲染很慢 无法使…...

Oracle 第2章:安装与配置Oracle

安装与配置Oracle数据库是一项复杂但有序的过程。以下是对Oracle数据库安装与配置的概述&#xff0c;包括系统需求与硬件推荐&#xff0c;以及详细的安装步骤。 系统需求与硬件推荐 系统需求 在安装Oracle数据库之前&#xff0c;需要确保目标系统满足Oracle官方规定的最低要…...

动态规划 —— 斐波那契数列模型-解码方法

1. 解码方法 题目链接&#xff1a; 91. 解码方法 - 力扣&#xff08;LeetCode&#xff09;https://leetcode.cn/problems/decode-ways/description/ 2. 题目解析 1. 对字母A - Z进行编码1-26 2. 11106可以解码为1-1-10-6或者11-10-6, 但是11-1-06不能解码 3. 0n不能解码 4. …...

PPT / Powerpoint中利用LaTeX输入公式

PPT / Powerpoint中利用LaTeX输入公式_ppt插入latex公式-CSDN博客文章浏览阅读2.8w次&#xff0c;点赞42次&#xff0c;收藏75次。新版的Word&#xff08;Office 2016后&#xff1f;&#xff09;是支持LaTeX公式输入的&#xff0c;但是Powerpoint并不支持。下面介绍如何利用。_…...

C++ 模板专题 - 类型擦除

一&#xff1a;概述 C 中的类型擦除&#xff08;Type Erasure&#xff09;是一种技术&#xff0c;允许你在不暴露具体类型信息的情况下&#xff0c;通过统一的接口处理不同的类型。这种技术常用于实现泛型编程&#xff0c;特别是在需要支持多种不同类型的情况下&#xff0c;如容…...

RuoYi-Vue项目 重点代码讲解

1. RuoYi-Vue项目 常规说明&#xff1a; ruoyi-admin&#xff1a;后台接口开发&#xff08;主要存放控制层相关代码&#xff09;ruoyi-common&#xff1a;通用工具ruoyi-framework&#xff1a;框架核心ruoyi-generator&#xff1a;代码生成&#xff08;可以移除&#xff09;r…...

pandas习题 024:用字典构造 DataFrame

编码题)用 Python 的字典构造一个 DataFrame,它有 a、b 两列,三行数据。其中 a 列值为 1、4、7,b 列值为 2、5、8,索引为 x、y、z。 即: ‘’’ a b x 1 2 y 4 5 z 7 8 ‘’’ import pandas as pddf = pd.DataFrame({a: [1, 4,...

如何在Node.js中执行解压缩文件操作

一、解压文件 1.安装依赖&#xff1a; 安装adm-zip依赖包&#xff1a;npm install adm-zip --save 安装iconv-lite依赖包&#xff1a;npm install iconv-lite --save 解压前的file文件夹结构&#xff1a; update-1.0.2.zip压缩包内容&#xff1a; 2.在depresssFile.js文件&…...

梦熊 CSP-S模拟赛 T3 youyou 的序列 II

原题链接 题目大意 给定一个长度为 n 的非负整数序列 a &#xff0c;初始时所有数字均被标记为蓝色&#xff0c;youyou 和 yy 轮流对序列 a 进行操作&#xff0c;由 youyou 开始。 • 如果当前是 youyou 的回合&#xff0c;那么他可以至多选择连续的 c 1 个数…...

记录下docker部署gitlab-ce-17.5版本及客户端git拉取方式配置

服务端部署 # 提前拉取镜像 docker pull gitlab/gitlab-ce:17.5.0-ce.0docker run -d \ --name gitlab \ --hostname gitlab.test.cn \ -p 443:443 \ -p 88:80 \ -p 2222:22 \ --restartalways \ -v /data/gitlab/config:/etc/gitlab \ -v /data/gitlab/logs:/var/log/gitlab …...

opencv-platform实现人脸识别

和同事接触了下甲方,对方算是一个资源整合的自由人&#xff0c;手里有项目&#xff0c;然后认识些开发就聊下有什么事情可以做的&#xff0c;对方聊了下做人脸签到&#xff0c;或者说人脸打开。就这方面我做了下简单的了解。做了个java小demo。 我们常用的人脸识别的摄像头屏幕…...

leetcode 有重复字符串的排列组合

1.题目要求: 2.题目代码&#xff1a; class Solution { public://运用回溯vector<string> result;string s;void backtricking(string S,vector<bool>& used){if(s.size() S.size()){result.push_back(s);return;}for(int i 0;i < S.size();i){if(i >…...

【大数据学习 | kafka】kafka的组件架构

broker:每个kafka的机器节点都会运行一个进程&#xff0c;这个进程叫做broker&#xff0c;负责管理自身的topic和partition&#xff0c;以及数据的存储和处理&#xff0c;因为kafka是集群形式的&#xff0c;所以一个集群中会存在多个broker&#xff0c;但是kafka的整体又不是一…...

Python基于TensorFlow实现简单循环神经网络回归模型(SimpleRNN回归算法)项目实战

说明&#xff1a;这是一个机器学习实战项目&#xff08;附带数据代码文档视频讲解&#xff09;&#xff0c;如需数据代码文档视频讲解可以直接到文章最后关注获取。 1.项目背景 Simple RNN是一种基础的循环神经网络&#xff0c;它能够处理序列数据&#xff0c;例如文本、时间序…...

torch.isclose

torch.isclose是 PyTorch 中的一个函数&#xff0c;用于判断两个张量中的对应元素是否接近相等。 其函数签名为&#xff1a;torch.isclose(input, other, rtol1e-05, atol1e-08, equal_nanFalse)。 参数说明&#xff1a; input 和 other&#xff1a;要进行比较的两个张量。r…...

Python记录-字典

定义 Python 中的字典&#xff08;dictionary&#xff09;是一种内置的数据结构&#xff0c;用于存储键值对&#xff08;key-value pairs&#xff09;。字典中的每个键&#xff08;key&#xff09;都是唯一的&#xff0c;并且与一个值&#xff08;value&#xff09;相关联。键…...

python读取学术论文PDF文件内容

目录 1、PyPDF22、pdfplumber3、PyMuPDF4、pdfminer总结 1、PyPDF2 PyPDF2 是一个常用的库&#xff0c;可以用来读取、合并、分割和修改PDF文件。读取pdf内容&#xff1a; import PyPDF2# 打开PDF文件 with open(ELLK-Net_An_Efficient_Lightweight_Large_Kernel_Network_for…...

5550 取数(max)

经验值&#xff1a;2000 时间限制&#xff1a;1000毫秒 内存限制&#xff1a;128MB 庐阳区2020年信息学竞赛试题 不许抄袭&#xff0c;一旦发现&#xff0c;直接清空经验&#xff01; 题目描述 Description 盒子里面有N个球&#xff0c;每个球上都一个数。你每次可以取走一…...

平台流量排名/重庆百度快照优化

平台&#xff1a;VC 2005 测试通过&#xff01;.vcproj这是使用应用程序向导生成的 VC 项目的主项目文件。 它包含生成该文件的 Visual C 的版本信息&#xff0c;以及有关使用应用程序向导选择的平台、配置和项目功能的信息。StdAfx.h, StdAfx.cpp这些文件用于生成名为 twod.pc…...

香港网站怎么做QQ第三方登录/写手接单平台

有种很方便的写法。typedef int *p&#xff1b;p pointer&#xff1b;这时直接把pointer带入原式中&#xff0c;取代p然后去掉typedef&#xff0c;得到的结果就是int * pointer&#xff1b;哈哈&#xff0c;这样直接替换就很直观多了。C语言语法简单&#xff0c;但内涵却博大精…...

网站网站优化/长沙网站建设公司

1、什么是Mybatis&#xff1f;(1)Mybatis是一个半ORM(对象关系映射)框架&#xff0c;它内部封装了JDBC&#xff0c;开发时只需要关注SQL语句本身&#xff0c;不需要花费精力去处理加载驱动、创建连接、创建statement等繁杂的过程。程序员直接编写原生态sql&#xff0c;可以严格…...

网站建设 慕课/网络营销与网站推广的

流程&#xff1a; 17年底,mask-R CNN DPM、R-CNN、YOLO、SSD 1、基于传统图像处理和机器学习算法的目标检测与识别方法 传统的目标检测与识别方法主要可以表示为&#xff1a;目标特征提取->目标识别->目标定位。 这里所用到的特征都是认为设计的&#xff0c;例如SIFT (尺…...

做企业网站价格/seo建站网络公司

第1关:平移、缩放、旋转正方体 (1) 理解几何变换基本原理, 掌握平移、旋转、缩放变换的方法; (2) 根据平移算法原理补全translation、scale、rotation_x、rotation_y和rotation_z函数; (3) 根据几何变换基本原理,将main函数中的translation、scale、rotation_z参数补充完整。…...

中国最大网站建设公司/最近的热点新闻

一般情况下&#xff0c;我们用Qt编译出来的程序是要依赖于系统Qt库的&#xff0c;也就是这个程序移到别的没有安装Qt库的系统上是不能使用的。会提示缺少……库文件之类的错误。这就是动态编译的结果。但是如果我们想编译一个程序&#xff0c;这个程序在发给别人后&#xff0c;…...