C++简单缓冲区类设计

目录

1.引言

2.静态缓冲区

3.动态缓冲区

4.数据引用类

5.自动数据引用类

6.几种缓冲区的类关系图

7.注意事项

8.完整代码


1.引言

        在C++中,设计静态和动态缓冲区类时,需要考虑的主要差异在于内存管理的方式。静态缓冲区类通常使用固定大小的内存区域(即栈分配或静态分配),而动态缓冲区类则根据需要动态地分配和释放内存(即堆分配)。下面将分别展示这几种缓冲区类的基本设计思路。

        不管是静态缓冲区还是动态缓冲区,都有统一的访问接口,于是提取共用方法,组成基础类:

template <class T>
class CSimpleDataBufferBase : public CNoncopyable
{
public:typedef T  DataType;typedef T* DataTypePointer;typedef T& DataTypeReference;typedef const T ConstDataType;typedef const T* ConstDataTypePointer;typedef const T& ConstDataTypeReference;public:CSimpleDataBufferBase() {}virtual ~CSimpleDataBufferBase() {}public:virtual  DWORD GetSize() const = 0;virtual  DataTypePointer GetData() = 0;virtual  ConstDataTypePointer GetData() const = 0;virtual  DWORD GetMaxSize() const = 0;operator DataTypePointer() {  return GetData(); } DataTypeReference operator*() { return *GetData(); }DataTypeReference operator[](int nIndex);virtual  BOOL  SetData(ConstDataTypePointer pData, DWORD dwSize) = 0;virtual  void  Clear() = 0;
};

接口设计要点:

1)CSimpleDataBufferBase继承CNoncopyable,禁止构造拷贝和赋值拷贝。

2)访问缓冲区数据的接口,const和非const版本。

3)重载操作符*或[]访问缓冲区元素的数据

template <class T>
typename CSimpleDataBufferBase<T>::DataTypeReference CSimpleDataBufferBase<T>::operator[](int nIndex)
{if ( (nIndex >= 0) && (nIndex < (int)GetSize())){DataTypePointer pData = GetData();return pData[nIndex];}else{throw std::out_of_range("invalid data<nIndex> position");}	
}

4)往缓冲区写数据接口,接收的是const T*和数据的长度。

5)获取缓冲区的上限。

5)清空缓冲区。

2.静态缓冲区

        静态缓冲区类通常包含一个固定大小的数组(或其他容器,但数组是最直接的例子),并提供一系列方法来操作这个数组。 静态缓冲区类CStaticSimpleDataBufferT实现代码如下:

//数据静态分配
template <class T>
class CStaticSimpleDataBufferT : public CSimpleDataBufferBase<T>
{
public:CStaticSimpleDataBufferT(DWORD dwMaxSize = MAX_STATIC_SIMPLE_BUFFER_SIZE);virtual ~CStaticSimpleDataBufferT() {  }public:DWORD GetSize() const { return m_dwDataLen; }DataTypePointer GetData() { return m_sData ;}ConstDataTypePointer GetData() const { return m_sData ;}BOOL  SetData(ConstDataTypePointer pData, DWORD dwSize);DWORD GetMaxSize() const {  return m_dwMaxDataSize; }void  Clear() { m_dwDataLen = 0; }private:DataType m_sData[MAX_STATIC_SIMPLE_BUFFER_SIZE];DWORD   m_dwDataLen;const DWORD m_dwMaxDataSize;		
};

        从实现的代码看,静态缓冲区就是在内存中事先分配好一段空间,这种分配一般是在栈中进行,分配速度特别快,但是不灵活,不能按照用户的大小需求分配空间。

3.动态缓冲区

        动态缓冲区类通常基于动态内存分配(如newdelete)来满足用户的需求。静态缓冲区的大小在编译时确定,而动态缓冲区的大小则根据需要动态变化。静态缓冲区适用于那些大小已知且不会改变的场景,而动态缓冲区则更灵活,适用于大小可能变化的场景。动态缓冲区类CDynamicSimpleDataBufferT实现代码如下:

