【c++】string模拟实现

string类的接口

namespace zjw
{class string{public:typedef char* iterator;typedef   const char* const_iterator;private:char* _str;int _size;int _capacity;};

这里的迭代器直接使用原生指针来封装。
_str为指向string数组的首地址的指针。
_size为string数组的大小。
_capacity为string数组的容量

基本函数

实现 函数返回string的首地址;
实现 函数返回string的尾地址;
实现 函数返回string的大小;
实现 函数返回string的容量;

	iterator begin(){return _str;}iterator end(){return _str+_size;}size_t size(){return _size;}size_t capacity(){return _capacity;}

如果一个string类不能被修改的话,就无法调用非const的成员函数
在这里插入图片描述

	const_iterator begin() const{return _str;}const_iterator end() const{return _str + _size;}

默认构造以及析构函数

	string(const char* str = ""):_size(strlen(str)){_capacity = _size;_str = new char[_capacity + 1];strcpy(_str, str);}~string(){ delete[]_str;_str = nullptr;_size = _capacity = 0;}

这里有一个问题,就是默认构造传的缺省参数可以是nullptr 吗??
答案是不行的,因为strlen要将str解引用找’\0’,如果传nullptr的话,对空指针解引用就会出错。
这里也不可以传单字符‘\0’,因为这里的str是const char* 类型,而’\0’是char 类型


运算符重载下标访问函数

	char& operator[](size_t pos){assert(pos<_size);return _str[pos];}const char& operator[](size_t pos) const{assert(pos < _size);return _str[pos];}

下标为_size的地方存的是’\0’,所以不用访问,pos<_size,为了让const迭代器不修改对于下标的值,修改上面得到下面,对上面进行函数重载

reserve函数

	void reserve(size_t n){if (n > _capacity){char* tmp = new char[n + 1];strcpy(tmp, _str);delete[]_str;_str = tmp;_capacity = n;}}

在这里插入图片描述
注意:这里多开一个是为了存’\0’;

push_back()函数

	void push_back(char ch){if (_capacity == _size){reserve(_capacity == 0 ? 4 : _capacity * 2);}_str[_size] = ch;_size++;_str[_size] = '\0';}

原来下标是_size的地方是‘\0’,然后之间在_size的地方放入ch,_size++,染后在补一个’\0’;要插入数据的一半都要扩容

append函数

