用户管理信息--类指针数组
- 类示意图
- 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)线性阶