//CSimpleDataBufferBase的默认适配器
template <class T>
class  CSimpleDataBufferAdapter : public CSimpleDataBufferBase<T>
{
public:CSimpleDataBufferAdapter() : m_pData(NULL),m_dwDataLen(0) { }virtual ~CSimpleDataBufferAdapter() { }public:DWORD GetSize() const { return m_dwDataLen; }BOOL  SetData(ConstDataTypePointer pData, DWORD dwSize) {  assert(0); return FALSE; }void  SetSize(DWORD dwSize) { m_dwDataLen = dwSize; }DWORD GetMaxSize() const {  assert(0); return 0; }void  Clear() {  assert(0); }DataTypePointer GetData() { return m_pData ;}ConstDataTypePointer GetData() const { return m_pData ;}protected:DataTypePointer  m_pData;DWORD   m_dwDataLen;	
};/动态缓冲区
template <class T>
class  CDynamicSimpleDataBufferT : public CSimpleDataBufferAdapter<T>
{
public:CDynamicSimpleDataBufferT(DWORD dwMaxSize = MAX_DYNAMIC_SIMPLE_BUFFER_SIZE);virtual ~CDynamicSimpleDataBufferT() { ClearData(); }public:void  Clear() {  m_dwDataLen = 0; }DWORD GetMaxSize() const { return m_dwMaxDataSize; }BOOL  SetData(ConstDataTypePointer pData, DWORD dwSize);protected:void  ClearData();private:const DWORD m_dwMaxDataSize;
};

构造函数、析构函数、赋值函数实现如下:

//构造函数
template <class T>
CDynamicSimpleDataBufferT<T>::CDynamicSimpleDataBufferT(DWORD dwMaxSize)
: m_dwMaxDataSize(dwMaxSize)
{m_pData = new T[dwMaxSize];if (m_pData == NULL)throw std::	bad_alloc("new T Array Failed");m_dwDataLen = 0;assert(m_pData != NULL);assert(m_dwDataLen >= 0);
}//清空数据函数
template <class T>
void  CDynamicSimpleDataBufferT<T>::ClearData()
{if (m_pData)delete []m_pData;m_pData = NULL;m_dwDataLen = 0;
}//赋值函数
template <class T>
BOOL CDynamicSimpleDataBufferT<T>::SetData(ConstDataTypePointer pData, DWORD dwSize)
{int  i;if (dwSize > m_dwMaxDataSize)return FALSE;for (i = 0; i < (int)dwSize; i++)m_pData[i] = pData[i];m_dwDataLen = dwSize;return TRUE;
}

        析构函数自动调用了Clear函数,释放了内存,这样就不怕退出的时候出现内存泄漏。

4.数据引用类

        在前面讲解的静态缓冲区和动态缓冲区内部都需要开辟空间,而数据引用类不需要开辟空间;CRefSimpleDataBufferT的具体实现如下:

template <class T>
class  CRefSimpleDataBufferT : public CSimpleDataBufferAdapter<T>
{
public:CRefSimpleDataBufferT() { }CRefSimpleDataBufferT(ConstDataTypePointer pBuffer, DWORD dwSize);virtual ~CRefSimpleDataBufferT()  {  }public:BOOL  SetData(ConstDataTypePointer pBuffer, DWORD dwSize);void  Clear();
};template <class T>
CRefSimpleDataBufferT<T>::CRefSimpleDataBufferT(ConstDataTypePointer pBuffer, DWORD dwSize)
{m_pData = const_cast<DataTypePointer>(pBuffer);m_dwDataLen = dwSize;
}template <class T>
void CRefSimpleDataBufferT<T>::Clear()
{if (m_pData)delete []m_pData;m_pData = NULL;m_dwDataLen = 0;
}template <class T>
BOOL  CRefSimpleDataBufferT<T>::SetData(typename CRefSimpleDataBufferT<T>::ConstDataTypePointer pBuffer, DWORD dwSize)
{Clear();m_pData = const_cast<DataTypePointer>(pBuffer);m_dwDataLen = dwSize;return TRUE;
}

