c++简单做一个文件变长储存
- 前言
- 源码
- 所有类头文件 .h
- ClassStu
- MyStr
- cFile
- 所有文件的实现源码.cpp
- classstu
- Mystr
- cFile
前言
-
用户信息写到文件是变长方式;
-
从文件上读取到内存,也是变长方式
-
用到了三个类;
** 用户信息类 ClassStu
** 自封装字符串类MyStr
** 文件类 -
源码如下
使用如下:
cFile MyFile("mydate.bin");//写入数据ClassStu* MyStu = new ClassStu(3,"shaguanaodai");MyFile.WriteFile(MyStu);//读取--显示文件的数据//先取个数MyFile--头四个字节放的是个数int nCount = MyFile.ReadFileHeader();//申请内存ClassStu* pStu = new ClassStu[nCount];memset(pStu, 0, sizeof(ClassStu) * nCount);MyFile.ReadFileAllDate(pStu, nCount);delete[] pStu;//释放空间return 0;
源码
所有类头文件 .h
ClassStu
#pragma once
#include "ClassStr.h"
class ClassStu
{
public:/*******************构造函数系列开始***********************/
/** ClassStu* 参数一 : int --学生Id* 参数二 : ClassStr字符串 --学生姓名* 参数三 : int --文件中的储存偏移* 功能 :默认构造,初始化类成员 --为空* 返回值 :无
*/ClassStu();/** ClassStu* 参数一 : int --学生Id* 参数二 : ClassStr字符串 --学生姓名* 参数三 : int --文件中的储存偏移* 功能 :默认构造,初始化类成员 --为空* 返回值 :无
*/ClassStu(int Id, const char* Name, int FileOffset = 0);
/** ClassStu* 无* 功能 :析构函数 --释放空间资源* 返回值 :无
*/~ClassStu();/*******************构造函数系列结束***********************//*******************获取类成员***********************///类成员信息公开
public:int m_Id; //IDMyStr* m_StuName;//用户名称int m_FileOffset;//存在文件的偏移
};
MyStr
#pragma once
#include <iostream>
using namespace std;/**/
class MyStr
{
public:
/*******************构造函数系列开始***********************/
/* * ClassStr* 参数一 : 无* 功能 :默认构造,初始化类成员 --为空* 返回值 :无
*/MyStr();/** ClassStr(const char* Str)* 参数一 : 字符串指针* 功能 :带参构造,初始化类成员--初始化字符串* 返回值 :无
*/MyStr(const char* Str);/** ClassStr(int nNumber)* 参数一 : 整形* 功能 :带参构造,初始化类成员--初始化字符串* 返回值 :无
*/MyStr(int nNumber);/** ClassStr(char nLen)* 参数一 :char* 功能 :初始化一块指定大小的内存;* 返回值 :无
*/MyStr(char nLen);/** ClassStr(ClassStr& cStr)* 参数一 : 类引用* 功能 :浅拷贝,当类相等的时候调用* 返回值 :无
*/MyStr(MyStr& cStr);//字符串设置为浅拷贝,字符串指向同一块内存,增加一个引用计数/** ~ClassStr* 参数一 : 无* 功能 :析构函数,释放类成员堆栈资源* 返回值 :无
*/~MyStr();
/*******************构造函数系列结束***********************//*******************运算符重载系列开始***********************/
/** operator=* 参数一 :类引用* 功能 :=号运算符重载* 返回值 :无*/void operator= (MyStr& cStr);// =号运算符重载/** operator=* 参数一 :类引用* 功能 :=号运算符重载* 返回值 :无*/void operator= (const char* cStr);// =号运算符重载
/** operator=* 参数一 : 整形* 功能 :=号运算符重载* 返回值 :无
*/void operator= (int nNumber);// =号运算符重载/** operator+* 参数一 : 整形* 功能 :+号运算符重载* 返回值 :无
*/int operator+ (int nNumber);// =号运算符重载/** operator-* 参数一 : 整形* 功能 :+号运算符重载* 返回值 :无
*/int operator- (int nNumber);// =号运算符重载/** operator[]* 参数一 : 整形* 功能 :修改字符串索引值* 返回值 :无* 实现类可以直接[]修改值* ClassStr cStr = "wooaoaoa0ao";* cStr[3] = 'b';
*/char& operator[] (int nIndex);// =号运算符重载
/*******************运算符重载系列结束***********************//*******************获取类成员系列开始***********************/
/** GetStr* 参数一 : 无* 功能 :返回m_str字符串* 返回值 :char*
*/char* GetStr();/** GetLen* 参数一 : 无* 功能 :返回m_str字符串* 返回值 :char*
*/int GetLen();/*******************获取类成员系列结束***********************//* 增删改查系列查这里开始*//*******************字符串增加功能开始***********************/
/** Insert* 参数一 : int 插入位置* 参数二 :const char* 插入字符串* 功能 :往字符串里面插入字符* 返回值 :char*
*/MyStr& Insert(int nPosition,const char* str);
/** FrontInsert* 参数一 : 无* 功能 :往字符串头部插入字符* 返回值 :void
*/void FrontInsert(const char* str);/** TailInsert* 参数一 : 无* 功能 :往字符串尾部插入字符* 返回值 :void
*/void TailInsert(const char* str);/*******************字符串插入功能结束***********************//*******************字符串删除功能开始***********************/
/** Delete* 参数一 : int 索引* 参数二 : int 删除数量* 功能 :往字符串尾部插入字符* 返回值 :ClassStr&
*/MyStr& Delete(int nIndex,int nCount);/*******************字符串删除功能结束***********************//*******************字符串查找功能开始***********************/
/** HeadFind* 参数一 : const char* str* 功能 :首部开始查找字符串* 返回值 :返回索引,失败返回-1;*/int HeadFind(const char* str);/** TailFind* 参数一 : const char* str* 功能 :尾部开始查找字符串* 返回值 :返回索引,失败返回-1;*/int TailFind(const char* str);
/** HeadFindCount* 参数一 : const char* str* 功能 :首部开始查找字符串,返回该字符串出现过的次数* 返回值 :int 返回次数;一次未出现过返回0直接调用了IsCmpContinuesHead函数来判断是否为-1 ,效率上会低点,可以优化;
*/int HeadFindCount(const char* str);/*******************字符串查找功能结束***********************//*******************字符串修改功能开始***********************//** Modify* 参数一 : const char* str nStr:字符串中需要被修改的字符* 参数二 : const char* str :改变成这个字符串* 参数三 : bool :是所有替换,还是只替换一次 false一次 true 所有替换* 功能 :字符串修改替换* 返回值 :int 成功返回修改次数 如果一次都没替换返回-2*/int Modify(const char* nStr,const char* cStr,bool bmp = false);/*******************字符串修改功能结束***********************//*******************字符串删除功能开始***********************///删除功能如果做的话 需要重新重构类成员,要填写 start 和end 来记录字符串的起始和结束位置; //我只做这个小型字符串 平时的修改的小功能
/*******************字符串删除功能结束***********************//* 增删改查系列查这里结束*//*******************内部小功能函数系列开始***********************/
private://类内部调用函数/** NumberCount* 参数一 : int --整数* 功能 :得到这个整数有多少个* 返回值 :整数的个数
*/int NumberCount(int nNumber);
/** GetDivNum* 参数一 : int --整数的个数* 功能 :求出一个10 100 1000 10000* 返回值 :int
*/int GetDivNum(int NumberCount);/** IsStr* 参数一 :无* 功能 :检测初始化m_Str是否为空;如果NEW申请失败就会返回nullptr* 返回值 :bool
*/bool IsStr();/** IsPnCount()* 参数一 :无* 功能 :检测初始化m_p_nCount是否为空;如果NEW申请失败就会返回nullptr* 返回值 :bool
*/bool IsPnCount();/** FreeSpace()* 参数一 :无* 功能 :检测初始化m_p_nCount是否为空;如果NEW申请失败就会返回nullptr* 返回值 :bool
*/void FreeSpace();
/** InitNumber()* 参数一 :无* 功能 :用户构造整数初始化和=号整数重载运算* 返回值 :bool
*/void InitNumber(int nNumber);/** InitSpace()* 参数一 :无* 功能 :初始化一块指定大小的内存空间* 返回值 :bool
*/void InitSpace(char nLen);/** StrToNumber* 参数一 :无* 功能 :把类成员m_Str字符串转化为数字返回;* 返回值 :int
*/int StrToNumber();/** FrontInsert* 参数一 :源地址;缓存地址* 参数二 :缓存大小* 参数三 : 目标地址;拷贝的地址* 参数四 :需要拷贝多少个字节* 功能 :前排插入* 返回值 :void
*/void FrontInsert(char* NewStr, int nSumLen, const char* str, int nLen);/** TailInsert* 参数一 :源地址;缓存地址* 参数二 :缓存大小* 参数三 : 目标地址;拷贝的地址* 参数四 :需要拷贝多少个字节* 功能 :尾部插入* 返回值 :void
*/void TailInsert(char* NewStr, int nSumLen, const char* str, int nLen);/** MiddleInsert* 参数一 :源地址;缓存地址* 参数二 :缓存大小* 参数三 : 目标地址;拷贝的地址* 参数四 :需要拷贝多少个字节* 参数五 :插入的位置* 功能 :中间插入一个字符串* 返回值 :void
*/void MiddleInsert(char* NewStr, int nSumLen, const char* str, int nLen,int nPosition);/** IsCmpByte(char chByte)* 参数一 :char 字节* 功能 :查字符串里面是否包含这个字节* 返回值 :int ---返回查找到的字符串位置索引
*/int IsCmpByteHead(char chByte,int nIndex);/** IsCmpByte(char chByte)* 参数一 :char 字节* 功能 :查字符里面是否出现过这个字节* 返回值 :int ---返回查找到的字符串位置索引
*/int IsCmpByteTail(char chByte, int nIndex);/*
* * IsCmpByteContinues(const char* str, int nLen,int nIndex)* 参数一 :const char* str 需要对比的字符串* 参数二 :int str长度* 参数三 :int nIndex m_Str索引* 参数四 :int nIn str的索引* 功能 :给定目标和源目标索引,连续对比每一个字节是否匹配* 返回值 :int ---返回查找到的字符串位置索引
*/bool IsCmpByteContinues(const char* str, int nLen, int nIndex, int nIn);
/*
* * IsCmpContinuesHead(char chByte) 正向查找* 参数一 :const char* str * 参数二 :int nLen字符串长度 * 参数三 :int nIndex m_Str索引 * 功能 :查字符里面是否出现过这个字节* 返回值 :int ---返回查找到的字符串位置索引
*/int IsCmpContinuesHead(const char* str, int nLen, int nIndex);/** IsCmpContinuesTail(char chByte) 反向查找* 参数一 :const char* str * 参数二 :int nLen字符串长度* 参数三 :int nIndex m_Str索引* 参数四 :TailIndex 判断对比到时候退出* 功能 :查字符里面是否出现过这个字节* 返回值 :int ---返回查找到的字符串位置索引
*/int IsCmpContinuesTail(const char* str, int nLen, int nIndex);
/**Replace(const char* cStr,int nIndex) * 参数一 :const char* str 替换的字符串* 参数二 :nIndex this字符串的索引* 功能 :替换字符串* 返回值 :无
*/void Replace(const char* cStr,int nIndex);/*******************内部小功能函数系列结束***********************/private://类成员以m_开头定义int m_nCount;//记录字符串的个数char* m_Str;//字符串指针int* m_p_nCount;//记录有多少个指针指向它;};
cFile
#pragma once
#include <iostream>
#include "ClassStr.h"
#include "ClassStu.h"
using namespace std;/*
*
* 明天测试一下文件类 -- 完成
* 删除和改名文件-- 完成
* 字符串类加入进来测试 --
*
* 有想一起学习c++的,,一起努力坚持下去:加入(q) :553235560
*/class cFile
{
public:enum FileType { WRITEERR = -3, READERR, PNULL , SUCCESS = 1 };
public:/*******************默认构造系列开始*************************/
/** cFile* 参数一 : 无* 功能 :默认构造,初始化类成员 --为空* 返回值 :无
*/cFile();/** cFile(const char* FileName,const char* Mode)* 参数一 : const char* FileName --文件的目录地址* 功能 :默认构造打开文件,初始化类成员* 返回值 :无
*/cFile(const char* FileName);/** cFile(cFile& fFile)* 参数一 : 无* 功能 :默认构造,初始化类成员 --为空* 返回值 :无
*/cFile(const cFile& fFile);/** ~cFile()* 参数 :无* 功能 :释放类资源* 返回值 :无
*/~cFile();/*******************默认构造系列结束*************************//*******************文件读系列开始*************************//** ReadFileHeader(int* nCount)* 参数一 :无* 功能 :获取文件首四个字节 为用户个数* 返回值 :成功返回个数,失败返回-1
*/int ReadFileHeader();
/** ReadFile(void* buffer,int FileOffset = 0)* 参数一 :void* buffer 读出数据放入的缓冲区* 功能 :从文件中读取数据放入缓冲区中* 返回值 :FileType
*/FileType ReadFileAllDate(ClassStu* pStudent,int nCount);/*******************文件读系列结束*************************//*******************文件写系列开始*************************//** WriteFile()* 参数一 :const void* buffer 要写入的字符串* 功能 :检查m_pFile是否为nullptr. 文件是否打开成功* 返回值 :FileType
*/int WriteFile(ClassStu* pStudent,int FileOffset = 0);/*******************文件写系列结束*************************//** UpDateHeader(bool bTmp);* 参数一 :bool ;默认是true 代表头部四个字节加1 flase 代表头部减1* 功能 : 用户个数的加减操作* 返回值 :FileType
*/FileType UpDateHeader(bool bTmp = true);/*******************内部调用函数系列*************************//** ReFileName(const char* old_filename, const char* new_filename)* 参数一 :const char* old_filename 要修改的文件路径和名字* 参数一 :const char* new_filename 文件的新名* 功能 :修改文件名* 返回值 :int 成功返回0 错误非0值
*/int ReFileName(const char* old_filename, const char* new_filename);/** DeleteFile(const char* FileName)* 参数一 :const char* FileName 当前文件下的文件名* 功能 :删除文件* 返回值 :int类型 成功返回0 错误非0值
*/int DeleteFile(const char* FileName);private:
/** CloseFile()* 参数 :无* 功能 :关闭文件* 返回值 :无
*/void CloseFile();/** ~IsOpen()* 参数 :无* 功能 :检查m_pFile是否为nullptr. 文件是否打开成功* 返回值 :bool
*/bool IsOpen();/** WriteFileDate(void* buffer,int nSize)* 参数一 :void* buffer 要写入文件的字符串缓冲区* 参数二 : int nSize 要写入多少个字节* 功能 :封装文件fwrite函数;使用起来更加方便* 返回值 :FileType
*/FileType WriteFileDate(void* buffer, int nSize);/** ReadFileDate(void* buffer,int nSize)* 参数一 :void* buffer 读出数据放入的缓冲区* 参数二 : int nSize 要从文件中读多少个字节* 功能 :封装文件fread函数;使用起来更加方便* 返回值 :FileType
*/FileType ReadFileDate(void* buffer, int nSize);private:FILE* m_pFile;//文件指针int* m_nCount;//引用技术,记录被赋值次数};
所有文件的实现源码.cpp
classstu
#include "ClassStu.h"ClassStu::ClassStu()
{m_StuName = nullptr;m_Id = 0;m_FileOffset = 0;}ClassStu::ClassStu(int Id, const char* Name, int FileOffset)
{if (Name == nullptr){return;}m_StuName = new MyStr(Name);m_Id = Id;m_FileOffset = FileOffset;
}ClassStu::~ClassStu()
{if (m_StuName != nullptr){delete m_StuName;//释放字符串空间}}
Mystr
#include "ClassStr.h"MyStr::MyStr()
{m_nCount = 0;m_Str = nullptr;m_p_nCount = new int(0);
}MyStr::MyStr(const char* Str)
{//先求传入字符串的长度 strlen长度为字符串,不包含/0;if (Str == nullptr){return;}int nLen = strlen(Str);//在申请空间m_nCount = nLen + 1;m_Str = new char[m_nCount];m_p_nCount = new int(0);if (!IsStr()){cout << "str内存初始化失败" << endl;}else{//申请的地址初始化为0memset(m_Str, 0, m_nCount);//在传入的地址进行拷贝操作memcpy_s(m_Str, nLen, Str, nLen);}}MyStr::MyStr(int nNumber)
{FreeSpace();//先求出整形有几位 NumberCount返回整形有几位数字;InitNumber(nNumber);
}MyStr::MyStr(char chNumber)
{InitSpace(chNumber);
}MyStr::MyStr(MyStr& cStr)
{m_nCount = cStr.m_nCount;m_Str = cStr.m_Str;m_p_nCount = cStr.m_p_nCount;if (m_p_nCount != nullptr){(*m_p_nCount)++;}
}void MyStr::operator=(MyStr& cStr)
{//先清除自身FreeSpace();m_Str = cStr.m_Str;m_nCount = cStr.m_nCount;m_p_nCount = cStr.m_p_nCount;(*m_p_nCount)++;}void MyStr::operator=(const char* cStr)
{if (cStr == nullptr){return;}int nLen = strlen(cStr);//在申请空间m_nCount = nLen + 1;m_Str = new char[m_nCount];if (m_Str == nullptr){cout<<"初始化字符串失败"<<endl;return;}m_p_nCount = new int(0);//申请的地址初始化为0memset(m_Str, 0, m_nCount);//在传入的地址进行拷贝操作memcpy_s(m_Str, nLen, cStr, nLen);
}void MyStr::operator=(int nLen)
{//等号的时候做出初始化if (nLen <= 0){cout << "nNumber初始化字符串长度不能为0" << endl;return;}m_nCount = nLen + 1;m_p_nCount = new int(0);m_Str = new char[m_nCount];if (!IsStr()){cout << "m_Str:申请内存空间失败" << endl;return;}}int MyStr::operator+(int nNumber)
{//先把字符串转化为数字int nTmp = StrToNumber();nTmp = nTmp + nNumber;return nTmp;
}int MyStr::operator-(int nNumber)
{int nTmp = StrToNumber();nTmp = nTmp - nNumber;return nTmp;
}char& MyStr::operator[](int nIndex)
{char* ch = nullptr;if (nIndex < 0 || nIndex> m_nCount){return *ch;}return m_Str[nIndex];
}MyStr::~MyStr()
{//判断引用计数是否为0if (*m_p_nCount != 0){(*m_p_nCount)--;}else //释放内存空间{delete[] m_Str;delete m_p_nCount;}
}char* MyStr::GetStr()
{return m_Str;
}int MyStr::GetLen(){return m_nCount -1;}MyStr& MyStr::Insert(int nPosition, const char* str)
{if (0 > nPosition || nPosition > m_nCount || str == NULL){cout << "插入错误:请选择正确的位置或str指针为NULL" << endl;return *this;}int nLen = strlen(str);//字符串的长度int nSumLen = nLen + m_nCount;char* NewStr = new char[nSumLen];//字符串申请总长度if (NewStr == nullptr){cout << "内存申请失败" << endl;return *this;}memset(NewStr,0,nSumLen);//申请的内存设置为0//可以分为插入头部 尾部 还有是中部if (nPosition == 0)//头部处理{FrontInsert(NewStr, nSumLen, str, nLen);}else if (nPosition == m_nCount)//尾部处理{TailInsert(NewStr, nSumLen, str, nLen);}else//中部{MiddleInsert(NewStr, nSumLen, str, nLen, nPosition);}//释放自身字符串空间delete[] m_Str;m_Str = NewStr;m_nCount = nSumLen;return *this;
}void MyStr::FrontInsert(const char* str)
{Insert(0, str);
}void MyStr::TailInsert(const char* str)
{Insert(m_nCount, str);
}MyStr& MyStr::Delete(int nPosition, int nCount)
{//删除头部 中间 尾部int nLen = m_nCount - nPosition - 1;if (nLen = nCount){m_Str[nPosition] = '\0';}return*this;
}int MyStr::HeadFind(const char* str)
{if (str == NULL)return -1;int nLen = strlen(str);int nIndex = 0;//字符串开始查找的位置int nCount = 0;//一 :这是判断的是一个字符对比的情况if (nLen == 1){return IsCmpByteHead(str[0], nIndex);//IsCmpByteHead 一个字符 在m_Str字符串中循环判断一次}//二:长度和字符串长度一样,就匹配每一个字节是否相等if (nLen == (m_nCount -1)){if (IsCmpByteContinues(str, nLen, 0,0))//IsCmpByteHead 一个字符 在m_Str字符串中循环判断一次{return 0;}}//三:这判断是多个字符的对比情况return IsCmpContinuesHead(str, nLen, nIndex);}int MyStr::TailFind(const char* str)
{if (str == NULL)return false;int nLen = strlen(str);int nIndex = m_nCount - nLen -1;//字符串开始查找的位置int nCount = 0;if (nLen == 1){return IsCmpByteTail(str[0], nIndex);}//二:长度和字符串长度一样,就匹配每一个字节是否相等if (nLen == (m_nCount - 1)){if (IsCmpByteContinues(str, nLen, 0,0))//IsCmpByteHead 一个字符 在m_Str字符串中循环判断一次{return 0;}}return IsCmpContinuesTail(str, nLen, nIndex);}int MyStr::HeadFindCount(const char* str)
{if (str == nullptr)return -1;int nCount = 0;int nLen = strlen(str);int nIndex = 0;do{nIndex = IsCmpContinuesHead(str, nLen, nIndex);if (nIndex == -1){return nCount;}nCount++;//找到了索引值就要增加nLen之后的位置开始查找nIndex = nIndex + nLen;} while (true);return nCount;
}int MyStr::Modify(const char* nStr, const char* cStr, bool bmp)
{//记录替换的次数int nCount = 0;int nLen = strlen(cStr);int nIndex = 0;do{nIndex = IsCmpContinuesHead(nStr, nLen, nIndex);if (nIndex == -1){return nCount;}nCount++;// 在替换 --需要替换的字符串 和this字符串索引Replace(cStr,nIndex);//找到了索引值就要增加nLen之后的位置开始查找nIndex = nIndex + nLen;} while (bmp);return nCount;
}int MyStr::NumberCount(int nNumber)
{//求数字有多少位int nLen = 0;while (nNumber != 0){nNumber = nNumber / 10;nLen++;}return nLen;
}int MyStr::GetDivNum(int nLen)
{int DivNum = 1;while ( nLen > 1 ){DivNum = DivNum * 10;nLen--;}return DivNum;
}bool MyStr::IsStr()
{if (m_Str == nullptr){return false;}return true;
}bool MyStr::IsPnCount()
{if (m_p_nCount == nullptr){return false;}return true;
}void MyStr::InitNumber(int nNumber)
{m_p_nCount = new int(0);int nLen = NumberCount(nNumber);m_nCount = nLen + 1;m_Str = new char[m_nCount];if (!IsStr()){cout << "内存初始化失败" << endl;}else{memset(m_Str, 0, m_nCount);int nDivNum = GetDivNum(nLen);int nIndex = 0;//在把每一位数字转换为字符串 数字的1 和字符串的1 先除,在取模for (int i = 0; i < m_nCount - 1; i++){m_Str[nIndex] = (char)(nNumber / (1 * nDivNum)) + '0';nIndex++;nNumber = nNumber % (1 * nDivNum);nDivNum = nDivNum / 10;}}}void MyStr::InitSpace(char nLen)
{if (nLen <= 0){cout << "nNumber初始化字符串长度不能为0" << endl;return;}m_nCount = nLen + 1;m_p_nCount = new int(0);m_Str = new char[m_nCount];//申请堆内存if (!IsStr()){cout << "m_Str:申请内存空间失败" << endl;return;}memset(m_Str,0, m_nCount);//全部初始化为0
}int MyStr::StrToNumber()
{int nTmp = 0;int nImu = GetDivNum(m_nCount - 1);for (int i = 0; i < m_nCount - 1; i++){char chCtr = m_Str[i];int nNum = (int)chCtr - '0';nTmp += nNum * nImu;nImu = nImu / 10; //nImu = 10}return nTmp;
}void MyStr::FrontInsert(char* NewStr, int nSumLen, const char* str,int nLen)
{//种方式也可以//memcpy_s(NewStr, nSumLen, str, nLen);//memcpy_s(NewStr + nLen, nSumLen, m_Str, m_nCount - 1);//另种方式也可以MiddleInsert(NewStr, nSumLen, str, nLen,0);
}void MyStr::TailInsert(char* NewStr, int nSumLen, const char* str, int nLen)
{//memcpy_s(NewStr, nSumLen, m_Str, m_nCount - 1);//memcpy_s(NewStr + m_nCount - 1, nSumLen, str, nLen);MiddleInsert(NewStr, nSumLen, str, nLen, m_nCount -1);
}void MyStr::MiddleInsert(char* NewStr, int nSumLen, const char* str, int nLen, int nPosition)
{memcpy_s(NewStr, nSumLen, m_Str, nPosition);//5wo ai6memcpy_s(NewStr + nPosition, nSumLen, str, nLen);memcpy_s(NewStr + nLen + nPosition, nSumLen, m_Str + nPosition, m_nCount - nPosition -1);}int MyStr::IsCmpByteHead(const char chByte,int nIndex)
{for (int i = nIndex; i < m_nCount -1; i++){if (m_Str[i] == chByte){return i;}}return -1;
}int MyStr::IsCmpByteTail(const char chByte, int nIndex)
{for (int i = nIndex; i >= 0; i--){if (m_Str[i] == chByte){return i;}}return -1;
}bool MyStr::IsCmpByteContinues(const char* str, int nLen, int nIndex,int nIn)
{for (int i = nIn; i < nLen; i++){if (m_Str[nIndex] != str[i]){return false;}nIndex++;}return true;
}int MyStr::IsCmpContinuesHead(const char* str,int nLen,int nIndex)
{int nLenCmp = 0;int nIn = 1;//正向查找do {//先查找第一个字节 ---在字符串中有没有,有返回索引nIndex = IsCmpByteHead(str[0], nIndex);//如果尾部查找到str[0],剩余的字节不够对比直接返回-1//str "ghy" m_str "erergh" 找到了g,但是m_str后面只有2个字符;肯定返回-1nLenCmp = m_nCount - 1 - nIndex;if (nIndex == -1 || nLenCmp < nLen){return -1;}//如果第一个字节存在,连续对比m_str和str的每一个字节if (IsCmpByteContinues(str, nLen, nIndex + nIn, nIn)){return nIndex;}nIndex++ ;//正向查找} while (true);return -1;}int MyStr::IsCmpContinuesTail(const char* str, int nLen, int nIndex)
{int nLenCmp = 0;int nIn = 1;do {//先查找第一个字节 ---在字符串中有没有,有返回索引nIndex = IsCmpByteTail(str[0], nIndex);//反向查找nLenCmp = m_nCount - 1 - nIndex;if (nIndex == -1 || nLenCmp < nLen){return -1;}//如果第一个字节存在,连续对比m_str和str的每一个字节if (IsCmpByteContinues(str, nLen, nIndex + nIn, nIn)){return nIndex;}nIndex--;//反向查找} while (true);return -1;
}void MyStr::Replace(const char* cStr, int nIndex)
{int nLen = strlen(cStr);for (int i = 0; i < nLen; i++){m_Str[nIndex] = cStr[i];nIndex++;}
}void MyStr::FreeSpace()
{if (!IsStr()){return;}delete[] m_Str;delete m_p_nCount;
}
cFile
#include "cFile.h"cFile::cFile(const cFile& fFile)
{m_pFile = nullptr;m_nCount = NULL;if (fFile.m_pFile != nullptr){m_pFile = fFile.m_pFile;m_nCount = fFile.m_nCount;(*m_nCount)++;}
}cFile::cFile()
{m_pFile = nullptr;m_nCount = nullptr;
}cFile::cFile(const char* FileName)
{//以读写方式打开文件fopen_s(&m_pFile, FileName, "r+b");//从文件头开始读,可读可写m_nCount = new int(0);if (!IsOpen())//文件打开不成功{//文件打开不成功,就创建一个新文件 从文件尾开始写fopen_s(&m_pFile, FileName, "w+b");//写入四个字节 ---也可以检测文件是否打开成功if (WriteFileDate(m_nCount, 4) != SUCCESS){cout << "初始化失败" << endl;}fflush(m_pFile);}}cFile::~cFile()
{if (*m_nCount != 0){(*m_nCount)--;}else{CloseFile();//关闭文件delete m_nCount;}}bool cFile::IsOpen()
{if (m_pFile == nullptr){return false;}return true;
}int cFile::ReadFileHeader()
{//文件偏移移动到首rewind(m_pFile);int nCount = 0;//从文件读四个字节到nCount /成功返回读取了多少个字节if (fread((char*)&nCount, 1, 4, m_pFile) == 4){return nCount;}return 0;
}cFile::FileType cFile::ReadFileAllDate(ClassStu* pStudent,int nCount)
{//1:检测缓冲区地址是否为空if (pStudent == nullptr){return PNULL;}//2:循环读取文件中用户信息--》缓存中char nLen = {0};for (int i = 0; i < nCount; i++){//2.1 先读用户的IDif (ReadFileDate(&pStudent->m_Id, 4) == READERR){return READERR;}//2.2 在读字符串的字节数if (ReadFileDate(&nLen, 1) == READERR){return READERR;}//2.3 在读字符串pStudent->m_StuName = new MyStr(nLen);if (ReadFileDate(pStudent->m_StuName->GetStr(), nLen) == READERR){return READERR;}//2.4 在读文件偏移if (ReadFileDate(&pStudent->m_FileOffset, 4) == READERR){return READERR;}pStudent++;//步长++}return SUCCESS;}cFile::FileType cFile::ReadFileDate(void* buffer, int nSize)
{if (buffer == nullptr || nSize <= 0){return READERR;}if (fread(buffer, 1, nSize, m_pFile) == nSize){return SUCCESS;}return READERR;
}int cFile::WriteFile(ClassStu* buffer,int FileOffset)
{//1:判断传入的指针是否为空if(buffer == nullptr){return WRITEERR;}//2:将文件偏移指向要写入的位置if (FileOffset == 0){fseek(m_pFile, FileOffset, SEEK_END);//移动到尾部开始写入}else{fseek(m_pFile, FileOffset, SEEK_SET);//移动到指定位置写入;}ClassStu* pStudent = buffer;//3.0 获取文件偏移,后面可以写入FileOffset = ftell(m_pFile);if (FileOffset == -1L){return WRITEERR;}//3.1 先写入学生Idif (WriteFileDate(&pStudent->m_Id, sizeof(int)) != SUCCESS){return WRITEERR;}//3.2 再写入用户名称的字符串长度int nLen = pStudent->m_StuName->GetLen();if (WriteFileDate(&nLen, sizeof(char)) != SUCCESS){return WRITEERR;}//3.3 写入用户的姓名if (WriteFileDate(pStudent->m_StuName->GetStr(), pStudent->m_StuName->GetLen()) != SUCCESS){return WRITEERR;}//3.4 写入文件偏移if (WriteFileDate(&FileOffset, sizeof(int)) != SUCCESS){return WRITEERR;}//3.5 修改首部四个字节用户个数UpDateHeader();if (fflush(m_pFile) == 0){cout << "写入文件成功了" << endl;}return SUCCESS;
}cFile::FileType cFile::WriteFileDate(void* buffer, int nSize)
{if (buffer == nullptr || nSize <= 0){return WRITEERR;}if (fwrite(buffer, 1, nSize, m_pFile) == nSize){return SUCCESS;}return WRITEERR;
}void cFile::CloseFile()
{fclose(m_pFile);
}int cFile::ReFileName(const char* old_filename, const char* new_filename)
{return rename(old_filename, new_filename);
}int cFile::DeleteFile(const char* FileName)
{return remove(FileName);
}cFile::FileType cFile::UpDateHeader(bool bTmp)
{//先读int nCount = ReadFileHeader();if (nCount == -1){return READERR;}bTmp ? nCount++ : nCount--;fseek(m_pFile,0,SEEK_SET);//移动到头部//再写if (WriteFileDate(&nCount, 4) != SUCCESS){return WRITEERR;}fflush(m_pFile);return SUCCESS;
}