c++用户管理信息(类指针数组)

news2024/7/4 5:15:55

用户管理信息--类指针数组

  • 类示意图
    • select类示意图
    • MyIterator示意图
    • VetorCstu示意图
    • ClassStu示意图
  • 项目源代码
    • select
      • select.h
      • select.cpp
    • MyIterator
      • MyIterator.h
      • MyIterator.cpp
    • VetorCstu
      • VetorCstu.h
      • VetorCstu.cpp
    • ClassStu
      • ClassStu.h
      • ClassStu.cpp
    • main源码
  • 总结---数组管理指针

类示意图

select类示意图

在这里插入图片描述

MyIterator示意图

在这里插入图片描述

VetorCstu示意图

在这里插入图片描述

ClassStu示意图

在这里插入图片描述

项目源代码

select

select.h

#pragma once
#include <iostream>
#include "classstu.h"
#include <iomanip>
#include "cfile.h"
#include "vetorcstu.h"
using namespace std;
///*
//类用于在内存中管理用户信息
//提供增删改查  功能等
//*/
//
class Select
{
public:
	/*
		* select  //构造函数
		* 参数一:传入用户个数,用来申请堆空间
		* 功能  : 初始化类成员
		* 返回值 无
		*
	*/

	Select()
	{
		m_pFile = nullptr;
		m_pcMyStu = 0;
	}

	Select(const char* filename) :m_pFile(new cFile(filename))
	{
		//1 委托构造已经初始化了文件类

		//2  初始化  cmystu内存操作的类
		  //2.1:读取文件头四个字节,保存用户的个数
			int nCount = m_pFile->ReadFileHeader();
		  //实例化cmystu类
			m_pcMyStu = new VetorCstu(nCount);
			if (m_pcMyStu == nullptr)
			{
				cout << "--cmystu--初始化申请内存失败" << endl;
				return;
			}

		//3  往m_pcMyStu里面插入5个ClassStu 初始化类成员
			m_pcMyStu->Insert(nCount);
		// 
		//4  把文件所有数据存放内存中
			m_pFile->ReadFileAllDate(m_pcMyStu);
	}

/*
	* ~select  //析构函数
	* 参数一:无
	* 功能  : 释放类成员申请的堆空间
	* 返回值 无
	*
*/
	~Select();


	/*
		* SelectAllDate
		* 参数一:无
		* 功能  : 把所有用户信息输出到标准设备中(屏幕)
		* 返回值 无
		*
	*/
	void SelectAllDate();

/*
	* FindOneDate
	* 参数一:myiterator
	* 功能  : 根据用户nuserid查找用户信息
	* 返回值 无
	*
*/
	bool FindOneDate(int nUserId);

	/*
		* DrawOneDate
		* 参数一:myiterator
		* 功能  : 输出传入用户的信息
		* 返回值 无
		*
	*/
	void DrawOneDate(MyIterator itr);


	/*
		* SelectFileOffOneDateId
		* 参数一:用户id号
		* 功能  : 根据用户userid,检测是否有当前用户,返回用户的文件偏移
		* 返回值 int类型;返回用户的文件偏移
		*
	*/
	int SelectFileOffOneDateId(int userid);


	/*
		* InsertOneDate
		* 参数一:字符串
		* 功能  : 内存中和文件中插入一个用户信息
		* 返回值 :bool
		*
	*/
	bool InsertOneDate(const char* susername,int nId = 0);


	/*
		* DeleteDate
		* 参数一:用户id -- userid
		* 功能  : 删除指定用户id在文件和内存中的数据
		* 返回值 :无
		*
	*/
	bool DeleteDate(int id);//删除数据

/*
	* UpDate
	* 参数一:const char*   修改的用户名
	* 参数一:用户id -- userid
	* 功能  : 修改用户数据
	* 返回值 :无
	*
*/
	bool UpDate(const char* susername, int nuserid);//修改用户数据

/*
	* callanyname   暂未实现
	* 参数一:
	* 功能  :
	* 返回值 :无
	*
*/
	//void callanyname();



/*
	* drawinit  初始化界面
	* 参数一:无
	* 功能  : //初始化界面
	* 返回值 :无
*/
	void DrawInit();//初始化界面


/*
	* drawhead
	* 参数一:无
	* 功能  : 把用户头部信息输出到标准设备中(屏幕)
	* 返回值 :无
*/
	void DrawHead();//封装显示头部
/*
	* IdEmptyFill
	* 参数一:用户id
	* 功能  : 计算id后面需要填充空格多少
	* 返回值 :无
*/
	int IdEmptyFill(int id);





/*
	* GetFlg
	* 参数一:无
	* 功能  : 获取类成员m_flg的值
	* 返回值 :bool
*/
	bool GetFlg();//记录是否有修改或删除数据的标志


/*
	* ReDEFile
	* 参数一:常量字符串  --文件名
	* 参数二:常量字符串  --新文件名
	* 功能  : 重写文件,把内存数据重新写入到文件中
	* 返回值 :bool 
	*
*/
	bool ReDEFile(const char* old_filename, const char* new_filename);//删除数据



/*
	* bubblesort
	* 参数一:无
	* 功能  : 冒泡排序法--大循环为次数,内循环为第n和第n+1依次往下对比
	* 返回值 :无
*/
	//void bubblesort();
	//排序--选择排序法 --取最小的索引;先比较数大小 --然后放在第i位
/*
	* selectionsort
	* 参数一:无
	* 功能  : 选择排序法--大循环为次数,取最小的索引;先比较数大小 --然后放在第i位
	* 返回值 :无
*/
	//void selectionsort();

	/*
		* insertsort
		* 参数一:无
		* 功能  : 插入排序法-- --依次往上对比;--   次数一次比一次对比多
		* 返回值 :无
	*/
	//void insertsort();
public:
	cFile* m_pFile;  //一个操作文件
	VetorCstu* m_pcMyStu;//一个操作内存

	bool m_flg = false;// 需要重写文件标志 记录是否有修改 或删除过数据  id为0的数据

};

select.cpp

#include "Select.h"