从实现的代码来看,如果引用的数据是动态分配的,就可以调用Clear函数释放内存,反之,则不需要调用。

5.自动数据引用类

自动数据引用类就是引用外部的动态分配的数据源,并自动释放这个数据源的内存。CAutoRefSimpleDataBufferT的实现代码如下:

//自动释放动态分配的数据引用类
template <class T>
class  CAutoRefSimpleDataBufferT : public CRefSimpleDataBufferT<T>
{	
public:CAutoRefSimpleDataBufferT() { }CAutoRefSimpleDataBufferT(ConstDataTypePointer pBuffer, DWORD dwSize);CAutoRefSimpleDataBufferT(ConstDataTypePointer pBuffer);void  Clear();DataTypePointer   operator->() { return GetData(); }ConstDataTypePointer   operator->() const  { return GetData(); }virtual ~CAutoRefSimpleDataBufferT();
};template <class T>
CAutoRefSimpleDataBufferT<T>::CAutoRefSimpleDataBufferT(typename CAutoRefSimpleDataBufferT<T>::ConstDataTypePointer pBuffer, DWORD dwSize)
: CRefSimpleDataBufferT<T>(pBuffer, dwSize)
{
}template <class T>
CAutoRefSimpleDataBufferT<T>::CAutoRefSimpleDataBufferT(typename CAutoRefSimpleDataBufferT<T>::ConstDataTypePointer pBuffer)
: CRefSimpleDataBufferT<T>(pBuffer, 1)
{
}template <class T>
void CAutoRefSimpleDataBufferT<T>::Clear()
{if (1 == m_dwDataLen)delete m_pData;elseCRefSimpleDataBufferT<T>::Clear();
}template <class T>
CAutoRefSimpleDataBufferT<T>::~CAutoRefSimpleDataBufferT()
{Clear();
}

CAutoRefSimpleDataBufferT和CRefSimpleDataBufferT的不同点就在于析构函数自动调用了Clear函数,释放了数据源的内存。

6.几种缓冲区的类关系图

7.注意事项

1)静态成员变量的初始化:静态成员变量需要在类外进行初始化,并且只能初始化一次。

2)线程安全:如果多个线程可能同时访问这个静态缓冲区,你需要实现适当的同步机制来避免数据竞争和不一致。

3)资源管理:静态缓冲区在程序结束时自动销毁,但如果你在其中存储了动态分配的资源(如指针指向的堆内存),你需要确保在程序结束前正确释放这些资源。

4)性能考虑:静态缓冲区大小固定,如果缓冲区大小设置不当,可能会导致频繁的内存溢出或内存浪费。

5)并发访问:在并发环境中,如果多个线程可能同时写入或读取缓冲区,需要考虑使用互斥锁(如std::mutex)来同步访问。

8.完整代码

Noncopyable.h

/*************************************************************************// 功能: 防止拷贝类// 备注: *************************************************************************/
#pragma onceclass  CNoncopyable
{
public:CNoncopyable() {}~CNoncopyable() {}protected:CNoncopyable(const CNoncopyable& src);  //拷贝构造函数const CNoncopyable& operator=(const CNoncopyable& src); //赋值函数
};

SimpleDataBuffer.h

