例子:
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
表示非连续的内存区域并通过一对指向首尾元素的指针双向链接起来,插入删除效率高,随机访问效率低
2
stl提供了三个最基本的容器: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");
#endif
InitData(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");
#endif
if (&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-01
inline _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);
#endif
return _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;
}
#endif
public:
//-----------------------------------------------------------------------------------------------------属性
/// <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");
#endif
ClearMemory();
}
/// <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");
#endif
if (_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-17
inline 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-29
operator _stdstr()const
{
return ToString().std_c_str();
}
public:
//从nStart开始向后查找aTypeValue第一次出现在当前容器中的位置,失败时返回_Array::npos
inline int find(const T& aTypeValue, const int nStart = 0) const { return _Math::find(_pData, _nElementCount, &aTypeValue, 1, nStart); }
//从nStart开始向后查找长度为pFindLength的pFind数据第一次出现在当前容器中的位置,失败时返回_Array::npos
inline 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::npos
inline 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::npos
inline 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::npos
inline 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::npos
inline 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::npos
inline 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::npos
inline 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::npos
inline 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::npos
inline 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::npos
inline 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::npos
inline 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-29
inline 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-12
template<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-12
const _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_