void Select::SelectAllDate()
{
	//显示头部标题
	DrawHead();
	//内存数据进行冒泡排序
	m_pcMyStu->BubbleSort();
	//序号 nIndex
	int nIndex = 1;
	//int nCount = m_cMyStu->GetCount();
	//迭代器输出
	for (auto Val : *m_pcMyStu)
	{
	
		if (Val.m_Id != 0)
		{

			cout << nIndex << setw(14 - (IdEmptyFill(nIndex))) << " ";

			cout << Val.m_Id << setw(8 - (IdEmptyFill(Val.m_Id))) << " ";

			cout << Val.m_StuName->GetStr() << setw(14 - ((Val.m_StuName->GetLen()))) << "  ";

			cout << Val.m_FileOffset << endl;
		}
		else
		{
			m_flg = true;
		}

		nIndex++;
	}

}

bool Select::FindOneDate(int nUserId)
{
	if (nUserId < 0)
	{
		return false;
	}
	MyIterator Itr = m_pcMyStu->Find(nUserId);
	DrawOneDate(Itr);
	return true;
	
}

void Select::DrawOneDate(MyIterator Itr)
{
	if (Itr == nullptr)
	{

		cout << "没有该用户Id" << endl;
		return;
	}

   DrawHead();
//	//打印pFindName查找到的用户信息
	cout << (*Itr).m_Id << setw(8 - IdEmptyFill((*Itr).m_Id)) << " ";
	cout << (*Itr).m_StuName->GetStr()<< setw(14 - (*Itr).m_StuName->GetLen()) << "  ";
	cout << (*Itr).m_FileOffset << endl;
}


//
int Select::SelectFileOffOneDateId(int UserId)
{
	//检查 UserId  // 检测最大是 也是要迭代
	if (UserId <= 0)
	{
		return 0;
	}
	for(auto Val:*m_pcMyStu)
	{
	
		if (UserId == Val.m_Id)
		{

			return Val.m_FileOffset;//返回在文件中的偏移
		}
		
	}
	return 0;
}

bool Select::InsertOneDate(const char* sUserName, int nUserId)
{
	//检测指针和长度
	int nLen = strlen(sUserName);
	if (sUserName == nullptr || nLen == 0)
	{
		cout << "sUserName写入失败" << endl;
		return false;
	}

	//如果为了就是插入新数据 否则是修改数据
	if(nUserId == 0)
	{ 
		nUserId = m_pcMyStu->GetMaxUserId();//用户id
	}

	MyStr* cStr = new MyStr(sUserName);

		//文件中插入数据
	ClassStu* cTmp = m_pFile->WriteInsertFile(cStr, nUserId);
	if (cTmp == nullptr)
	{
		cout << "ClassStu* cTmp写入失败" << endl;
		return false;
	}

	//内存插入数据
	m_pcMyStu->push_back(cTmp);

	//直接赋值cStr 空指针
	cStr = nullptr;
	cTmp = nullptr;
	return true;
}


bool Select::DeleteDate(int nId)
{
	//nId为用户序号  序号-1 为用户的数组索引
	int nIndex = nId - 1;
	int FileOffset = (*m_pcMyStu)[nIndex].m_FileOffset;
	
	if (!FileOffset == 0)
	{
		//需要判断一下  是否找到了
		//获取到文件偏移 修改文件的数据 把用户Id改为0即可
		if (m_pFile->WriteDeleteFile(FileOffset) == 1)
		{
			//内存中删除
			m_pcMyStu->Erase(nIndex);
			m_flg = true;
			return m_flg;
		}
	}
	return false;
}

bool Select::UpDate(const char* sUserName, int nId)
{
	//nId转为 用户的userid
	int nUserId = (*m_pcMyStu)[nId - 1].m_Id;
	//先插入数据
	if (!InsertOneDate(sUserName, nUserId))
	{
		cout << "InsertOneDate失败" << endl;
		return false;
	}
	//在把原来的删除
	if (!DeleteDate(nId))
	{
		cout << "DeleteDate失败" << endl;
		return false;
	}

	return true;
}


void Select::DrawInit()
{
	cout << "========" << "欢迎来到电话薄操作" << "========" << endl;
	//封装一个.cpp文件
	cout << "一:显示所有数据。" << endl;
	cout << "二:查询联系人" << endl;
	cout << "三:增加联系人。" << endl;
	cout << "四:修改联系人。" << endl;
	cout << "五:删除联系人。" << endl;
	cout << "六:随机拨打任意联系人。" << endl;
	cout << "七:退出程序。" << endl;
	cout << "请选择操作:" << endl;

}

//void Select::CallAnyName()
//{
//}

void Select::DrawHead()
{
	cout << "用户序号" << setw(6) << " ";
	cout << "用户ID" << setw(4) << " ";
	cout << "用户名称" << setw(6) << "  ";
	cout << "文件偏移" << endl;
}
int Select::IdEmptyFill(int Id)
{
	int nCount = 0;
	while (Id > 9) {
		Id = Id / 10;  // 整数除法,相当于取整除
		nCount++;
	}
	return nCount;
}

	bool Select::GetFlg()
	{
		return m_flg;
	}

	bool Select::ReDEFile(const char* old_filename, const char* new_filename)
	{
		return m_pFile->ReDeFileName(old_filename, new_filename,m_pcMyStu);
	}

Select::~Select()
{
	delete m_pcMyStu;
	delete m_pFile;
}

MyIterator

MyIterator.h

#pragma once
#include "ClassStu.h"

class MyIterator
{

public:

	/*******************构造函数系列开始***********************/
/*
	* MyIterator
	* 参数一 :无
	* 功能   :初始化类成员
	* 返回值 :无

*/
	MyIterator();
	
	/*
		* MyIterator
		* 参数一 :ClassStu** 数据成员的指针
		* 参数二 :当前指向ClassStu* 成员索引
		* 参数三 :成员的个数
		* 功能   :使用类来管理指针,使数组更安全的遍历
		* 返回值 :无

	*/
	MyIterator(ClassStu** cStuStart, int nIndex,int nMax);

	