#pragma once
#include "Noncopyable.h"
#include <assert.h>
#include <new>
#include <stdexcept>
using namespace std;#define  MAX_STATIC_SIMPLE_BUFFER_SIZE  	  (4*1024)  //4K
#define  MAX_DYNAMIC_SIMPLE_BUFFER_SIZE       (800*1024) //800Ktemplate <class T>
class CSimpleDataBufferBase : public CNoncopyable
{
public:typedef T  DataType;typedef T* DataTypePointer;typedef T& DataTypeReference;typedef const T ConstDataType;typedef const T* ConstDataTypePointer;typedef const T& ConstDataTypeReference;public:CSimpleDataBufferBase() {}virtual ~CSimpleDataBufferBase() {}public:virtual  DWORD GetSize() const = 0;virtual  DataTypePointer GetData() = 0;virtual  ConstDataTypePointer GetData() const = 0;virtual  DWORD GetMaxSize() const = 0;operator DataTypePointer() {  return GetData(); } DataTypeReference operator*() { return *GetData(); }DataTypeReference operator[](int nIndex);virtual  BOOL  SetData(ConstDataTypePointer pData, DWORD dwSize) = 0;virtual  void  SetSize(DWORD dwSize) = 0;virtual  void  Clear() = 0;
};template <class T>
typename CSimpleDataBufferBase<T>::DataTypeReference CSimpleDataBufferBase<T>::operator[](int nIndex)
{if ( (nIndex >= 0) && (nIndex < (int)GetSize())){DataTypePointer pData = GetData();return pData[nIndex];}else{throw std::out_of_range("invalid data<nIndex> position");}	
}//数据静态分配
template <class T>
class CStaticSimpleDataBufferT : public CSimpleDataBufferBase<T>
{
public:CStaticSimpleDataBufferT(DWORD dwMaxSize = MAX_STATIC_SIMPLE_BUFFER_SIZE);virtual ~CStaticSimpleDataBufferT() {  }public:DWORD GetSize() const { return m_dwDataLen; }DataTypePointer GetData() { return m_sData ;}ConstDataTypePointer GetData() const { return m_sData ;}BOOL  SetData(ConstDataTypePointer pData, DWORD dwSize);void  SetSize(DWORD dwSize) { m_dwDataLen = dwSize; }DWORD GetMaxSize() const {  return m_dwMaxDataSize; }void  Clear() { m_dwDataLen = 0; }private:DataType m_sData[MAX_STATIC_SIMPLE_BUFFER_SIZE];DWORD   m_dwDataLen;const DWORD m_dwMaxDataSize;		
};template <class T>
CStaticSimpleDataBufferT<T>::CStaticSimpleDataBufferT(DWORD dwMaxSize)
:  m_dwDataLen(0),m_dwMaxDataSize(dwMaxSize)
{
}template <class T>
BOOL  CStaticSimpleDataBufferT<T>::SetData(ConstDataTypePointer pData, DWORD dwSize)
{int  i;if (dwSize > m_dwMaxDataSize)return FALSE;for (i = 0; i < (int)dwSize; i++)m_sData[i] = pData[i];m_dwDataLen = dwSize;return TRUE;
}
///
template <class T>
class  CSimpleDataBufferAdapter : public CSimpleDataBufferBase<T>
{
public:CSimpleDataBufferAdapter() : m_pData(NULL),m_dwDataLen(0) { }virtual ~CSimpleDataBufferAdapter() { }public:DWORD GetSize() const { return m_dwDataLen; }BOOL  SetData(ConstDataTypePointer pData, DWORD dwSize) {  assert(0); return FALSE; }void  SetSize(DWORD dwSize) { m_dwDataLen = dwSize; }DWORD GetMaxSize() const {  assert(0); return 0; }void  Clear() {  assert(0); }DataTypePointer GetData() { return m_pData ;}ConstDataTypePointer GetData() const { return m_pData ;}protected:DataTypePointer  m_pData;DWORD   m_dwDataLen;	
};/
template <class T>
class  CDynamicSimpleDataBufferT : public CSimpleDataBufferAdapter<T>
{
public:CDynamicSimpleDataBufferT(DWORD dwMaxSize = MAX_DYNAMIC_SIMPLE_BUFFER_SIZE);virtual ~CDynamicSimpleDataBufferT() { ClearData(); }public:void  Clear() {  m_dwDataLen = 0; }DWORD GetMaxSize() const { return m_dwMaxDataSize; }BOOL  SetData(ConstDataTypePointer pData, DWORD dwSize);protected:void  ClearData();private:const DWORD m_dwMaxDataSize;
};template <class T>
CDynamicSimpleDataBufferT<T>::CDynamicSimpleDataBufferT(DWORD dwMaxSize)
: m_dwMaxDataSize(dwMaxSize)
{m_pData = new T[dwMaxSize];if (m_pData == NULL)throw std::	bad_alloc("new T Array Failed");m_dwDataLen = 0;assert(m_pData != NULL);assert(m_dwDataLen >= 0);
}template <class T>
void  CDynamicSimpleDataBufferT<T>::ClearData()
{if (m_pData)delete []m_pData;m_pData = NULL;m_dwDataLen = 0;
}template <class T>
BOOL CDynamicSimpleDataBufferT<T>::SetData(ConstDataTypePointer pData, DWORD dwSize)
{int  i;if (dwSize > m_dwMaxDataSize)return FALSE;for (i = 0; i < (int)dwSize; i++)m_pData[i] = pData[i];m_dwDataLen = dwSize;return TRUE;
}
//
template <class T>
class  CRefSimpleDataBufferT : public CSimpleDataBufferAdapter<T>
{
public:CRefSimpleDataBufferT() { }CRefSimpleDataBufferT(ConstDataTypePointer pBuffer, DWORD dwSize);virtual ~CRefSimpleDataBufferT()  {  }public:BOOL  SetData(ConstDataTypePointer pBuffer, DWORD dwSize);void  Clear();
};template <class T>
CRefSimpleDataBufferT<T>::CRefSimpleDataBufferT(ConstDataTypePointer pBuffer, DWORD dwSize)
{m_pData = const_cast<DataTypePointer>(pBuffer);m_dwDataLen = dwSize;
}template <class T>
void CRefSimpleDataBufferT<T>::Clear()
{if (m_pData)delete []m_pData;m_pData = NULL;m_dwDataLen = 0;
}template <class T>
BOOL  CRefSimpleDataBufferT<T>::SetData(typename CRefSimpleDataBufferT<T>::ConstDataTypePointer pBuffer, DWORD dwSize)
{Clear();m_pData = const_cast<DataTypePointer>(pBuffer);m_dwDataLen = dwSize;return TRUE;
}//自动释放动态分配的数据引用类
template <class T>
class  CAutoRefSimpleDataBufferT : public CRefSimpleDataBufferT<T>
{	
public:CAutoRefSimpleDataBufferT() { }CAutoRefSimpleDataBufferT(ConstDataTypePointer pBuffer, DWORD dwSize);CAutoRefSimpleDataBufferT(ConstDataTypePointer pBuffer);void  Clear();DataTypePointer   operator->() { return GetData(); }ConstDataTypePointer   operator->() const  { return GetData(); }virtual ~CAutoRefSimpleDataBufferT();
};template <class T>
CAutoRefSimpleDataBufferT<T>::CAutoRefSimpleDataBufferT(typename CAutoRefSimpleDataBufferT<T>::ConstDataTypePointer pBuffer, DWORD dwSize)
: CRefSimpleDataBufferT<T>(pBuffer, dwSize)
{
}template <class T>
CAutoRefSimpleDataBufferT<T>::CAutoRefSimpleDataBufferT(typename CAutoRefSimpleDataBufferT<T>::ConstDataTypePointer pBuffer)
: CRefSimpleDataBufferT<T>(pBuffer, 1)
{
}template <class T>
void CAutoRefSimpleDataBufferT<T>::Clear()
{if (1 == m_dwDataLen)delete m_pData;elseCRefSimpleDataBufferT<T>::Clear();
}template <class T>
CAutoRefSimpleDataBufferT<T>::~CAutoRefSimpleDataBufferT()
{Clear();
}

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

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

