_Array类,类似于Vector,其实就是_string

devtools/2024/9/19 21:17:37/ 标签: 算法, c++, 数据结构

例子:

using namespace lf;
using namespace std;int main() {_Array<int> a(10, -1);_Array<_string> s = { _t("one"), _t("two") };_pcn(a);_pcn(s);}

结果:

源代码_Array.h:

/*******************************************************************************************
文件名						: _Array.h作者							: 李锋功能							: 线性表创建时间						: 2016年07月16日最后一次修改时间				:  2024年09月15日
********************************************************************************************/
#ifndef __ARRAY_H_  
#define __ARRAY_H_#include "_StrW.h"
#include "_StrA.h"
#include "_Convert.h"
#include "_Object.h"_LF_BEGIN_/**********************************************************************************************************
1
vector与list区别
vector为存储的对象分配一块连续的地址空间,因此对vector中的元素随机访问效率很高。在vecotor中插入或者
删除某个元素,需要将现有元素进行复制,移动。如果vector中存储的对象很大,或者构造函数复杂,则在对现
有元素进行拷贝时开销较大,因为拷贝对象要调用拷贝构造函数。对于简单的小对象,vector的效率优于list。
vector在每次扩张容量的时候,将容量扩展2倍,这样对于小对象来说,效率是很高的。list中的对象是离散存储的,
随机访问某个元素需要遍历list。在list中插入元素,尤其是在首尾插入元素,效率很高,只需要改变元素的指针。综上所述:
vector适用:对象数量变化少,简单对象,随机访问元素频繁
list适用:对象数量变化大,对象复杂,插入和删除频繁
最大的区别是, list是双向的,而vector是单向的。
因此在实际使用时,如何选择这三个容器中哪一个,应根据你的需要而定,一般应遵循下面
的原则:
1、如果你需要高效的随即存取,而不在乎插入和删除的效率,使用vector
2、如果你需要大量的插入和删除,而不关心随即存取,则应使用list
3、如果你需要随即存取,而且关心两端数据的插入和删除,则应使用deque。vector表示一段连续的内存区域,每个元素被顺序存储在这段内存中,对vector   的随机访问效率很高,但对非末尾元素的插入和删除则效率非常低。deque也表示一段连续的内存区域,但与vector不同的是它支持高效地在其首部插入和删除元素,它通过两级数组结构来实现,一级表示实际的容器,第二级指向容器的首和尾list表示非连续的内存区域并通过一对指向首尾元素的指针双向链接起来,插入删除效率高,随机访问效率低2stl提供了三个最基本的容器:vector, list, deque。vector和built - in数组类似,它拥有一段连续的内存空间,并且起始地址不变,因此
它能非常好的支持随即存取,即[]操作符,但由于它的内存空间是连续的,所以在中间
进行插入和删除会造成内存块的拷贝,另外,当该数组后的内存空间不够时,需要重新
申请一块足够大的内存并进行内存的拷贝。这些都大大影响了vector的效率。list就是数据结构中的双向链表(根据sgi   stl源代码),因此它的内存空间可以是不连续
的,通过指针来进行数据的访问,这个特点使得它的随即存取变的非常没有效率,因此它
没有提供[]操作符的重载。但由于链表的特点,它可以以很好的效率支持任意地方的删除
和插入。deque是一个double - ended   queue,它的具体实现不太清楚,但知道它具有以下两个
特点:它支持[]操作符,也就是支持随即存取,并且和vector的效率相差无几,它支持在两端
的操作:push_back, push_front, pop_back, pop_front等,并且在两端操作上与list的效率
也差不多。因此在实际使用时,如何选择这三个容器中哪一个,应根据你的需要而定,一般应遵循下面
的原则:
1、如果你需要高效的随即存取,而不在乎插入和删除的效率,使用vector
2、如果你需要大量的插入和删除,而不关心随即存取,则应使用list
3、如果你需要随即存取,而且关心两端数据的插入和删除,则应使用deque。**********************************************************************************************************线性表的定义:一个线性表是n(n>=0)个具有相同属性的数据元素的有限序列。其中各元系有着依次相邻的逻辑关系。线性表中数据元素个数n称为线性表的长度。n=0时该线性表称为空表。**************************************************************************************************************/
//#define _ARRAY_DEBUG_/// <summary>
/// 
/// </summary>
/// <typeparam name="T"></typeparam>
template<class T>
class _ArrayIterator
{
private:T* _Ptr;
public:/// <summary>/// 构造函数,传值迭代器管理的值/// </summary>/// <param name="pNode"></param>inline _ArrayIterator(T* pt) { _Ptr = pt; }/// <summary>/// 比较实现/// </summary>/// <param name="that"></param>/// <returns></returns>bool operator != (const _ArrayIterator& that) { return _Ptr != that._Ptr; }/// <summary>/// 自增实现/// </summary>/// <returns></returns>inline _ArrayIterator& operator ++ () { ++_Ptr;   return *this; }/// <summary>/// 解引用,取值/// </summary>/// <typeparam name="T"></typeparam>T& operator * () { return *_Ptr; }};//_Array相当于std::vector,不限于线性表。
template<typename T>
class _Array : public _Object
{
public:
/*using traits_type    = _Traits;using allocator_type = _Alloc;using value_type      = _Elem;using size_type       = typename _Alty_traits::size_type;using difference_type = typename _Alty_traits::difference_type;using pointer         = typename _Alty_traits::pointer;using const_pointer   = typename _Alty_traits::const_pointer;using reference       = value_type&;using const_reference = const value_type&;using iterator       = _String_iterator<_Scary_val>;using const_iterator = _String_const_iterator<_Scary_val>;using reverse_iterator       = _STD reverse_iterator<iterator>;using const_reverse_iterator = _STD reverse_iterator<const_iterator>;
*/using iterator		=	_ArrayIterator<T>;using value_type	=	T;protected:T*			_pData;						//指针,指向第一个元素size_t		_nElementCount;				//无素个数size_t		_nBufferCount;				//缓冲元素个数size_t		_nDefaultBufferCount = 8;	//缺省缓冲数量size_t		_nAutoBufferCount = 0;		//自动设置缓冲次数的计数器public:static const int npos = -1;//-----------------------------------------------------------------------------------------------------------构造与析构函数
public: /// <summary>/// vector<int> ivec(10,-1);  //10个int元素,每个都初始化为-1/// </summary>/// <param name="nElementCount">元素数量</param>/// <param name="tDefaultValue">默认值</param>/// 创建时间:????-??-??    最后一次修改时间:2024-09-15 inline explicit _Array(const size_t& nElementCount = 0, const T& tDefaultValue = T()){/*构造函数中不能调用虚函数指的是直接或者隐式使用 this指针调用虚函数由于,不能确定this指针所代表的对象,包括其中指向虚函数表的指针,有没有构造完成,即包括指向虚函数表的指针在内的所有成员有没有,完全构造完成,所以难以正常使用虚函数。更重要的就是一些指针,还没有构造的时候,就用到了--这是野指针--,结果不确定!!!比如有一个 char指针,起到类似 string 的作用,只是需要动态分配内存,没有分配内存时,就是个野指针,一旦 使用的虚函数,使用了这个指针,后果就很严重。更严重的问题是,基类对子类的虚函数,如何使用完全没有谱,因为子类还没有定义。而且没有任何标志,表示虚函数表指针构造完成。虚函数没法调用。有标志也不行,子类会更改,虚函数表指针;虚函数表指针,会随着父类->子类;逐层构造,逐渐更改。PS:关于2.构造函数中调用结果运行行为正常,即已具有正常多态行为(因为在进入构造函数函数体之前,构造对象的虚函数表,对象中虚函数表指针,对象成员都已初始化完成,已是完整的派生类对象)。这个说法有问题,父类正在构造时候,子类对象,并没有开始构造,父类对象构造完成后,才会开始子类的构造,这时才会把虚函数表的指针,改成子类的虚函数表指针,这是单继承。多继承更复杂。*/#ifdef _ARRAY_DEBUG__cout << _t("inline explicit _Array(const size_t& nElementCount, const T& tDefaultValue = T())\n");#endifInitData(nElementCount,0,tDefaultValue,true,false);  //子类的InitData虚函数还未构造}/// <summary>/// 拷贝nCount个T数据到数组,默认还有8个T数据缓冲被初始化为零。/// </summary>/// <param name="pType">数据类型指针</param>/// <param name="nCount">数据个数</param>/// <param name="nDefaultBuffer">默认缓冲个数</param>/// <param name="bZeroBuffer">是否初始化缓冲为0</param>/// 创建时间:????-??-??    最后一次修改时间:2024-09-05 inline explicit _Array(const T* pType, const int nCount, const int nDefaultBuffer = 8, bool bZeroBuffer = true){
#ifdef _ARRAY_DEBUG__cout << _t("调用构造函数:_Array<T>::_Array(const T* pType, const int nCount, const int nDefaultBuffer = 8), 参数:") << _geti(nCount) << _geti(nDefaultBuffer) << _t("\n");
#endif_nDefaultBufferCount = nDefaultBuffer;InitData(0,nCount + _nDefaultBufferCount);Add(pType, nCount);if (bZeroBuffer)ZeroBufferAll();}inline _Array(const _Array& rhs){
#ifdef _ARRAY_DEBUG__cout << _t("调用构造函数: _Array<T>::_Array(const _Array& rhs)\n");
#endifif (&rhs == this || rhs._nElementCount == 0) {InitData(0);return;}_nDefaultBufferCount = rhs._nDefaultBufferCount;_nBufferCount = rhs._nBufferCount;_nElementCount = rhs._nElementCount;_pData = _Memory::New<T>(_nElementCount + _nBufferCount);_Memory::Copy(_pData, rhs._pData, _nElementCount);}/*C++11中新特性之:initializer_list详解C++11提供的新类型,定义在<initializer_list>头文件中。template< class T >class initializer_list;先说它的用处吧,然后再详细介绍一下。首先有了initializer_list之后,对于STL的container的初始化就方便多了,比如以前初始化一个vector需要这样:int a[] = {0, 1, 2, 3};std::vector<int> vec(a, a+sizeof(a));或者std::vector<int> vec;vec.push_back(1);vec.push_back(3);vec.push_back(3);vec.push_back(2);有了initializer_list后,就可以直接像初始化数组一样:复制代码class Test {private:static std::map<string, string> const nameToBirthday = {{"lisi", "18841011"},{"zhangsan", "18850123"},{"wangwu", "18870908"},{"zhaoliu", "18810316"},};}复制代码当然啦,里面的std::map必须提供参数为initializer_list的构造函数如:*/inline _Array(std::initializer_list<T> aList){InitData(0,aList.size() + _nDefaultBufferCount);Add(aList.begin(), aList.size());}/// <summary>/// /// </summary>/// <param name="v"></param>/// 创建时间:2024-07-01    最后一次修改时间:2024-07-01inline _Array(const std::vector<T>& v) {InitData(0,v.size() +_nDefaultBufferCount );for (const auto& tValue : v) {Add(tValue);}}/// <summary>/// /// </summary>/// <returns></returns>/// 创建时间:2023-05-03    最后一次修改时间:2023-05-03   inline _ArrayIterator<T> begin()const { return _ArrayIterator<T>(_pData); }/// <summary>/// /// </summary>/// <returns></returns>/// 创建时间:2023-05-03    最后一次修改时间:2023-05-03   inline _ArrayIterator<T> end()const{//迭代器使用的语句//for (_ArrayIterator<int> f = dl.begin(); f != dl.end(); f++) {       }return _ArrayIterator<T>(_pData + _nElementCount);}//-------------------------------------------------------------------------------------------------------------操作符重载
public:inline _Array<T>& operator=(const _Array<T>& rhs){if (&rhs != this){if ( &rhs != null && rhs._nElementCount != 0){_Memory::Delete<T>(_pData, _nElementCount + _nBufferCount);_nDefaultBufferCount = rhs._nDefaultBufferCount;_nBufferCount = rhs._nBufferCount;_nElementCount = rhs._nElementCount;_pData = _Memory::New<T>(_nElementCount + _nBufferCount);_Memory::Copy(_pData, rhs._pData, _nElementCount + _nBufferCount);}else{ClearMemory();}}return *this;}//重载的下标操作符inline T& operator[](const int& nIndex)const{
#ifdef _ARRAY_DEBUG_assert(nIndex < _nElementCount);
#endifreturn _pData[nIndex];}inline bool operator==(const _Array<T>& rhs) const{if (_pData == rhs._pData) return true;  //排除 相同引用  class aValue;    if( aValue == aValue)if (_pData == nullptr || rhs._pData == nullptr) return false;if (_nElementCount != rhs._nElementCount) return false;for (int n = 0; n < rhs._nElementCount; ++n){if (_pData[n] != rhs._pData[n]) return false;}return true;}inline bool operator!=(const _Array& rhs) const{return (*this == rhs ? false : true);}/*//模板类的友元函数,这里的的T跟T,是独立于类_Array<T>的template<typename T>friend bool operator== (const _Array<T>& lhs, const _Array<T>& rhs);template<typename T>friend bool operator!= (const _Array<T>& lhs, const _Array<T>& rhs);*/#if _CLR_/// <summary>/// /// </summary>/// <param name="arr"></param>/// 创建时间: 2022-12-25      最后一次修改时间:2022-12-25   inline _Array(cli::array<T>^ arr){InitData(0,arr->Length + 8);for each (T t in arr){Add(t);}}/// <summary>/// /// </summary>/// 创建时间: 2022-12-25      最后一次修改时间:2022-12-25  inline  operator cli::array<T>^ () const{cli::array<T>^ arr	= gcnew cli::array<T>(_nElementCount);for (int i = 0; i < _nElementCount; ++i){  arr[i] = _pData[i];}return arr;	 }#endifpublic://-----------------------------------------------------------------------------------------------------属性/// <summary>/// 内存大小,以 byte 为单位。/// </summary>/// <returns></returns>inline int GetMemoryLength()const { return sizeof(T) * (_nElementCount + _nBufferCount); }/// <summary>/// 字符串长度/// </summary>__declspec(property(get = GetMemoryLength)) const int MemoryLength;inline int GetDataMemoryLength()const { return sizeof(T) * _nElementCount; }/// <summary>/// 数据占用的内存长度,以 byte 为单位。/// </summary>__declspec(property(get = GetDataMemoryLength)) const int DataMemoryLength;/// <summary>/// vector 容器的容量(用 capacity 表示),指的是在不分配更多内存的情况下,/// 容器可以保存的最多元素个数;而 vector 容器的大小(用 size 表示),/// 指的是它实际所包含的元素个数。	对于一个 vector 对象来说,通过该模板类提供的 /// capacity() 成员函数,可以获得当前容器的容量;通过 size() 成员函数,可以获得容器当前的大小/// </summary>/// <returns></returns>inline int Capacity()const { return _nElementCount + _nBufferCount; }/// <summary>/// 每次重新分配内存缺省缓冲数量/// </summary>/// <returns></returns>inline int DefaultBuffer() const { return _nDefaultBufferCount; }/// <summary>/// 剩余缓冲数量/// </summary>/// <returns></returns>inline int Buffer() const { return _nBufferCount; }//设置缺省缓冲数量inline void DefaultBuffer(const int& nDefaultBuffer) { _nDefaultBufferCount = nDefaultBuffer; }//是否为空inline bool IsEmpty() { return _nElementCount == 0; }//----------------------------------------------------------------------------------------------------操作//查找元系的最大值inline const T* Min() const { return _Math::Min<T>(_pData, _nElementCount); }//查找元系的最小值inline const T* Max() const { return _Math::Max<T>(_pData, _nElementCount); }//开始位置inline  T* Begin()const { return _pData; }// 结束位置inline  T* End()const { return _pData + _nElementCount; }/// <summary>/// 返回一个翻转的数组/// </summary>/// <returns></returns>/// 创建时间:2023-05-01    最后一次修改时间:2023-05-01 inline _Array<T> Reverse()const{_Array<T> arrResult(_nElementCount);	for (int i = _nElementCount - 1; i >= 0; --i){arrResult.Add(_pData[i]);}return arrResult;}//---------------------------------------------------------------------------------------------------------虚拟函数,子类重写
protected:/// <summary>/// 初始化数据/// </summary>/// <param name="nElementCount">元素个数</param>/// <param name="nBufferCount">缓冲个数</param>/// <param name="tDefaultValue">元素默认值</param>/// <param name="bDefaultValue">是否设置元素默认值</param>/// <param name="bInitBuffer">是否初始化缓冲</param>/// 创建时间:????-??-??    最后一次修改时间:2024-09-15 inline virtual void InitData(const size_t& nElementCount = 0,const size_t& nBufferCount = 0,const T& tDefaultValue = T(),const bool& bDefaultValue= false,const bool& bInitBuffer = false){ _nBufferCount = nBufferCount;_nElementCount = nElementCount;_pData = null;if (_nElementCount + _nBufferCount > 0) {//分配内存_pData = _Memory::New<T>(_nElementCount + _nBufferCount);//初始化数据if (bDefaultValue) {for (size_t n = 0; n < _nElementCount; ++n) {*(_pData + n) = tDefaultValue;}}//初始化缓冲if (bInitBuffer) {for (size_t n = _nElementCount; n < _nElementCount + _nBufferCount; ++n) {*(_pData + n) = T();}}}		#ifdef _ARRAY_DEBUG__cout << _t("inline virtual void _Array<T>::InitData") << _t("\n");
#endif}public:/// <summary>/// _Array<_char> *ps = new LString("abc");  delete ps; /// 如果_Array的析构函数不用virtual,则上属语句LString的虚拟函数不会被调用/// 虚析构函数的作用是为了当用一个基类的指针删除一个派生类的对象时,派生类的析构函数会被调用。/// 当然,并不是要把所有类的析构函数都写成虚函数。因为当类里面有虚函数的时候,编译器/// 会给类添加一个虚函数表,里面来存放虚函数指针,这样就会增加类的存储空间。所以,只有当一/// 个类被用来作为基类的时候,才把析构函数写成虚函数。/// </summary>inline virtual ~_Array(){
#ifdef _ARRAY_DEBUG__cout << _t("_Array<T>::~_Array()\n");
#endifClearMemory();}/// <summary>/// 添加一串元素,pData为数据指针,nLength数据长度/// </summary>/// <param name="pData"></param>/// <param name="nLength"></param>/// <returns></returns>inline virtual _Array<T>& Add(const T* pData, const int& nLength){#ifdef _ARRAY_DEBUG_//_cout << _t("调用函数:inline virtual const T* add(const T* pData, const int nLength)\t参数:") << _geti(nLength) << _t("\n");;
#endif	 /*#ifdef  _STR_DEBUG__cout << _t("_Str<T>:\t inline  const _Str<T>& Add(const T& aChar) 参数:") << _geti(aChar) << _t("\n");
#endif //要判断 *pData == 0 防止  str_.Add(L"\0",1); if (aChar == 0) { return *this; }if (_nBufferCount >= 1){_pData[_nElementCount] = aChar;_nBufferCount -= 1;_nElementCount += 1;_pData[_nElementCount] = 0;}else{SetBuffer(1 + _nDefaultBufferCount * _Math::Pow(2, _nAutoBufferCount)); //自动设置缓冲次数加 if (_nBufferCount >= 1){_pData[_nElementCount] = aChar;_nBufferCount -= 1;_nElementCount += 1;_pData[_nElementCount] = 0;}else{throw _t("设置缓冲区失败!");}++_nAutoBufferCount;}return *this;}*/if (pData == null || nLength <= 0) return *this;if (_nBufferCount >= nLength){_Memory::Copy<T>(_pData + _nElementCount, pData, nLength);_nBufferCount -= nLength;_nElementCount += nLength;}else{	SetBuffer(nLength + _nDefaultBufferCount * _Math::pow(2, _nAutoBufferCount)); //自动设置缓冲次数加 if (_nBufferCount >= nLength){_Memory::Copy<T>(_pData + _nElementCount, pData, nLength);				 _nBufferCount -= nLength;_nElementCount += nLength;				 }else{throw _t("设置缓冲区失败!");}++_nAutoBufferCount;}return *this;}/// <summary>/// 添加单个元素/// </summary>/// <param name="rData"></param>/// <returns></returns>inline _Array<T>& Add(const T& rData){	return Add(&rData, 1);	}/// <summary>/// 添加一个数组/// </summary>/// <param name="arr"></param>/// <returns></returns>inline _Array<T>& Add(const _Array<T>& arr){return Add(arr.DataConst, arr.Length);}//删除元系,nStartPos为开始位置,nLength长度inline virtual const T* Del(const int& nStartPos, const int& nLength){if (nStartPos + nLength > _nElementCount){_nBufferCount = _nBufferCount + _nElementCount - nStartPos;_nElementCount = nStartPos + 1;}else if (nStartPos + nLength >= _nElementCount){_nElementCount -= nLength;_nBufferCount += nLength;}else{for (int n = nStartPos + nLength; n < _nElementCount; ++n){_pData[n - nLength] = _pData[n];}_nElementCount -= nLength;_nBufferCount += nLength;}return _pData;}/// <summary>/// 清空所有内存,并把指针设为null/// </summary>inline virtual void ClearMemory() override{#ifdef _ARRAY_DEBUG_//_cout << _t("void _Array<T>::ClearData()\n");#endifif (_nElementCount + _nBufferCount > 0 && _pData != null) {_Memory::Delete<T>(_pData, _nElementCount + _nBufferCount);}else {if (_pData != null) {throw "_pData != null";}}_pData = null;_nBufferCount = 0;_nElementCount = 0;}/// <summary>/// 清空数据,但不释放内存,只是把数据计数器重设为0。/// </summary>inline virtual void ClearData()override{_nBufferCount = _nBufferCount + _nElementCount;_nElementCount = 0;}/// <summary>///  设置缓冲数,如果原来缓冲区数量大于新设置的数量,则不设置。/// </summary>/// <param name="nBufferCount"></param>/// <param name="bZeroBuffer"></param>/// 创建时间:????-??-??    最后一次修改时间:2023-03-11 inline virtual void SetBuffer(const int& nBufferCount, const bool& bZeroBuffer = false){#ifdef _ARRAY_DEBUG__cout << _t("调用函数:inline virtual void SetBuffer(const int& nBufferCount)\t参数:") << _geti(nBufferCount) <<_t("\n");
#endif	 if (_nBufferCount >= nBufferCount) return;if (nBufferCount == 0) return;T* pNew = _Memory::New<T>(_nElementCount + nBufferCount);if (_nElementCount > 0)_Memory::Copy(pNew, _pData, _nElementCount);_Memory::Delete<T>(_pData, _nElementCount + _nBufferCount);_pData = pNew;_nBufferCount = nBufferCount;if (bZeroBuffer)ZeroBufferAll();}/// <summary>/// 转为String表示/// </summary>/// <returns></returns>/// 创建时间:2023-04-29    最后一次修改时间:2024-08-17inline virtual _string ToSplitString(const _string& sSplitString)  const override{  				_string sResult;_string sp = sSplitString.Length == 0 ? _string(_t(",")) : sSplitString;sResult.Add(_t("{"));if (_nElementCount > 0){for (int i = 0; i < _nElementCount - 1; ++i){sResult.std_append(_Convert::to_string_t<T>(_pData[i]));sResult.std_append(sp);}sResult.std_append(_Convert::to_string_t<T>(_pData[_nElementCount - 1]));}sResult.Add(_t("}"));return sResult;}inline _string ToString()const{return ToSplitString("");}/// <summary>/// 强制转换为String/// </summary>/// 创建时间:2023-04-29    最后一次修改时间:2023-04-29operator _stdstr()const{return ToString().std_c_str();}public: //从nStart开始向后查找aTypeValue第一次出现在当前容器中的位置,失败时返回_Array::nposinline int find(const T& aTypeValue, const int nStart = 0) const { return _Math::find(_pData, _nElementCount, &aTypeValue, 1, nStart); }//从nStart开始向后查找长度为pFindLength的pFind数据第一次出现在当前容器中的位置,失败时返回_Array::nposinline int find(const T* pFind, const int& nStart, const int& pFindLength) const { return _Math::find(_pData, _nElementCount, pFind, pFindLength, nStart); }//从nStart开始向后查找aFindLLinearList第一次出现在当前容器中的位置,失败时返回_Array::npos int find(const _Array& aFindLLinearList, const int& nStart = 0) const { return _Math::find(_pData, _nElementCount, aFindLLinearList._pData, aFindLLinearList._nElementCount, nStart); }//从nStart开始向前查找aTypeValue第一次出现在当前容器中的位置,失败时返回_Array::npos。inline int rfind(const T& aTypeValue, const int& nStart = npos) const { return _Math::rfind(_pData, _nElementCount, &aTypeValue, 1, nStart); }//从nStart开始向前查找长度为pFindLength的pFind数据第一次出现在当前容器中的位置,失败时返回_Array::nposinline int rfind(const T* pFind, const int& nStart, const int& pFindLength) const { return _Math::rfind(_pData, _nElementCount, pFind, pFindLength, nStart); }//从nStart开始向前查找aFindLLinearList第一次出现在当前容器中位置,失败时返回_Array::npos inline int rfind(const _Array& aFindLLinearList, const int& nStart = npos) const { return _Math::rfind(_pData, _nElementCount, aFindLLinearList._pData, aFindLLinearList._nElementCount, nStart); }//从nStart开始向后查找aTypeValue第一次出现的位置,失败时返回_Array::nposinline int find_First_of(const T& aTypeValue, const int& nStart = 0) const { return _Math::find_First_of(_pData, _nElementCount, &aTypeValue, 1, nStart); }//从nStart开始向后查找长度为pFindLength的pFind数据任一元素第一次出现的位置,失败时返回_Array::nposinline int find_First_of(const T* pFind, const int& nStart, const int& pFindLength) const { return _Math::find_first_of(_pData, _nElementCount, pFind, pFindLength, nStart); }//从nStart开始向后查找aFindLLinearList任一元素第一次出现的位置,失败时返回_Array::npos inline int find_First_of(const _Array& aFindLLinearList, const int& nStart = 0) const { return _Math::find_first_of(_pData, _nElementCount, aFindLLinearList._pData, aFindLLinearList._nElementCount, nStart); }//从nStart开始向后查找aTypeValue第一次不出现的位置,失败时返回_Array::nposinline int find_First_not_of(const T& aTypeValue, const int& nStart = 0) const { return _Math::find_first_not_of(_pData, _nElementCount, &aTypeValue, 1, nStart); }//从nStart开始向后查找长度为pFindLength的pFind数据任一元素第一次不出现的位置,失败时返回_Array::nposinline int find_First_not_of(const T* pFind, const int& nStart, const int& pFindLength) const { return _Math::find_first_not_of(_pData, _nElementCount, pFind, pFindLength, nStart); }//从nStart开始向后查找aFindLLinearList任一元素第一次不出现的位置,失败时返回_Array::npos inline int find_First_not_of(const _Array& aFindLLinearList, const int& nStart = 0) const { return _Math::find_first_not_of(_pData, _nElementCount, aFindLLinearList._pData, aFindLLinearList._nElementCount, nStart); }//从nStart开始向前查找aTypeValue第一次出现的位置,成功返回索引处,失败时返回_Array::nposinline int find_last_of(const T& aTypeValue, const int& nStart = 0) const { return _Math::find_last_of(_pData, _nElementCount, &aTypeValue, 1, nStart); }//从nStart开始向前查找pFind中元系第一次出现的位置,成功返回索引处,失败时返回_Array::nposinline int find_last_of(const T* pFind, const int& nStart, const int& pFindLength) const { return _Math::find_last_of(_pData, _nElementCount, pFind, pFindLength, nStart); }//从nStart开始向前(倒序)查找aFindLLinearList任一元素第一次出现的位置,找到返回索引处,失败时返回_Array::nposinline int find_last_of(const _Array& aFindLLinearList, const int& nStart = 0) const { return _Math::find_last_of(_pData, _nElementCount, aFindLLinearList._pData, aFindLLinearList._nElementCount, nStart); }//从nStart开始向前查找aTypeValue第一次不出现的位置,失败时返回_Array::nposinline int find_last_not_of(const T& aTypeValue, const int& nStart = 0) const { return _Math::find_last_not_of(_pData, _nElementCount, &aTypeValue, 1, nStart); }//从nStart开始向前查找长度为pFindLength的pFind数据任一元素第一次不出现的位置,失败时返回_Array::nposinline int find_last_not_of(const T* pFind, const int& nStart, const int& pFindLength) const { return _Math::find_last_not_of(_pData, _nElementCount, pFind, pFindLength, nStart); }//从nStart开始向前查找aFindLLinearList任一元素第一次不出现的位置,失败时返回_Array::npos inline int find_last_not_of(const _Array& aFindLLinearList, const int& nStart = 0) const { return _Math::find_last_not_of(_pData, _nElementCount, aFindLLinearList._pData, aFindLLinearList._nElementCount, nStart); }public:/// <summary>/// 临时整型数据,方法函数调用。/// </summary>int TmepEffectiveCount = 0;/// <summary>/// 把有效长度后一位数据进行初始化,如果是数字,则会自动初始化0。/// </summary>inline void ZeroBufferOne() {if (this->_nBufferCount > 0)this->_pData[this->_nElementCount] = T();}/// <summary>/// 初始化剩下的缓冲区/// </summary>inline void ZeroBufferAll() {if (this->_nBufferCount > 0){for (int i = 0; i < _nBufferCount; ++i){_pData[i + _nElementCount] = T();}}}/// <summary>/// 重新设置元素的长度,这个长度不能超过 OldLength + Buffer/// </summary>/// <param name="nNewLength"></param>/// 创建时间:????-??-??    最后一次修改时间:????-??-??(2024/04/21)inline void ResetLength(const int& nNewLength) {if (nNewLength > this->Capacity()) {_char  sError[] = _t("新设置的长度已超过容器的最大长度!\n");_cout << _t("_Mem::ResetLength") << sError;throw sError;}int iCap = this->Capacity();this->_nBufferCount = iCap - nNewLength;this->_nElementCount = nNewLength;}/// <summary>/// 除非内存给其它对象托管,否则不要调用这个函数。/// 放置对象当前使用的内存,可能内存已托管给别的对象,/// 重新初始化当前对象/// </summary>/// 创建时间:2022-12-29    最后一次修改时间:2022-12-29inline virtual void GiveUpMem(){this->InitData(0);}/// <summary>/// 返回有nCount个元素的数组。/// </summary>/// <param name="nCount"></param>/// <returns></returns>/// 创建时间:2023-12-10    最后一次修改时间:2023-12-10   已测试static inline _Array<T> newElement(const size_t& nCount){_Array<T> tmp(nCount); //设置nCount个缓冲//把缓冲变成元素tmp._nBufferCount = 0; tmp._nElementCount = nCount;return tmp;  //此处C++编译器直接返回tmp对象,不会再构造一个_Array<T>.}public://----------------------------------------------------------------属性  inline T* GetData() { return this->_pData; }__declspec(property(get = GetData)) T* Data;inline const T* GetDataConst() const { return  this->_pData; }__declspec(property(get = GetDataConst)) const T* DataConst;/// <summary>/// 数组长度,无素个数/// </summary>__declspec(property(get = GetLength)) int Length;/// <summary>/// 有效元素的个数/// </summary>/// <returns></returns>inline int GetLength()const { return _nElementCount; }/// <summary>/// 自动分配内存次数/// </summary>/// 创建时间:2024-08-18    最后一次修改时间:2024-08-18__declspec(property(get = GetAutoBufferCount)) size_t AutoBufferCount;inline const size_t& GetAutoBufferCount()const{ return _nAutoBufferCount; }}; //-------------------------------------------------------------------------------------_Array#ifdef _UNICODE_template<class T>
std::wistream& operator >> (std::wistream& os, _Array<T>& arr)
{_cout << _t("std::wistream& operator >> (std::wistream& os, _Array<T>& aString){未完成!\n");return os;
}template<class T>
std::wostream& operator<<(std::wostream& os, const _Array<T>& arr)
{os << arr.ToString();return os;
}#else
template<class T>
std::istream& operator >> (std::istream& os, _Array<T>& aString)
{_cout << _t("std::wistream& operator >> (std::wistream& os, _Array<T>& aString){未完成!\n");return os;
}template<class T>
std::ostream& operator<<(std::ostream& os, const _Array<T>& arr)
{os << arr.ToString();return os;
}#endif_LF_END_ //------------------------------------------------------------------------------_LF_END_ #endif // !_ARRAY_H_

_ByteArray.h

/*******************************************************************************************
文件名						: _ByteArray.h作者							: 李锋功能							: 字节数组创建时间						: 2022年01月01日最后一次修改时间				:  2022年01月05日
********************************************************************************************/#ifndef __BYTEARRAY_H_
#define __BYTEARRAY_H_#include "_Array.h"
#include "_StrA.h"
#include "_StrW.h"_LF_BEGIN_/// <summary>
/// _Byte 数组
/// </summary>
class _ByteArray final : public _Array<_byte>
{
public:explicit _ByteArray(int nBuffer = 0) : _Array<_byte>(nBuffer) {}explicit _ByteArray(const _ByteArray& ba, const size_t&  nCount);
public:void TrusteeshipMem(const _byte* pData, const int nDataMemoryLength, const int& nMemoryLength);void TrusteeshipMem(_string& sText);void TrusteeshipMem(_ByteArray& ba);//int AddString(const _string& S);int AddStringA(const _StrA& s);int AddStringW(const _StrW& s);int AddFloat(const float& fValue);int AddInt(const int& iValue);int AddInt64(const __int64& iValue);int AddByte(const _byte& bValue);//_string  ReadString(const int& nPos, const int& nLength);_StrA  ReadStringA(const int& nPos, const int& nLength);_StrW  ReadStringW(const int& nPos, const int& nLength);bool ReadFromFile(const _char* sFileName);bool WriteToFile(const _char* sFileName);/// <summary>/// 类型转换,转换成T类型/// </summary>/// <typeparam name="T"></typeparam>/// <param name="nStart">指针开始位置</param>/// <returns>返回T类型的引用</returns>/// 创建时间:2024-08-12    最后一次修改时间:2024-08-12template<class T> const T& ToAny(const size_t& nStart = 0)const{lassert( _nElementCount >= nStart + sizeof(T)   ,"转换的数据太大了,大于数组本身所分配的内存。");T* pt = (T*)_pData + nStart;return *pt;}/// <summary>/// 转换为宽字符串/// </summary>/// <returns></returns>/// 创建时间:2024-08-12    最后一次修改时间:2024-08-12const _string ToWString()const;
};_LF_END_  //------------------------------------------------------------------------------------------_LF_END_#endif  //------------------------------------------------------------------- #endif 

_ByteArray.cpp

#include "_ByteArray.h"
#include "global_c_all.h"_LF_BEGIN__ByteArray::_ByteArray(const _ByteArray& ba, const size_t& nCount)
{if (nCount >= ba.Length){Add(ba);}else{_Array<_byte>::Add(ba.DataConst, nCount);}
}/// <summary>
/// 释放本身内存,托管新的内存。
/// </summary>
/// <param name="pData"></param>
/// <param name="nDataMemoryLength">数据长度</param>
/// <param name="nMemoryLength">使用内存长度</param>
/// 创建时间:2023-01-04    最后一次修改时间:2023-01-05
void _ByteArray::TrusteeshipMem(const _byte* pData, const int nDataMemoryLength, const int& nMemoryLength)
{ClearMemory();  //清除内存_nBufferCount = nMemoryLength - nDataMemoryLength;if (_nBufferCount < 0){throw _t("托管内存错误!");}_pData = (_byte*)pData;_nElementCount = nDataMemoryLength;
}/// <summary>
/// 托管String对象,并放本身内存。
/// </summary>
/// <param name="sText"></param>
/// 创建时间:2023-01-04    最后一次修改时间:2023-01-05
void _ByteArray::TrusteeshipMem(_string& sText)
{TrusteeshipMem((const _byte*)sText.Data, sText.DataMemoryLength, sText.MemoryLength);sText.GiveUpMem();
}/// <summary>
/// 释放本身内存,托管其它对象
/// </summary>
/// <param name="ba"></param>
/// 创建时间:2023-01-04    最后一次修改时间:2023-01-05
void _ByteArray::TrusteeshipMem(_ByteArray& ba)
{TrusteeshipMem((const _byte*)ba.Data, ba.GetDataMemoryLength(), ba.GetMemoryLength());ba.GiveUpMem();
}/*
int  _ByteArray::AddString(const _string& s)
{if (s.Length == 0) return -1;int nPos = Length;Add((_byte*)s.Data, (int) (sizeof(_char) * s.Length) );return nPos;}
*/
int _ByteArray::AddStringA(const _StrA& s)
{if (s.Length == 0) return -1;int nPos = _nElementCount;Add((_byte*)s.Data, (int)(sizeof(char) * s.Length));return nPos;
}int _ByteArray::AddStringW(const _StrW& s)
{if (s.Length == 0) return -1;int nPos = _nElementCount;Add((_byte*)s.Data, (int)(sizeof(wchar_t) * s.Length));return nPos;
}int _ByteArray::AddFloat(const float& fValue)
{int nPos = _nElementCount;Add((_byte*)&fValue, sizeof(float));return nPos;
}int _ByteArray::AddInt(const int& iValue)
{int nPos = _nElementCount;Add((_byte*)&iValue, sizeof(int));return nPos;
}int _ByteArray::AddInt64(const __int64& iValue)
{int nPos = _nElementCount;Add((_byte*)&iValue, sizeof(__int64));return nPos;
}int _ByteArray::AddByte(const _byte& bValue)
{int nPos = _nElementCount;Add(&bValue, sizeof(_byte));return nPos;
}/*
_string _ByteArray::ReadString(const int& nPos, const int& nLength)
{int n = nLength / sizeof(_char);return _string( (_char*) (_pData + nPos), n);
}
*/_StrA _ByteArray::ReadStringA(const int& nPos, const int& nLength)
{int n = nLength / sizeof(char);return _StrA((char*)(_pData + nPos), n);
}_StrW _ByteArray::ReadStringW(const int& nPos, const int& nLength)
{int n = nLength / sizeof(wchar_t);return _StrW((wchar_t*)(_pData + nPos), n);
}bool _ByteArray::ReadFromFile(const _char* sFileName)
{return ga.ReadFileToBuffer<_byte>(sFileName, *this);}bool _ByteArray::WriteToFile(const _char* sFileName)
{return ga.WriteFile<_byte>(sFileName, *this);
}const _string _ByteArray::ToWString() const
{	 return (wchar_t*)_pData;
}_LF_END_


http://www.ppmy.cn/devtools/112712.html

相关文章

直播相关03-录制麦克风声音, ffmpeg 命名,使用命令行完成录音

一 ffmpeg 命令 ffmpeg arg1 arg2 -i arg3 arg4 arg5ffmpeg 全局参数 输入文件参数 -i 输入文件 输出文件参数 输出文件arg1&#xff1a;全局参数 arg2&#xff1a;输入文件参数 arg3&#xff1a;输入文件 arg4&#xff1a;输出文件参数 arg5&#xff1a;输出文件 二 ffprobe …

根据NVeloDocx Word模板引擎生成Word(四)

前面介绍了《E6低代码开发平台》的Word模版引擎NVeloDocx&#xff0c;实现了表单的基本字段、子表、单张图片、二维码、条形码怎么基于NVelocity脚本输出到Word文件&#xff0c;都是些比较简单且常用的需求。 本篇介绍怎么基于NVeloDocx在Word中插入图表&#xff0c;目前只支持…

HarmonyOS Next鸿蒙NDK使用示例

创建一个Native C项目 跟普通项目相比&#xff0c;主要区别是多了一个cpp文件夹、oh-package.json5中的dependencies引入还有build-profile.json5中的externalNativeOptions配置&#xff0c;abiFilters是支持的CPU架构&#xff0c;目前移动端项目只支持arm64-v8a、x86_64两种。…

笔试强训day07

在字符串中找出连续最长的数字串 #include <bits/stdc.h>using namespace std; const int N 500; char s[N]; bool check(char c) {return c > 0 && c < 9; } int main() {scanf("%s", s);int l -1, r -1;int n strlen(s);int left 0, rig…

Spring Boot 常用注解

1. 基础 Spring 注解 Component 标记一个类作为 Spring IoC 容器的一个组件。Repository 标记一个 DAO 类&#xff0c;同时提供了异常转换机制。Service 标记业务逻辑层的服务类。Controller 标记一个 Web 层的控制器类。RestController 结合了 Controller 和 ResponseBody&am…

GO Govaluate

govaluate 是一个用于在 Go 语言中动态求值表达式的库。它允许你解析和评估字符串形式的表达式&#xff0c;这些表达式可以包含变量、函数以及逻辑、算术和比较操作。它非常适合在运行时处理复杂的逻辑规则和条件表达式&#xff0c;而不需要重新编译代码。 安装 govaluate go…

C语言自定义类型结构体(24)

文章目录 前言一、结构体类型的声明结构体回顾结构体的特殊声明结构体的自引用 二、结构体的内存对齐对齐规则为什么存在内存对齐&#xff1f;修改默认对齐数 三、结构体传参四、结构体实现位段什么是位段位段的内存分配位段的跨平台问题位段的应用位段使用的注意事项 总结 前言…

Linux学习-Ansible(一)

环境- Rocky-Linux8.6 安装部署Ansible # 安装ansible [rootharbor ansible]# dnf install -y ansible-core #查看安装信息 [rootharbor ansible]# ansible-doc --version ansible-doc [core 2.12.2]config file /root/ansible/ansible.cfgconfigured module search path […

动态规划---不相交的线

题目&#xff1a; 在两条独立的水平线上按给定的顺序写下 nums1 和 nums2 中的整数。 现在&#xff0c;可以绘制一些连接两个数字 nums1[i] 和 nums2[j] 的直线&#xff0c;这些直线需要同时满足&#xff1a; nums1[i] nums2[j]且绘制的直线不与任何其他连线&#xff08;非水…

SQLITE3数据库实现信息的增删改查

#include <myhead.h> #include <sqlite3.h> typedef struct { int id; char name[20]; int age; int money; }woker; int callbake(void *arg,int n,char **a,char **b)//回调 输出查找到的工人信息 { for(int i 0;i<n;i) { …

[数据集][目标检测]汽车头部尾部检测数据集VOC+YOLO格式5319张3类别

数据集制作单位&#xff1a;未来自主研究中心(FIRC) 版权单位&#xff1a;未来自主研究中心(FIRC) 版权声明&#xff1a;数据集仅仅供个人使用&#xff0c;不得在未授权情况下挂淘宝、咸鱼等交易网站公开售卖,由此引发的法律责任需自行承担 数据集格式&#xff1a;Pascal VOC格…

Linux05

1.echo命令 echo是输出命令&#xff0c;类似printf 例如&#xff1a;echo "hello world"&#xff0c;输出hello world echo pwd&#xff0c;输出pwd的位置。是键盘上~ 2.重定向符> >> >指把左边内容覆盖到右边 echo hello world>test.txt >…

MATLAB在嵌入式系统设计中的最佳实践

嵌入式系统设计是一个复杂的过程&#xff0c;涉及硬件和软件的紧密集成。MATLAB提供了一套全面的解决方案&#xff0c;从算法开发到代码生成&#xff0c;再到硬件验证&#xff0c;极大地简化了这一过程。本文将探讨使用MATLAB进行嵌入式系统设计的最佳实践&#xff0c;包括模型…

Vue Router push方法的使用

Vue Router push方法的使用 this.$router.push 是 Vue Router 提供的一个方法,用于在 Vue.js 应用中进行编程式导航。它的作用是将用户导航到应用中的不同路由。 基本作用 this.$router.push 方法会在浏览器历史记录中添加一个新的记录,并导航到指定的路由。它的工作方式类…

深度学习中常见的损失函数

在机器学习和深度学习中&#xff0c;损失函数用于衡量模型预测值与真实值之间的差异。根据任务的类型&#xff08;如回归、分类等&#xff09;&#xff0c;可以使用不同的损失函数。下面列举了一些常见的损失函数&#xff1a; 1. 回归问题中的损失函数 回归任务的目标是预测连…

广播与组播,超时检测

目录 一.超时检测 必要性 超时检测的设置方法 1. 通过函数自带的参数设置 2. 通过设置套接字属性进行设置 3. alarm函数与sigaction函数结合 二.广播与组播&#xff08;broadcast & multicast&#xff09; 1. 广播&#xff08;udp&#xff09; 理论&#xff1a…

什么是外贸专用路由器?

一、外贸专用路由器的显著特点 全球兼容性 外贸专用路由器支持多种国际通信标准和频段&#xff0c;能够无缝连接不同国家和地区的网络&#xff0c;从而避免因地域限制导致的网络问题。这种全球兼容性确保了外贸企业在全球范围内的网络部署更加顺畅&#xff0c;让企业在任何角落…

对抗性EM用于变分深度学习:在低剂量PET和低剂量CT中的半监督图像质量增强应用|文献速递--Transformer架构在医学影像分析中的应用

Title 题目 Adversarial EM for variational deep learning: Application to semi-supervised image quality enhancement in low-dose PET and low-dose CT 对抗性EM用于变分深度学习&#xff1a;在低剂量PET和低剂量CT中的半监督图像质量增强应用 01 文献速递介绍 医学影…

『功能项目』战士的伤害型技能【45】

我们打开上一篇44战士职业平A怪物掉血的项目&#xff0c; 本章要做的事情是制作技能按钮&#xff0c;点鼠标点击时释放对范围内怪物的伤害技能 首先双击打开资源脚本下的Canvas预制体 制作技能栏 在资源商店中下载免费资源 - 技能图片 将技能图片拖拽至技能栏的Button按钮组件…

深入理解Python中的魔法参数 *args 和 **kwargs

在Python编程中&#xff0c;函数的灵活性是其强大之处之一。其中&#xff0c;*args 和 **kwargs 是实现函数参数可变性的重要工具。 无论我们是Python初学者还是经验丰富的开发者&#xff0c;充分理解这两个概念都有助于编写更加灵活、高效的代码。 本文将深入探讨*args和**kw…