	/*
		* MyIterator
		* 参数一 :MyIterator&
		* 功能   :默认构造 浅拷贝
		* 返回值 :无

	*/




	/*******************构造函数系列结束***********************/


	/*******************运算符重载函数系列结开始***********************/

/*
	* operator*
	* 参数一 :无
	* 功能   :返回当前用户信息
	* 返回值 :ClassStu&

*/

	ClassStu& operator*();

	/*
		* operator++
		* 参数一 :无
		* 功能   :数组往前移动一位
		* 返回值 :ClassStu& 引用

	*/

	MyIterator& operator++();

	/*
		* operator--
		* 参数一 :无
		* 功能   :数组往前移动一位
		* 返回值 :MyIterator& 引用

	*/

	MyIterator& operator--();


	/*
		* operator !=(MyIterator Iterator)
		* 参数一 :MyIterator
		* 功能   :用来判断begin 和end   迭代使用
		* 返回值 :MyIterator& 引用

	*/

	bool operator !=(MyIterator Iterator);


/*
	* operator ==(MyIterator Iterator)
	* 参数一 :MyIterator
	* 功能   :用来判断begin 和end   迭代使用
	* 返回值 :MyIterator& 引用

*/

	bool operator ==(void* pVoid);

	/*******************运算符重载函数系列结结束***********************/
private:
	ClassStu** m_cStuStart;
	int m_nIndex;//指向成员的索引值
	int m_nMax;//最成员的个数
};


MyIterator.cpp

#include "MyIterator.h"

MyIterator::MyIterator()
{
	m_cStuStart = nullptr;
	m_nIndex = 0;
	m_nMax = 0;
}

MyIterator::MyIterator(ClassStu** cStuStart, int nIndex,int nMax)
{
	m_cStuStart = cStuStart;
	m_nIndex = nIndex;
	m_nMax = nMax;
}

ClassStu& MyIterator::operator*()
{
	return **m_cStuStart;
}

MyIterator& MyIterator::operator++()//这里有问题
{
	
	if (m_nIndex == m_nMax)
	{
		m_nIndex++;
		return *this;
	}
	m_nIndex++;
	m_cStuStart++;
	return *this;
}
//
MyIterator& MyIterator::operator--()
{

	if (m_nIndex == 0)
	{
		return *this;
	}
	m_nIndex--;
	m_cStuStart--;
	return *this;
}
//
bool MyIterator::operator!=(MyIterator Iterator)
{
	if (m_nIndex == ((Iterator.m_nMax)))
	{
		return false;
	}
	return true;
}

bool MyIterator::operator==(void* pVoid)
{
	if (m_cStuStart == pVoid)
	{
		return true;
	}
	return false;
}

VetorCstu

VetorCstu.h

#pragma once
#include "ClassStu.h"
#include "MyIterator.h"

class VetorCstu
{
public:
	/*******************构造函数系列开始***********************/
/*
	* VetorCstu
	* 参数一 :无
	* 功能   :初始化类成员,默认构造30个
	* 返回值 :无

*/
    VetorCstu(int InitNumber = 0);
/*
	* VetorCstu
	* 参数一 :无
	* 功能   :析构函数  释放堆空间资源
	* 返回值 :无

*/

	~VetorCstu();

	/*******************构造函数系列结束***********************/


	/*******************增删改查函数系列开始***********************/


/*
* Insert
* 参数一 :int 插入的位置
* 参数二 :ClassStu*
* 功能   : 数组中指定位置插入一个成员
* 返回值 :bool

*/
	bool Insert(int nPos,ClassStu* cStu);

/*
	* push_back
	* 参数一 :ClassStu*
	* 功能   :数组中尾部插入一个成员
	* 返回值 :无  

*/
	void push_back(ClassStu* cStu);

/*
	* Insert
	* 参数一 :int nCount
	* 功能   :数组成员实例化ClassStu->nCount个
	* 返回值 :无

*/
	void Insert(int nCount);
/*
	* push_front
	* 参数一 :ClassStu*
	* 功能   :数组首部插入一个成员
	* 返回值 :无

*/
	void push_front(ClassStu* cStu);
/*
	* Erase
	* 参数一 :int  数组的索引值
	* 功能   :数组中删除指定成员 --- 老式删除方法:从数组中移除      另一种删除软删除方法成员属性ClassStu->m_id 改为0
	* 返回值 :bool

*/
	void Erase(int nPos);


/*
	* pop_back
	* 参数一 :无
	* 功能   :删除数组最后一个成员
	* 返回值 :无

*/
	void pop_back();

/*
	* Front
	* 参数一 :无
	* 功能   :访问第一个数组成员
	* 返回值 :ClassStu&

*/
	ClassStu& Front();


/*
	* Front
	* 参数一 :无
	* 功能   :访问最后一个数组成员
	* 返回值 :ClassStu&

*/
	ClassStu& Back();


/*
	* Find
	* 参数一 :int
	* 功能   :通过用户m_Id查找到用户信息
	* 返回值 :MyIterator

*/
	MyIterator Find(int nUserId);


	/*******************增删改查函数系列结束***********************/


	/*******************检查访问数组类开始***********************/
/*
	* IsEmpty
	* 参数一 :无
	* 功能   :检查容器是否为空
	* 返回值 :bool   不为0 返回真

*/
	bool IsEmpty();


/*
	* IsFind
	* 参数一 :int
	* 功能   :通过用户Id返回在数组中的索引
	* 返回值 :int   返回用户的索引,没有返回-1

*/
	int IsFind(int nUserId);

	/*
	* size
	* 参数一 :无
	* 功能   :返回成员个数
	* 返回值 :int

*/
	int Size();



/*
	* GetMaxUserId
	* 参数一:无
	* 功能  : 获取用户最大的UserId号
	* 返回值 :int  返回用户最大UserId号
	*
*/
	int GetMaxUserId();

	/*******************检查访问数组类结束***********************/