相关文章

JAVA使用Scanner类的nextLint()方法无法正确读取中文。

在练习的时候&#xff0c;我发现我使用Scanner类的nextLint&#xff08;&#xff09;方法无法正确读取到中文了。检查了我的idea编辑器&#xff0c;用的编码格式也是”utf-8“。所以编码格式没有问题。 问题如下棉两张图所示&#xff0c;我输入宝马后&#xff0c;控制台不打印…

外包干了2年,收获不少。。。

有一种打工人的羡慕&#xff0c;叫做“大厂”。 真是年少不知大厂香&#xff0c;错把青春插稻秧。 但是&#xff0c;在深圳有一群比大厂员工更庞大的群体&#xff0c;他们顶着大厂的“名”&#xff0c;做着大厂的工作&#xff0c;还可以享受大厂的伙食&#xff0c;却没有大厂…

STM32F407单片机编程入门(二十七)以太网接口详解及实战含源码

文章目录 一.概要二.单片机以太网系统基本结构1.OSI 七层模型2.单片机实现以太网功能组成 三.STM32F407VET6单片机以太网内部结构1.MII接口介绍2.RMII接口介绍 四.LWIP TCP/IP协议栈介绍五.PHY收发器LAN8720介绍1.LAN8720内部框图2.LAN8720应用电路3.LAN8720以太网模块 六.Cube…