	void append(const char* str){size_t len = strlen(str);if (_size + len > _capacity){reserve(_size + len);}strcpy(_str + _size, str);_size += len;//_str[_size] = '\0';}

尾插一个字符串,如果string的大小+要插入的字符串大小>_capacity,就扩容到_size + len,刚好,strcpy会从str开始直到遇到‘\0’一个字节一个字节拷贝到_str + _size(原字符串’\0’的地方),这里会把str字符串后面的‘\0’也拷贝过来。

运算符重载+=字符以及+=字符串

	string& operator+=(char ch){push_back(ch);return *this;}string& operator+=(const char* str){append(str);return *this;}

在这里传引用返回是因为_str指向的空间是在堆上开的,出函数不会被销毁,所以可以传引用返回

insert函数(插入字符)

void insert(size_t pos, char ch){assert(pos<=_size);if (_capacity == _size){reserve(_capacity == 0 ? 4 : _capacity * 2);}size_t end = _size;while (end >=pos){_str[end+1] = _str[end];end--;}_str[pos] = ch;_size++;}

上面这个写法可以吗??
是不可以的
在这里插入图片描述
怎么修改呢??

	void insert(size_t pos, char ch){assert(pos<=_size);if (_capacity == _size){reserve(_capacity == 0 ? 4 : _capacity * 2);}size_t end = _size+1;while (end >pos){_str[end] = _str[end-1];end--;}_str[pos] = ch;_size++;}

这样就可以了,我们从’\0’的下一个位置开始end,此时end结束的条件是=0,所以不会陷入循环,这里和顺序表的insert很像,可以参考顺序表那里。


earse函数

	void earse(size_t pos, size_t len = npos){assert(pos < _size);if (len == npos || pos > _size-len){_str[pos] = '\0';_size = pos;}else{strcpy(_str + pos, _str + pos + len);_size -= len;}}

删除从pos位置开始的len个字符长度的字符,如果len大于剩下的字符,就全删了,这里给的缺省值为npos=-1,可以认为是很大的数,绝对超过了pos后面的字符数,我们要在string里面声明一个npos,在类外面定义初始化。
在这里插入图片描述

如果len==npos或者len+pos>_size,就始要将pos开始后面的字符串全删除,我们直接在pos位置放’\0’即可,
_size=pos;
如果没有超过字符串
在这里插入图片描述


insert(插入字符串)

void insert(size_t pos, const char* str){size_t len = strlen(str);if (_size + len > _capacity){reserve(_size + len);}size_t end = _size + len;while (end > pos + len - 1){_str[end] = _str[end - len];end--;}strncpy(_str + pos, str, len);_size += len;}

![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/9d88ba8502954c0dbd884890654c612a.png

void test6(){string str;str.push_back('a');str.push_back('a');str.push_back('b');str.insert(2, "hello");cout << str.c_str();}

swap

	void swap(string& str){std::swap(_str, str._str);std::swap(_size, str._size);std::swap(_capacity, str._capacity);}
	void test12(){   string str1;string str2;str1 += "hello";str2+="nihao";cout << "str1:"<<str1 << endl;cout << "str2:"<<str2 << endl;str1.swap(str2);cout << "str1:" << str1 << endl;cout << "str2:" << str2 << endl;}

在这里插入图片描述


这里我们自己实现的swap是类成员函数,但是#include< algorithm >这个头文件库里面也有一个swap,swap全局也有一个非成员函数swap

在这里插入图片描述

我们可以发现算法库中的swap需要完成三次的拷贝,以及一次析构(临时变量c的析构),而string里面定义一个全局的swap,就是为了防止调用算法库里面的swap,因为会先在全局找,然后会在展开的库里找,而全局的swap实现只需要调用类里面的swap即可

	void swap(string& x, string& y){x.swap(y);cout << "没使用库里的" << endl;}
	void test13(){string str1;string str2;str1 += "hello";str2 += "nihao";cout << "str1:" << str1 << endl;cout << "str2:" << str2 << endl;swap(str1, str2);//检测是调用库里的,还是全局的cout << "str1:" << str1 << endl;cout << "str2:" << str2 << endl;}

在这里插入图片描述

赋值以及拷贝构造

	string(const string& s){string tmp(s._str);swap(tmp);}string& operator=(string tmp){swap(tmp);return *this;}

根据调试发现
在这里插入图片描述

老版本赋值

		string& operator=(const string& s){char* tmp = new char[s._capacity + 1];strcpy(tmp, s._str);delete[] _str;_str = tmp;_size = s._size;_capacity = s._capacity;return *this;}

find函数(查找字符)

	size_t find(char ch, size_t pos = 0){for (int i = pos; i < _size; i++){if (_str[i] == ch)return i;}return npos;}

从pos位置开始查找,如果pos使用缺省,则从第一个位置开始查找,从pos位置开始遍历,如果找到返回下标,如果找不到返回npos

	void test7(){string str;str.push_back('a');str.push_back('a');str.push_back('b');str.insert(2, "hello");cout << endl;int ret = str.find('b', 0);cout << ret;}

在这里插入图片描述


find函数(查找子串)

		size_t find(const char* sub, size_t pos = 0) const{assert(pos < _size);//下标为_size的是‘\0’const char* ptr = strstr(_str + pos, sub);if (ptr != nullptr)//找到了,但是strstr返回的是找到子串的起始地址-字符串起始地址就是子串相对起始位置的长度{return ptr - _str;}else{return npos;}}
	void test8(){string str;str += "beijing huanyingni zhangjiawang";int ret = str.find("zhangjiawang");cout << ret;}

在这里插入图片描述


substr函数

string substr(size_t pos = 0, size_t len = npos) const{string substr;if (pos > _size - len){for (int i = pos; i <= _size; i++){substr += _str[i];}}else{for (int i = pos; i < pos + len; i++){substr += _str[i];}substr += '\0';}return substr;}

从pos位置开始取,取len个长度,分两种情况,如果从pos开始还没取到len长,就结束,就取到结尾,遍历pos到_size,string substr 保存遍历的值.
第二种,遍历pos到pos+len,string substr 保存遍历的值.最后记得加‘\0’;
在这里插入图片描述

运算符重载比较函数

	bool operator==(const string& s1, const string& s2){return strcmp(s1.c_str(), s2.c_str())==0;}bool operator>(const string& s1, const string& s2){return strcmp(s1.c_str(), s2.c_str());}bool operator<(const string& s1, const string& s2){return  !(s1 > s2 && s1 == s2);}bool operator<=(const string& s1, const string& s2){return  !(s1 > s2);}bool operator>=(const string& s1, const string& s2){return  !(s1 < s2);}bool operator!=(const string& s1, const string& s2){return  !(s1 == s2);}

注意这里为什么要搞成全局的呢??

	void test10(){string str1;string str2;str1 += "abc";str2 += "aba";cout << (str1 == str2) << endl;cout << ("aba" == str2) << endl;//2cout << (str2== "aba") << endl;}

因为第二种的话不满足类成员做左操作数,全局的话就可以,而第三个是会搞一个类型转换.

	void test10(){string str1;string str2;str1 += "abc";str2 += "aba";cout << (str1 == str2) << endl;cout << ("aba" == str2) << endl;cout << (str2== "aba") << endl;cout << (str1>str2) << endl;cout << (str1 >=str2) << endl;cout << (str1<str2) << endl;cout << (str1 <=str2) << endl;cout << (str1!=str2) << endl;}

在这里插入图片描述


运算符重载流插入

	ostream& operator<<(ostream& out, const string& s){for (auto e : s)//遍历一个一个输出{out << e;}return out;}

有返回值是为了可以连续流插入

运算符重载流提取

版本一:

	istream& operator>>(istream& in, string& s){char ch;in >> ch;//读取字符到chwhile (ch != ' ' && ch != '\n')//读到‘ ’或‘\n’结束输入{s += ch;//将ch加进去in >> ch;//循环读取}return in;}

这样写会有一个问题,就是cin和scanf一样默认‘\n’和‘ ’是分割符不会进行读取,所以ch不会是空格或换行,所以陷入死循环.
在这里插入图片描述
版本2:
c语言中可以用getchar来读取,而c++中存在get就可以读空格

istream& operator>>(istream& in, string& s){char ch;in.get(ch);while (ch != ' ' && ch != '\n'){s += ch;in.get(ch);}return in;}
	void test11(){string str1;string str2;cin >> str1;//>>str2;//>>str2;cout << str1;//cout << str1.capacity();}

在这里插入图片描述


版本3
由于我们在s+=ch,会出现频繁扩容,影响效率,我们应该怎么解决呢??
我们可以提前开好空间,但是不知道应该开多大.假如说我们开128个

	istream& operator>>(istream& in, string& s){char ch;in.get(ch);s.reserve(128);while (ch != ' ' && ch != '\n'){s += ch;in.get(ch);}return in;}
	void test11(){string str1;string str2;cin >> str1;//>>str2;//>>str2;//cout << str1;cout << str1.capacity();}

在这里插入图片描述
两个数据开128就会有极大的浪费,多一点还好
在这里插入图片描述
版本4

	istream& operator>>(istream& in, string& s){s.clear();//可能我们s里面之前有数据,但是流提取是要覆盖的char ch;ch = in.get();char buff[128];int i = 0;while (ch != ' ' && ch != '\n'){buff[i++] = ch;if (i == 127){buff[127] = '\0';s += buff;i = 0;}ch = in.get();}if (i > 0){buff[i] = '\0';s += buff;}return in;}

这里感觉可以类比冯诺依曼体系,buff就相当于内存,先将输入的值放在内存buff里面,等到装满了,在一次性给s,减少搬运次数.避免了一次空间开的很大,而数据只有几个
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

clear

	void clear(){_size = 0;_str[0] = '\0';}

c_str

将const string* 转化为const char*

	const char* c_str() const{return _str;}

cout不能直接处理自定义类型string,但是可以使用c_str将string转成常量字符串,内置类型就可以直接打印


源码

.h

#pragma once
#define _CRT_SECURE_NO_WARNINGS
using namespace std;
#include<assert.h>
#include<iostream>
#include<algorithm>
namespace zjw
{class string{public:typedef char* iterator;typedef   const char* const_iterator;iterator begin(){return _str;}iterator end(){return _str + _size;}const_iterator begin() const{return _str;}const_iterator end() const{return _str + _size;}string(const char* str = ""):_size(strlen(str)){_capacity = _size;_str = new char[_capacity + 1];strcpy(_str, str);}~string(){delete[]_str;_str = nullptr;_size = _capacity = 0;}size_t size(){return _size;}size_t capacity(){return _capacity;}char& operator[](size_t pos){assert(pos < _size);return _str[pos];}const char& operator[](size_t pos) const{assert(pos < _size);return _str[pos];}void reserve(size_t n){if (n > _capacity){char* tmp = new char[n + 1];strcpy(tmp, _str);delete[]_str;_str = tmp;_capacity = n;}}void push_back(char ch){if (_capacity == _size){reserve(_capacity == 0 ? 4 : _capacity * 2);}_str[_size] = ch;_size++;_str[_size] = '\0';}void append(const char* str){size_t len = strlen(str);if (_size + len > _capacity){reserve(_size + len);}strcpy(_str + _size, str);_size += len;//_str[_size] = '\0';}string& operator+=(char ch){push_back(ch);return *this;}string& operator+=(const char* str){append(str);return *this;}void insert(size_t pos, char ch){assert(pos <= _size);if (_capacity == _size){reserve(_capacity == 0 ? 4 : _capacity * 2);}size_t end = _size + 1;while (end > pos){_str[end] = _str[end - 1];end--;}_str[pos] = ch;_size++;}const char* c_str() const{return _str;}void earse(size_t pos, size_t len = npos){assert(pos < _size);if (len == npos || pos > _size - len){_str[pos] = '\0';_size = pos;}else{strcpy(_str + pos, _str + pos + len);_size -= len;}}bool empty(){return _size == 0;}void resize(size_t n, char ch = '\0'){if (n <= _size){_str[n] = '\0';_size = n;}else{reserve(n);for (size_t i = _size; i < n; i++){_str[i] = ch;}_size = n;}}void insert(size_t pos, const char* str){size_t len = strlen(str);if (_size + len > _capacity){reserve(_size + len);}size_t end = _size + len;while (end > pos + len - 1){_str[end] = _str[end - len];end--;}strncpy(_str + pos, str, len);_size += len;}size_t find(char ch, size_t pos = 0){for (int i = pos; i < _size; i++){if (_str[i] == ch)return i;}return npos;}size_t find(const char* sub, size_t pos = 0) const{assert(pos < _size);const char* ptr = strstr(_str + pos, sub);if (ptr != nullptr){return ptr - _str;}else{return npos;}}string substr(size_t pos = 0, size_t len = npos) const{string substr;if (pos > _size - len){for (int i = pos; i <= _size; i++){substr += _str[i];}}else{for (int i = pos; i < pos + len; i++){substr += _str[i];}substr += '\0';}return substr;}void swap(string& str){std::swap(_str, str._str);std::swap(_size, str._size);std::swap(_capacity, str._capacity);}string(const string& s){string tmp(s._str);swap(tmp);}string& operator=(string tmp){swap(tmp);return *this;}string& operator=(const string& s){char* tmp = new char[s._capacity + 1];strcpy(tmp, s._str);delete[] _str;_str = tmp;_size = s._size;_capacity = s._capacity;return *this;}void clear(){_size = 0;_str[0] = '\0';}friend istream& operator>>(istream& in, string& s);public:static const int  npos;private:char* _str;int _size;int _capacity;};const int string::npos = -1;void swap(string& x, string& y){x.swap(y);cout << "没使用库里的" << endl;}istream& operator>>(istream& in, string& s){s.clear();char ch;ch = in.get();char buff[128];int i = 0;while (ch != ' ' && ch != '\n'){buff[i++] = ch;if (i == 127){buff[127] = '\0';s += buff;i = 0;}ch = in.get();}if (i > 0){buff[i] = '\0';s += buff;}return in;}//istream& operator>>(istream& in, string& s)//{//	//	char ch;//	//	in.get(ch);//	//	s.reserve(128);//	while (ch != ' ' && ch != '\n')//	{//	//	//		s += ch;//		in.get(ch);//	}//	//		//		//	//	return in;//}bool operator==(const string& s1, const string& s2){return strcmp(s1.c_str(), s2.c_str())==0;}bool operator>(const string& s1, const string& s2){return strcmp(s1.c_str(), s2.c_str());}bool operator<(const string& s1, const string& s2){return  !(s1 > s2 && s1 == s2);}bool operator<=(const string& s1, const string& s2){return  !(s1 > s2);}bool operator>=(const string& s1, const string& s2){return  !(s1 < s2);}bool operator!=(const string& s1, const string& s2){return  !(s1 == s2);}ostream& operator<<(ostream& out, const string& s){for (auto e : s){out << e;}return out;}//istream& operator>>(istream& in, string& s)//{//	s.clear();//	char ch;//	//	ch = in.get();//	//in >> ch;//	s.reserve(128);//	while (ch != ' ' && ch != '\n')//	{//		//		s += ch;//		ch = in.get();//		//in >> ch;//	}//	return in;//////////}void test1(){string str;str += 'a';str += 'b';str += "beijing";string::iterator it = str.begin();while (it != str.end()){cout << *it << " ";it++;}}void test2(){string str;str.push_back('a');str.push_back('a');str.push_back('b');str.push_back('a');str.push_back('a');string::iterator it = str.begin();while (it != str.end()){cout << *it << " ";it++;}cout << str[2];}void test3(){string str;str.append("stringbj");for (auto& e : str){cout << e << " ";}}void print_string(const string it){string::const_iterator res = it.begin();while (res != it.end()){cout << *res << " ";++res;}}void test4(){string str;str += "abc";str.append("stringbj");string::iterator it = str.begin();while (it != str.end()){cout << *it << " ";it++;}//str.insert(0, 'g');for (auto& e : str){cout << e << " ";}cout << endl;// str.earse(1,string::npos);*//* for (auto e : str){cout << e << " ";}*/// print_string(str);}void test5(){string str;str.push_back('a');str.push_back('a');str.push_back('b');str.resize(10);/* string::iterator it = str.begin();while (it != str.end()){cout << *it << " ";it++;}*/cout << str.c_str();}void test6(){string str;str.push_back('a');str.push_back('a');str.push_back('b');str.insert(2, "hello");cout << str.c_str();}void test7(){string str;str.push_back('a');str.push_back('a');str.push_back('b');str.insert(2, "hello");cout << endl;int ret = str.find('b', 0);cout << ret;}void test8(){string str;str += "beijing huanyingni zhangjiawang";int ret = str.find("zhangjiawang");cout << ret;}void test9(){string str;str += "beijing huanyingni zhangjiawang";string op = str.substr(0, 10);cout << op.c_str();}void test10(){string str1;string str2;str1 += "abc";str2 += "aba";cout << (str1 == str2) << endl;cout << ("aba" == str2) << endl;cout << (str2== "aba") << endl;cout << (str1>str2) << endl;cout << (str1 >=str2) << endl;cout << (str1<str2) << endl;cout << (str1 <=str2) << endl;cout << (str1!=str2) << endl;}void test11(){string str1;string str2;cin >> str1;//>>str2;//>>str2;//cout << str1;cout << str1.capacity();}void test12(){   string str1;string str2;str1 += "hello";str2+="nihao";cout << "str1:"<<str1 << endl;cout << "str2:"<<str2 << endl;str1.swap(str2);cout << "str1:" << str1 << endl;cout << "str2:" << str2 << endl;}void test13(){string str1;string str2;str1 += "hello";str2 += "nihao";cout << "str1:" << str1 << endl;cout << "str2:" << str2 << endl;swap(str1, str2);cout << "str1:" << str1 << endl;cout << "str2:" << str2 << endl;}void test14(){string str2;str2 += "nihao";string str1(str2);}}

.cpp

#include"标头.h"int main()
{zjw::test11();
}

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

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

相关文章

测试工具使用技巧01-->jmeter链接mysql

前言 在做接口或者性能测试的时候&#xff0c;有时需要jmeter连接数据库做操作&#xff0c;可以看看如下实例。操作实例 在mysql数据库中有如下数据表 在jmeter导入jdbc驱动插件&#xff08;需要的留言找我拿&#xff09; 在jmeter测试计划元件最下面&#xff0c;导入jdbc.…

Android平台实现无纸化同屏并推送RTMP或轻量级RTSP服务(毫秒级延迟)

技术背景 在写这篇文章之前&#xff0c;实际上几年之前&#xff0c;我们就有非常稳定的无纸化同屏的模块&#xff0c;本文借demo更新&#xff0c;算是做个新的总结&#xff0c;废话不多说&#xff0c;先看图&#xff0c;本文以Android平台屏幕实时采集推送&#xff0c;Windows…

ActiveRAG—主动学习

原文地址&#xff1a;ActiveRAG — Active Learning 2024 年 2 月 26 日 大型语言模型&#xff08;LLM&#xff09;的出现开创了对话式人工智能的新时代。这些模型可以生成非常类似人类的文本&#xff0c;并且比以往更好地进行对话。然而&#xff0c;他们仍然面临着仅仅依靠预先…

面试宝典-【redis】

目录 1.什么是缓存穿透 ? 怎么解决 ? 2.什么是布隆过滤器 3.什么是缓存击穿 ? 怎么解决 ? 4.什么是缓存雪崩 ? 怎么解决 ? 5.redis做为缓存&#xff0c;mysql数据如何与redis进行同步?(双写) 6.排他锁是如何保证读写、读读互斥的呢&#xff1f; 7.你听说过延…

C# LINQ运算符

LINQ运算符 1. 概述1.1 集合->集合1.1.1 筛选运算符1.1.2 映射运算符1.1.3 连接运算符1.1.4 排序运算符1.1.5 分组运算符1.1.6 集合运算符1.1.7 转换方法:Import1.1.8 转换方法:Export 1.2 集合->单个元素或标量值1.2.1 元素运算符1.2.2 聚合方法1.2.3 数量词 1.3 空->…

【MySQL 系列】MySQL 语句篇_DQL 语句

DQL&#xff08;Data Query Language&#xff09;&#xff0c;即数据查询语言&#xff0c;用来查询数据记录。DQL 基本结构由 SELECT FROM、WHERE、JOIN 等子句构成。 DQL 语句并不会改变数据库&#xff0c;而是让数据库将查询结果发送结果集给客户端&#xff0c;返回的结果是一…

软考72-上午题-【面向对象技术2-UML】-UML中的图3

一、状态图 1-1、状态图的定义 状态图&#xff0c;展现了一个状态机&#xff0c;由&#xff1a;状态、转换、事件和活动组成&#xff0c;是系统的动态视图。 活动(动作) 可以在状态内执行也可以在状态转换(迁移) 时执行。 状态图强调&#xff1a;行为的事件顺序。 1-2、状态图…

SpringBoot项目如何部署到服务器

文章目录 准备&#xff1a;方式一&#xff1a;Jar包方式&#xff08;推荐&#xff09;部署步骤&#xff1a; 方式二&#xff1a;War包方式部署步骤&#xff1a; 总结 准备&#xff1a; 云服务器&#xff08;阿里云、腾讯云等&#xff09;Linux系统以及运行所需的环境 方式一&a…

力扣--深度优先算法/回溯算法216.组合总和 Ⅲ

思路分析&#xff1a; 深度优先搜索 (DFS)&#xff1a; 通过递归实现&#xff0c;尝试从数字 1 到 9 中选择可能的数字&#xff0c;构建和为 n&#xff0c;长度为 k 的组合。递归函数 dfs&#xff1a; 接收参数&#xff1a;result 为最终结果集&#xff0c;path 为当前正在生成…

【C++】二叉树进阶之二叉搜索树

> 作者简介&#xff1a;დ旧言~&#xff0c;目前大二&#xff0c;现在学习Java&#xff0c;c&#xff0c;c&#xff0c;Python等 > 座右铭&#xff1a;松树千年终是朽&#xff0c;槿花一日自为荣。 > 目标&#xff1a;熟练掌握二叉搜索树&#xff0c;能自己模拟实现二…

类和对象-继承

师从黑马程序员 基本语法 有些类与类之间存在特殊的关系&#xff0c;例如&#xff1a; 定义这些类时&#xff0c;下一级别的成员除了拥有上一级的共性&#xff0c;还有自己的特性。 这时候我们就可以考虑继承技术&#xff0c;减少重复代码 语法&#xff1a;class 子类&…

加密流量分类torch实践4:TrafficClassificationPandemonium项目更新

加密流量分类torch实践4&#xff1a;TrafficClassificationPandemonium项目更新 更新日志 代码已经推送开源至露露云的github&#xff0c;如果能帮助你&#xff0c;就给鼠鼠点一个star吧&#xff01;&#xff01;&#xff01; 3/10号更新 流量预处理更新 增加了基于splitCa…

misc49

下载附件是个txt文件&#xff0c;打开发现是个压缩包的头 后缀改成zip后打开 base解码无果&#xff0c;我们尝试字母解码 然后音符解码得到 ❀✿✼❇❃❆❇✿❁❇✻✿❀✾✿✻❀❊❆❃❀❊✻❅❀❄✼❂❊❊✾❇❁✽✽✼❁❂❀❀❀❉❃❂❀❉❃❂❊❊✾✼✻✻❀❆✻✻❀❀✻✻✿…

round四舍五入在python2与python3版本间区别

round()方法返回数值的小数点四舍五入到n个数字。 语法 以下是round()方法的语法&#xff1a; round( x ,n) 参数 x --这是一个数值&#xff0c;表示需要格式化的数值 n --这也是一个数值,表示小数点后保留多少位 返回值 该方法返回 数值x 的小数点四舍五入到n个数字 …

使用css结合js实现html文件中的双行混排

此前写过一个使用flex布局实现html文件中的双行混排&#xff0c;但是感觉效果不佳。经过几天思考&#xff0c;我认为双行混排的要点其实是两个&#xff1a; 1、正文和批注的文字大小不同&#xff1b; 2、正文和批注的行距相互配合进行设定。 正文和批注的文字大小及行距都可…

OpenHarmony下musl编译工具链普法

OpenHarmony下musl编译工具链普法 引言 欠的债总是要还的&#xff0c;这不前面欠的关于OpenHarmony下musl相关的还是要还的。这里我对其中的相关知识点&#xff0c;梳理&#xff0c;归纳重新消化下&#xff01; 一.GCC/Clang/LLVM的区别与联系 说实话&#xff0c;这块我现在都…

当量化私募投资总监能学到什么?

我的情况更新 ​我是美国电子工程背景毕业的。在华尔街第一份实习是在E3做手工t0的proprietary trading&#xff0c;被刷下来之后就一直在帮顶级的对冲基金打杂当助理。所以当初决定回国一展身手&#xff0c;并且写下了破百万阅读的&#xff1a; 在私募做量化研究半年能学到什…

基于神经网络的偏微分方程求解器再度取得突破,北大字节的研究成果入选Nature子刊

目录 一.引言:神经网络与偏微分方程 二.如何基于神经网络求解偏微分方程 1.简要概述 2.基于神经网络求解偏微分方程的三大方向 2.1数据驱动 基于CNN 基于其他网络 2.2物理约束 PINN 基于 PINN 可测量标签数据 2.3物理驱动(纯物理约束) 全连接神经网路(FC-NN) CN…

保姆级讲解字符串函数(下篇)

目录 strtok的使用 strerror的使用 strstr的使用和函数模拟实现 strstr的使用 strstr函数模拟实现 接上篇&#xff1a;保姆级讲解字符串函数&#xff08;上篇&#xff09;&#xff0c;我们接着把剩下三个函数讲解完&#xff0c;继续跟着我的步伐一起学习呀. strtok的使用 …

从 Language Model 到 Chat Application:对话接口的设计与实现

作者&#xff1a;网隐 RTP-LLM 是阿里巴巴大模型预测团队开发的大模型推理加速引擎&#xff0c;作为一个高性能的大模型推理解决方案&#xff0c;它已被广泛应用于阿里内部。本文从对话接口的设计出发&#xff0c;介绍了业界常见方案&#xff0c;并分享了 RTP-LLM 团队在此场景…