	/********************friend函数**Iterator迭代器********************/



/*
	* Begin
	* 参数一 :无
	* 功能   :数据首个元素 迭代器返回自定义MyIterator,来操作数据
	* 返回值 :无

*/
	MyIterator begin()  //return构造可以返回同等类型
	{
		return MyIterator(m_cStu, 0, m_nCount);
	}
/*
	* Begin
	* 参数一 :int  成员索引
	* 功能   :数据+ nIndex元素 ,来操作数据
	* 返回值 :无

*/
	MyIterator begin(int nIndex)  //return构造可以返回同等类型
	{
		return MyIterator(m_cStu+ nIndex, nIndex, m_nCount);
	}
/*
	* End
	* 参数一 :无
	* 功能   :数据最后一个元素 迭代器返回自定义MyIterator,来操作数据
	* 返回值 :无

*/
	MyIterator end()
	{
		return MyIterator(m_cStu, m_nCount, m_nCount);
	}
/*
	* EmptyItr
	* 参数一 :无
	* 功能   :迭代器Itr赋值为空
	* 返回值 :无

*/
	MyIterator EmptyItr()
	{
		return MyIterator(nullptr, 0, 0);
	}
	/********************friend函数**Iterator迭代器****结束***************/



	/********************运算符重载系列开始********************/
/*
	* ClassStu& operator[](int nIndex)
	* 参数一 :数组成员索引
	* 功能   :实现可以取出每个成员用户信息
	* 返回值 :无
*/

	ClassStu& operator[](int nIndex)
	{
		if (nIndex<0 || nIndex >= m_nSumCount)
		{
			//这里应该报错,超出了边界
			return *m_cStu[m_nSumCount];
		}

		return *m_cStu[nIndex];
	}

	/********************运算符重载系列结束********************/






	/********************数据排序开始****************************/
/*
	* BubbleSort
	* 参数一 :无
	* 功能   :冒泡排序法
	* 返回值 :无
*/
	void BubbleSort();

//
选择性--排序法
//void Select::SelectionSort()
//{
//	ClassStu* pTmpMin = new ClassStu;
//	int nMinIndex = 0;
//	for (int i = 0; i < m_nCount - 1; i++)
//	{
//		//保存堆数组的第一个元素
//		nMinIndex = i;
//		for (int k = i + 1; k < m_nCount; k++)
//		{
//			if (m_pSelePhone[nMinIndex].m_Id < m_pSelePhone[k].m_Id)
//			{
//				nMinIndex = k;
//			}
//		}
//		//这里做交换的值;把索引i存起来
//		memcpy_s(pTmpMin, sizeof(ClassStu), &m_pSelePhone[i], sizeof(ClassStu));
//		//把最小的放到I中
//		memcpy_s(&m_pSelePhone[i], sizeof(ClassStu), &m_pSelePhone[nMinIndex], sizeof(ClassStu));
//		//把I放到值放到nMinIndex中
//		memcpy_s(&m_pSelePhone[nMinIndex], sizeof(ClassStu), pTmpMin, sizeof(ClassStu));
//
//	}
//	//释放临时变量空间
//	delete pTmpMin;
//}
//
插入排序法
//void Select::InsertSort()
//{
//	ClassStu* pTmpMin = new ClassStu;
//	int j = 0;
//	for (int i = 1; i < m_nCount; i++)
//	{
//		//赋值给临时变量
//		memcpy_s(pTmpMin, sizeof(ClassStu), m_pSelePhone + i, sizeof(ClassStu));
//		j = i - 1;
//
//		while (j >= 0 && m_pSelePhone[j].m_Id > pTmpMin->m_Id)
//		{
//			memcpy_s(m_pSelePhone + j + 1, sizeof(ClassStu), m_pSelePhone + j, sizeof(ClassStu));
//			j = j - 1;
//		}
//
//		memcpy_s(m_pSelePhone + j + 1, sizeof(ClassStu), pTmpMin, sizeof(ClassStu));
//
//	}
//
//}



	/********************数据排序结束****************************/


	/********************获取成员数据****************************/






private:
	ClassStu** m_cStu;
    int m_nCount;//当前有new了多少个ClassStu*类
	int m_nSumCount;//容量总大小
	int m_nStep = 10;//每次增加10
	
};


VetorCstu.cpp

#include "VetorCstu.h"

VetorCstu::VetorCstu(int InitNumber)
{
	m_nCount = 0;
	m_nSumCount = InitNumber + m_nStep;
	m_cStu = new ClassStu*[m_nSumCount];//初始化了ClassStu*数组

}

VetorCstu::~VetorCstu()
{
	if (m_cStu != nullptr)
	{

		//要先析构*m_cStu里面的成员
		//析构要判断数组里面存在的指针是否重复,重复的只释放一次
		ClassStu** cStu = m_cStu;

		for (int i = 0; i < m_nCount; i++)
		{
			delete *cStu;
			cStu++;
		}

		delete[] m_cStu;
	}

}

bool VetorCstu::Insert(int nPos,ClassStu* cStu)
{
	//越界判断
	if (nPos < 0)
	{
		return false;
	}
	//指针判断
	if (cStu == nullptr)
	{
		return false;
	}
	//容器满了,需要扩容
	if (m_nCount == m_nSumCount)//要重新申请内存
	{
		m_nSumCount = m_nCount + m_nStep;
		//申请新的空间
		ClassStu** cStu = m_cStu;
		m_cStu = new ClassStu*[m_nSumCount];
		//把原来的数据全部移动的新的空间里面
		memcpy_s(m_cStu, m_nSumCount * 4, cStu, m_nCount*4);
		//这里要删除cStu  //但是删除会里面
		delete[] cStu;
	}
	//插入位置判断  头部、中间  尾部  
	// 头部、中间 需要计算向后移动多少位置
	if (nPos != m_nCount)
	{
		//计算后面还有多少个数
		int nSize = (m_nCount - nPos) * 4;
	  memcpy_s(m_cStu + nPos + 1, m_nCount * 4, m_cStu + nPos, nSize);
	}

	m_cStu[nPos] = cStu;

	m_nCount++;
	return true;
}
void VetorCstu::push_back(ClassStu* cStu)
{
	//Insert里面 有判断cStu是否为空
	Insert(m_nCount, cStu);
}
void VetorCstu::Insert(int nCount)
{
	for (int i = 0; i < nCount; i++)
	{
		ClassStu* cStu = new ClassStu;
		push_back(cStu);
	}
}
void VetorCstu::push_front(ClassStu* cStu)
{
	//Insert里面 有判断cStu是否为空
	Insert(0, cStu);
}
void VetorCstu::Erase(int nPos)
{
	//1:先判断nPos删除的位置
	if (nPos < 0 || nPos >= m_nCount)
	{
		return;
	}
	//2: 释放指针下的内存空间
	delete *(m_cStu + nPos);

	//3:计算后面还有多少个数,进行移动位置
	if ((m_nCount - 1) != nPos)
	{
	int nSize = (m_nCount - nPos - 1) * 4;
	memcpy_s(m_cStu + nPos, m_nCount * 4, m_cStu + nPos + 1, nSize);
	}
	m_cStu[m_nCount - 1] = 0;
	m_nCount--;
}