测试的底层逻辑

写这篇文章&#xff0c;是希望把我的一些我认为是非常有价值的经验总结出来&#xff0c;能够帮助刚做测试不久的新同事&#xff0c;或者是测试经验丰富的老同事以共享。希望我们可爱的新同事&#xff0c;准备要在测试领域耕耘的伙伴&#xff0c;能够通过我的文章了解到测试的底…

【智慧城市】新中地GIS开发实训项目:华农优秀学生学习成果展示(3)智游江城

华农GIS开发实训项目答辩③-智游江城/一个月学习成果展示 项目名称&#xff1a;智游江城 项目功能 主页面展示 菜单功能 控制台 3D城市 查询 导航 游览路线推荐 测量 资讯

Node的安装和配置

1、安装Node 下载nodejs 链接&#xff1a;下载 | Node.js 中文网 官网下载最新版本&#xff1a;https://nodejs.org/en/download/ 一路点击Next&#xff0c;最后Finish。nodejs一般会下载在C盘里。 下载完成后&#xff0c;可以在cmd中查看安装的nodejs和npm版本&#xff0c;…

【C++】红黑树的封装——同时实现map和set

目录 红黑树的完善默认成员函数迭代器的增加 红黑树的封装红黑树模板参数的控制仿函数解决取K问题对Key的非法操作 insert的调整map的[]运算符重载 在list模拟实现一文中&#xff0c;介绍了如何使用同一份代码封装出list的普通迭代器和const迭代器。今天学习STL中两个关联式容器…

lime使用记录

主要是对预测结果进行可解释 import numpy as np import pandas as pd from sklearn.datasets import load_iris from sklearn.model_selection import train_test_split from sklearn.ensemble import RandomForestClassifier from sklearn.metrics import classification_re…

thinkphp6调用微信商户支付-合单支付工具代码开发

合单支付基本在加盟店或是分公司或是营销系统里面常见。他的出现&#xff0c;打破了传统提现支付或是转账支付。他的业务原理其实很简单&#xff0c;就是需要优先申请非普通商户&#xff0c;其次是每个入驻的商户都需要申请普通商户。在这之前一定要申请好对应的场景服务&#…

大学学校用电安全远程监测预警系统

1.概述&#xff1a; 该系统是基于移动互联网、云计算技术&#xff0c;通过物联网传感终端&#xff0c;将办公建筑、学校、医院、工厂、体育场馆、宾馆、福利院等人员密集场所的电气安全数据&#xff0c;实时传输至安全用申管理服务器&#xff0c;为用户提供不间断的数据跟踪&a…

2024年项目经理不能错过的开源项目管理系统大盘点:全面指南

在2024年&#xff0c;随着项目管理领域的不断发展&#xff0c;开源项目管理系统成为了项目经理们提升工作效率的利器。本文将全面盘点几款备受推荐的开源项目管理系统&#xff0c;帮助项目经理们找到最佳选择&#xff0c;不容错过。 在项目管理日益复杂的今天&#xff0c;开源项…

鼎阳加油-IOC关键技术问题的解决记

鼎阳SDS6204示波器EPICS IOC的搭建-CSDN博客 这款示波器在labview下工作的很好&#xff0c;以前搭建逐束团3D系统时连续几个月不间断的工作连接从没断过线&#xff0c;并做过速率测试&#xff0c;单通道时10Hz的波形更新速率都可以达到&#xff1a; 鼎阳SDS6204示波器波形读取…

温州大麓青年音乐节即将开唱,37组音乐人国庆齐聚共谱华章

金秋十月&#xff0c;当丰收的季节与音乐的旋律相遇&#xff0c;温州将迎来一场前所未有的文化盛事。2024年10月1日至4日&#xff0c;温州大麓青年音乐节将在瓯海盛大举行。不仅是一场音乐的狂欢&#xff0c;更是一次多元文化的碰撞与融合。本届音乐节邀请了37组以上的知名音乐…

中级职称评审到底需要准备什么材料?

职称评审需要的材料非常非常多&#xff0c;其中涉及到各类表格&#xff0c;这些小资料&#xff0c;看起来简单&#xff0c;实则做起来复杂&#xff0c;不过这种资料只能当年通知出来之后进行整理&#xff0c;今天甘建二跟大家说一下职称评审中需要提前准备的一些重要材料&#…

酒店智能门锁SDK接口通用转换函数对接酒店收银-SAAS本地化-未来之窗行业应用跨平台架构

一、通用转换代码 public class CyberWin_LocakAPP{// public static byte[] bufCard new byte[128 1];public static string 未来之窗_美萍_getsign(byte[] bufCard){int i;string 酒店标识, s, s2;// 先读卡string 未来之窗 Encoding.ASCII.GetString(bufCard);// edt_Ca…

使用dayjs获取今天日期,星期几

<div>{{ curDate }} {{ getWeek() }}</div>import dayjs from dayjs;data(){return{curDate: dayjs(new Date()).format(YYYY年MM月DD日)} }, mounted() {this.getWeek(); }, methods: {// 获取今天星期几getWeek() {let datas dayjs().day();let week [日, 一, …

Linux 搭建与使用yolov5训练和检验自建模型的步骤

Linux 搭建与使用yolov5训练和检验自建模型的步骤 硬件设备 环境搭建(无cuda) 下载anaconda wget https://repo.anaconda.com/archive/Anaconda3-2024.06-1-Linux-x86_64.sh bash Anaconda3-2024.06-1-Linux-x86_64.sh # 看完许可证后, yes, 后面选择安装路径, 可以按默认路…

打造高效合同管理平台,提升企业运营效率

在现代企业的日常运营中&#xff0c;合同管理扮演着至关重要的角色。无论是劳动协议、采购订单还是销售合同&#xff0c;各类合同都承载着企业的重要信息和业务节点。然而&#xff0c;面对日益复杂的商业环境和海量合同数据&#xff0c;如何有效管理和利用这些合同成为众多企业…

一些写论文必须要知道的神仙级网站!芝士AI(paperzz)

说实话&#xff0c;写论文真的是挺头疼&#xff0c;尤其到了毕业季的时候&#xff0c;没有过任何写作毕业论文的经验的毕业生而言更是如此&#xff0c;相信大家都有过这种状态&#xff0c;不知从何下笔&#xff0c;还需要面对论文进度的压力&#xff0c;并且时常需要寻找各种资…

基于Python大数据可视化的短视频推荐系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码 精品专栏&#xff1a;Java精选实战项目…