void VetorCstu::pop_back()
{
	Erase(m_nCount - 1);
}

ClassStu& VetorCstu::Front()
{
	if (m_nCount == 0)
	{
		cout << "数据成员为空:报错" << endl;

	}
	return *m_cStu[0];
}

ClassStu& VetorCstu::Back()
{
	if (m_nCount == 0)
	{
		cout << "数据成员为空:报错" << endl;

	}
	return *m_cStu[m_nCount -1];
}

MyIterator VetorCstu::Find(int nUserId)
{

	int nIndex = IsFind(nUserId);

	if (nIndex == -1)
	{
		return EmptyItr();
	}

	return this->begin(nIndex);
}



bool VetorCstu::IsEmpty()
{

	return m_nCount != 0;
}

int VetorCstu::IsFind(int nUserId)
{
	int nIndex = 0;
	for (auto Val : *this)
	{
		if (Val.m_Id == nUserId)
		{

			return nIndex;
		}

		nIndex++;

	}
	return -1;
}

int VetorCstu::Size()
{
	return m_nCount;
}

//
//
//
//bool VetorCstu::Delete(int nIndex)
//{
//	//判断索引nIndex是否越界
//	if (nIndex < 0 || nIndex > m_nCount)
//	{
//		return false;
//	}
//	//把学生类的成员Id置为0
//	m_cStu[nIndex]->m_Id = 0;
//	
//	return true;
//}
//

//
//MyIterator VetorCstu::FindCstu(int UserId)
//{
//
//	//首先判断userid
//	int MaxId = GetMaxUserId();
//	MaxId--;
//	if (UserId < 0 || UserId > MaxId)
//	{
//		return  MyIterator(nullptr, 0, 0);
//	}
//	int nIndex = Find(UserId);
//	if (nIndex == -1)//没有找到用户的UserId
//	{
//		return  MyIterator(nullptr, 0, 0);
//	}
//	return MyIterator(m_cStu + nIndex,m_nCount,nIndex);
//}
//
//
//
//
//
int VetorCstu::GetMaxUserId()
{

		//保存最大索引
	if (m_nCount == 0)
	{
		return 1;
	}
	int nMaxIndex = 0;

	//获取m_pSelePhone->Id的最大索引
	for (int k = 0; k < m_nCount - 1; k++)
	{
		if (m_cStu[k]->m_Id < m_cStu[k + 1]->m_Id)
		{
			nMaxIndex = k + 1;
		}
	}

	//返回最大的Id ++
	return m_cStu[nMaxIndex]->m_Id + 1;
}
//
void VetorCstu::BubbleSort()
{
	//先定义一个变量   这里交换不能用new
	ClassStu* cPtm = nullptr;
	//两层循环
	for (int i = 0; i < m_nCount - 1; i++)
	{
		//用第i和值和所有的都比较一遍
		for (int k = 0; k < m_nCount - i - 1; k++)
		{
			if (m_cStu[k]->m_Id > m_cStu[k + 1]->m_Id)//Id值比他大就交换到后面去
			{
				//先保存&m_pSelePhone[k]的内存
				cPtm = m_cStu[k];
				//把&m_pSelePhone[i]的数据保存到&m_pSelePhone[k]位置
				m_cStu[k] = m_cStu[k + 1];
				//把&m_pSelePhone[k]的数据保存到临时变量
				m_cStu[k + 1] = cPtm;
			}
		}

	}
}
//
//int VetorCstu::GetCount()
//{
//	return m_nCount;
//}

ClassStu

ClassStu.h

#pragma once
#include "ClassStr.h"
class ClassStu
{
public:
	/*******************构造函数系列开始***********************/
/*
	* ClassStu
	* 参数一 : int --学生Id
	* 参数二 : ClassStr字符串 --学生姓名
	* 参数三 : int --文件中的储存偏移
	* 功能   :默认构造,初始化类成员 --为空
	* 返回值 :无
*/
	ClassStu();

	/*
		* ClassStu(ClassStu& cStu)
		* 参数一 : ClassStu&
		* 功能   :默认构造,浅拷贝
		* 返回值 :无
	*/
	ClassStu(ClassStu& cStu);


/*
	* ClassStu
	* 参数一 : int --学生Id
	* 参数二 : ClassStr字符串 --学生姓名
	* 参数三 : int --文件中的储存偏移
	* 功能   :默认构造,初始化类成员 --为空
	* 返回值 :无
*/
	ClassStu(int Id, const char* Name, int FileOffset = 0);



/*
	* ClassStu(int Id, const char* Name, int FileOffset = 0)
	* 参数一 : int --学生Id
	* 参数二 : MyStr*字符串 --学生姓名
	* 参数三 : int --文件中的储存偏移
	* 功能   :默认构造,初始化类成员 --为空
	* 返回值 :无
*/
	ClassStu(int Id, MyStr* cStr, int FileOffset = 0);
/*
	* ClassStu
	* 无
	* 功能   :析构函数 --释放空间资源
	* 返回值 :无
*/
	~ClassStu();

	/*******************构造函数系列结束***********************/

	/*******************运算符重载***********************/


/*
	* operator=
	* 参数一 :ClassStu*
	* 功能   :=号运算符重载,浅拷贝
	* 返回值 :无
*/ 


	void operator=(ClassStu* cStu);

/*
	* operator=
	* 参数一 :ClassStu&
	* 功能   :=号运算符重载,浅拷贝
	* 返回值 :无
*/

	//void operator=(ClassStu cStu);

/*
	* operator=
	* 参数一 :ClassStu&
	* 功能   :=号运算符重载,浅拷贝
	* 返回值 :ClassStu&   可以连续=  a=b=c  注:当函数返回时就可以等了   
*/

	ClassStu& operator=(ClassStu& cStu);



/*
	* operator*
	* 参数一 :ClassStu
	* 功能   :*运算符重载,返回用户姓名缓存
	* 返回值 :char*
*/

	char* operator*();




/*
	* operator==
	* 参数一 :ClassStu
	* 功能   :判断是否为空类
	* 返回值 :char*
*/

	bool operator== (void* pVoid);

	/*******************获取类成员***********************/
/*
	* IsEmpty()
	* 参数一 :无
	* 功能   :判断是否为空  m_StuName
	* 返回值 :bool  字符串不为空返回真 为空返回假
*/
	bool IsEmpty();

/*
	* InitClass()
	* 参数一 :无
	* 功能   :封装初始化成员函数
	* 返回值 :无
*/
	void InitClass();

/*
	* IsClear()
	* 参数一 :无
	* 功能   :清除自身
	* 返回值 :无
*/
	void IsClear();
	/*******************获取类成员结束***********************/

	/*******************序列化***********************/

	bool Serialize(FILE* pFile);//序列化--从内存写入文件

	bool Deserialize(FILE* pFile);//反序列化--从文件读到内存

	/*******************序列化***********************/
//类成员信息公开
public:
	int m_Id; //ID
	MyStr* m_StuName;//用户名称
	int m_FileOffset;//存在文件的偏移

	int* m_nIndex;
};


ClassStu.cpp

#include "ClassStu.h"

ClassStu::ClassStu()
{
	InitClass();

}


ClassStu::ClassStu(ClassStu& cStu)
{
	if (cStu == nullptr || cStu.m_StuName == m_StuName)
	{
		InitClass();
		return;
	}

	if (cStu.m_nIndex == nullptr)
	{
		//引用技术
		cStu.m_nIndex = new int(0);
	}

	m_Id = cStu.m_Id;
	m_FileOffset = cStu.m_FileOffset;
	m_StuName = cStu.m_StuName;
	m_nIndex = cStu.m_nIndex;
	(*m_nIndex)++;

}

ClassStu::ClassStu(int Id, const char* Name, int FileOffset)
{
	if (Name == nullptr)
	{
		InitClass();
		return;
	}
	m_StuName = new MyStr(Name);
	m_nIndex = new int(0);
	m_Id = Id;
	m_FileOffset = FileOffset;

}

ClassStu::ClassStu(int Id, MyStr* cStr, int FileOffset)
{
	if (cStr == nullptr)
	{
		InitClass();
		return;
	}
	m_StuName = cStr;
	m_nIndex = new int(0);
	m_Id = Id;
	m_FileOffset = FileOffset;


}

ClassStu::~ClassStu()
{
	IsClear();
}

void ClassStu::operator=(ClassStu* cStu)
{

	if (cStu == nullptr || cStu->m_StuName == m_StuName)
	{
		InitClass();
		return;
	}

	if (cStu->m_nIndex == nullptr)
	{
		//引用技术
		cStu->m_nIndex = new int(0);
	}

	//先清除自身
	IsClear();
	m_Id = cStu->m_Id;
	m_FileOffset = cStu->m_FileOffset;
	m_StuName = cStu->m_StuName;

	m_nIndex = cStu->m_nIndex;
	(*m_nIndex)++;
}

ClassStu& ClassStu::operator=(ClassStu& cStu)
{

	if (cStu == nullptr || cStu.m_StuName == m_StuName)
	{
		return *this;
	}

	if (cStu.m_nIndex == nullptr)
	{
		//引用技术
		cStu.m_nIndex = new int(0);
	}
	//先清除自身
	IsClear();
	m_Id = cStu.m_Id;
	m_FileOffset = cStu.m_FileOffset;
	m_StuName = cStu.m_StuName;
	m_nIndex = cStu.m_nIndex;
	(*m_nIndex)++;
	return *this;
}





char* ClassStu::operator*()
{
	return m_StuName->GetStr();
}

bool ClassStu::operator==(void* pVoid)
{
	if (this == nullptr)
	{
		return true;
	}
	return false;
}

bool ClassStu::IsEmpty()
{
	return m_StuName->GetStr() != nullptr;
}

void ClassStu::InitClass()
{

	m_StuName = nullptr;
	m_nIndex = nullptr;
	m_Id = 0;
	m_FileOffset = 0;

}

void ClassStu::IsClear()
{
	if (m_StuName == nullptr)
	{
		return;
	}
	if (*m_nIndex != 0)
	{
		(*m_nIndex)--;
		return;
	}

	cout << "m_StuName" << m_Id << endl;
	delete m_nIndex;
	delete m_StuName;
}

bool ClassStu::Serialize(FILE* pFile)
{
	//2:将文件偏移指向要写入的位置

	fseek(pFile, 0, SEEK_END);//移动到尾部开始写入

	//3.0 获取文件偏移,后面可以写入
	int FileOffset = ftell(pFile);
	m_FileOffset = FileOffset;

	if (FileOffset == -1L)
	{
		return false;
	}
	//3.1 先写入学生Id

	if (fwrite(&m_Id, 1, 4, pFile) != 4)
	{
		return false;
	}

	//3.2 再写入用户名称的字符串长度
	char nLen = m_StuName->GetLen();
	if (fwrite(&nLen, 1, 1, pFile) != 1)
	{
		return false;
	}
	//3.3 写入用户的姓名
	if (fwrite(m_StuName->GetStr(), 1, nLen, pFile) != nLen)
	{
		return false;
	}
	//3.4 写入文件偏移
	if (fwrite(&FileOffset, 1, 4, pFile) != 4)
	{
		return false;
	}


	return true;
}

bool ClassStu::Deserialize(FILE* pFile)
{

	//2.1 先读用户的ID
	if (fread(&m_Id, 1, 4, pFile) != 4)
	{
		return false;
	}
	//2.2 在读字符串的字节数
	char nLen = 0;
	if (fread(&nLen,1, 1, pFile) != 1)
	{
		return false;
	}
	//2.3 在读字符串
	m_StuName = new MyStr(nLen);
	if (fread(m_StuName->GetStr(), 1, nLen, pFile) != nLen)
	{
		return false;
	}

	//2.4 在读文件偏移
	if (fread(&m_FileOffset, 1, 4, pFile) != 4)
	{
		return false;
	}

	return true;

}

main源码

#include "Select.h"
#include <conio.h>

int main()
{
	//初始化;已经把文件数据读入内存中
	Select MySele2("mystudate.bin");
	int selectId = 0;	//保存操作的选择
	while (selectId != 7)
	{
		system("cls");
		//初始化界面
		MySele2.DrawInit();
		scanf_s("%d", &selectId);//获取用户的输入
		if (selectId < 0 || selectId > 7)
		{
			cout << "输入错误,请重新输入" << endl;
			continue;
		}

		switch (selectId)
		{
			case 1:
			{
				MySele2.SelectAllDate();//显示所有数据
			
				break;

			}
			case 2://查询单个联系人
			{
				
				int nUserId = 0;
				cout << "请输入用户Id:" << endl;
				scanf_s("%d",&nUserId);
				MySele2.FindOneDate(nUserId);
				break;
			}
			case 3://增加联系人
			{
				char sUserName[32] = { 0 };//保存用户的输入查找用户名
				memset(sUserName, 0, 32);
				cout << "请输入姓名:" << endl;
				//获取到用户输入的姓名
				scanf_s("%s", sUserName, 32);
				MySele2.InsertOneDate(sUserName);
				break;
			}
			case 4://修改联系人
			{
				char sUserName[32] = { 0 };//保存用户的输入查找用户名
				memset(sUserName, 0, 32);
				//先修改文件 :先把要修改的删除操作,在新增一项即可 ,序号
				int nId = 0;
				cout << "请输入要求改的用户序号" << endl;
				scanf_s("%d", &nId);
				//获取成员个数、 检测是否超出边界
				int nSize = MySele2.m_pcMyStu->Size();
				if (nId < 1 || nId > nSize)
				{
					cout << "删除失败" << endl;
					break;
				}

				cout << "请输入要修改的名字" << endl;
				scanf_s("%s", sUserName, 32);
				
				//修改数据
				MySele2.UpDate(sUserName, nId);
			

				break;
			}
			case 5://删除联系人
			{
			
				//填写用户ID
				cout << "请输入要删除的用户序号" << endl;
				int nIndex = 0;
				scanf_s("%d", &nIndex);

				int nSize = MySele2.m_pcMyStu->Size();
				if (nIndex < 1 || nIndex > nSize)
				{
					cout << "删除失败" << endl;
					break;
				}

				if (MySele2.DeleteDate(nIndex) == false)
				{
					cout << "删除失败" << endl;
				}

			}
		
		}

		system("pause");


	}
	//退出后,如果有删除 修改文件。则要重写文件
	if (MySele2.GetFlg())
	{
		//重新将内存数据写入文件
		MySele2.ReDEFile("mystudate.bin", "mystudate_old.bin");
	}
	return 0;

}


总结—数组管理指针

时间复杂度

  • 查看数据成员 —直接索引下标—o(1) 常量阶
  • 插入数据—需要移动数据–o(n)线性阶
  • 删除数据—需要移动数据–o(n)线性阶
  • 搜索数据—需要遍历–o(n)线性阶

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

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

相关文章

中科大计网学习记录笔记(五):协议层次和服务模型

前言&#xff1a; 学习视频&#xff1a;中科大郑烇、杨坚全套《计算机网络&#xff08;自顶向下方法 第7版&#xff0c;James F.Kurose&#xff0c;Keith W.Ross&#xff09;》课程 该视频是B站非常著名的计网学习视频&#xff0c;但相信很多朋友和我一样在听完前面的部分发现信…

2024.2.4日总结(小程序开发1)

小程序开发和普通网页开发的区别 运行环境不同 网页运行在浏览器环境中&#xff0c;小程序运行在微信环境中 API不同 由于运行的环境不同&#xff0c;所以小程序中无法调用DCM和BOM的API&#xff0c;但是可以调用微信环境提供的各种API&#xff0c;如&#xff1a;地理定位&…

MySQL学习记录——삼 库的操作

文章目录 1、创建数据库2、字符集和校验集3、基本操作4、备份与恢复5、连接情况 1、创建数据库 开两个窗口&#xff0c;一个用来访问数据目录/var/lib/mysql&#xff0c;一个用来打开mysql&#xff1a;mysql -u root -p。 创建用的命令 create databse d1; d1是名字&#xff…

【Java八股文面试系列】JVM-内存区域

目录 Java内存区域 运行时数据区域 线程独享区域 程序计数器 Java 虚拟机栈 StackFlowError&OOM 本地方法栈 线程共享区域 堆 GCR-分代回收算法 字符串常量池 方法区 运行时常量池 HotSpot 虚拟机对象探秘 对象的创建 对象的内存布局 句柄 Java内存区域 运…

BUG:docker启动之后直接退出问题

示例如下&#xff1a; 问题排查&#xff1a; 启动命令 sudo docker run --privilegedtrue --runtimenvidia --shm-size80g -v /mmm_data_center:/mmm_data_center -v /imagecenter_new/:/imagecenter_new -v /data1:/data1 -v /mnt/offline_data/:/mnt/offline_data/ --neth…

蓝桥杯---生日蜡烛

某君从某年开始每年都举办一次生日party&#xff0c;并且每次都要吹熄与年龄相同根数的蜡烛&#xff0c;现在算起来&#xff0c;他一共吹熄了236根蜡烛。请问,他从多少岁开始过生日party的? 请填写他开始过生日 party的年龄数。 注意:你提交的应该是一个整数&#xff0c;不要…

记elasticsearch CPU负载100%问题

记elasticsearch CPU负载100%问题 环境&#xff1a;问题表现&#xff1a;初步排查&#xff1a;日志查询hot_thread 深入查询当前elasticsearch正在运行的Task查看Task详情解决问题对导致问题的原因的几个猜测问题复现&#xff1a;导致问题的原因。json导入规则问题json导入规则…

ElementUI Form:Form表单

ElementUI安装与使用指南 Form表单 点击下载learnelementuispringboot项目源码 效果图 el-form.vue&#xff08;Form表单&#xff09;页面效果图 项目里 el-form.vue代码 <script> export default {name: el_form,data() {var checkAge (rule, value, callback…

2月4号作业

编写程序实现二叉树的创建&#xff0c;三种遍历自己销毁 #include <myhead.h>#define TRUE 1 #define FALSE 0 #define OVERFLOW -2 #define OK 1 #define ERROR 0#define INIT_SIZE 20 #define INCREMENT_SIZE 5typedef int Status; typedef int TElemType; //存储结构…

Linux权限【超详细】

&#x1f4d9; 作者简介 &#xff1a;RO-BERRY &#x1f4d7; 学习方向&#xff1a;致力于C、C、数据结构、TCP/IP、数据库等等一系列知识 &#x1f4d2; 日后方向 : 偏向于CPP开发以及大数据方向&#xff0c;欢迎各位关注&#xff0c;谢谢各位的支持 目录 扩展知识&#xff1a…

Linux项目自动化构建工具之make/Makefile演示gcc编译

文章目录 一、背景二、如何使用&#xff1f;三、原理四、关于make的问题五、再次理解/编写makefile依赖关系依赖方法 六、原理讲解项目清理makefile是支持变量的取消执行make后显示命令依赖方法可以多行 一、背景 会不会写makefile&#xff0c;从一个侧面说明了一个人是否具备…

C语言进阶之文件操作

一、什么是文件 磁盘上的文件是文件。 但是在程序设计中&#xff0c;我们一般谈的文件有两种&#xff1a;程序文件、数据文件&#xff08;从文件功能的角度来分类的&#xff09;。 1&#xff09;程序文件 包括源程序文件&#xff08;后缀为.c&#xff09;,目标文件&#xff…

VueFire:一个一流的 Vue 和 Firebase 体验,包括对 Nuxt 的支持,现在已经稳定了

VueFire&#xff0c;一个一流的 Vue 和 Firebase 体验 — 包括对 Nuxt 的支持&#xff0c;现在已经稳定了。 Vue 和 Firebase 现在比以往任何时候都更好了。 构建更好的VueFire 去年&#xff0c;我们宣布与 Eduardo San Martin Morote 合作&#xff0c;构建一个成熟的 Vue 和…

《数字乡村标准化白皮书(2024)》正式发布 智汇云舟参编

近日&#xff0c;全国信标委数字乡村标准研究组2023年度全体会议在北京召开。会议期间&#xff0c;智汇云舟参编的《数字乡村标准化白皮书&#xff08;2024&#xff09;》&#xff08;简称《白皮书》&#xff09;正式发布&#xff01; 发布仪式 白皮书研究背景 作为国家基础制…

交换机ARP学习异常,看网工大佬是如何处理的?

晚上好&#xff0c;我的网工朋友。 在复杂多变的网络环境中&#xff0c;网工就没有不遇到问题的&#xff0c;习惯了&#xff0c;兵来将挡水来土掩。 那ARP异常你遇到过吗&#xff1f;ARP作为网络中的基础协议之一&#xff0c;它的稳定性对整个网络的性能和可靠性至关重要。 …

【MongoDB】跨库跨表查询(python版)

MongoDB跨表跨库查询 1.数据准备&#xff1a;2.跨集合查询3.跨库查询应该怎么做&#xff1f; 讲一个简单的例子&#xff0c;python连接mongodb做跨表跨库查询的正确姿势 1.数据准备&#xff1a; use order_db; db.createCollection("orders"); db.orders.insertMan…

电路分析2

7 等效电路的思想&#xff0c;简化不是目的&#xff0c;这个电路说明一切&#xff01;_哔哩哔哩_bilibili 高中知识&#xff0c;翻笔记 8 什么时候用Y型&#xff1f;看到有有相同数字的时候&#xff0c;就可以考虑用 9 10 输入电阻还有没学完的 ok 11

海外多语言盲盒开发:打破语言障碍,连接全球消费者

随着全球化的加速和互联网的普及&#xff0c;语言障碍成为了影响跨国交流和商业活动的重要因素。为了满足跨国市场的需求&#xff0c;海外多语言盲盒开发成为了一个新兴的领域。本文将探讨海外多语言盲盒开发的意义、现状和未来发展。 一、海外多语言盲盒开发的意义 在全球化…

【C++】运算符重载详解

&#x1f497;个人主页&#x1f497; ⭐个人专栏——C学习⭐ &#x1f4ab;点击关注&#x1f929;一起学习C语言&#x1f4af;&#x1f4ab; 目录 导读 1. 为什么需要运算符重载 2. 运算符重载概念 3. 运算符重载示例 3.1 运算符重载 3.2 >或<运算符 4. 运算符重…

提前祝大家新年好!来看看社区 2023 都得了哪些奖吧

大噶好&#xff01;转眼马上就是“龙”历新年啦&#xff0c;不知道大家这周的工作热情怎么样呢&#xff1f;小陈的心已经在殷切期盼回家过年了&#xff5e; RTE 开发者社区预祝诸位&#xff1a; 2024 年 &#x1f432;龙年添财气&#xff0c;万事皆胜意&#xff01; 回顾过去…