c++简单做一个文件变长储存(自己封装字符串类)

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;
}

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

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

相关文章

Vue+Element UI+Echarts

Vue文档 Vue.js - 渐进式 JavaScript 框架 | Vue.js (vuejs.org) 一个简单的基于vue.js的无缝滚动 vue-seamless-scroll (chenxuan0000.github.io) Element&#xff0c;一套为开发者、设计师和产品经理准备的基于 Vue 2.0 的桌面端组件库 Element - 网站快速成型工具 ECharts …

【C】volatile 关键字

目录 volatile1&#xff09;基本概念2&#xff09;用途&#xff1a;禁止编译器优化3&#xff09;总结 volatile 1&#xff09;基本概念 const是C语言的一个关键字。 const用于告诉编译器相应的变量可能会在程序的控制之外被修改&#xff0c;因此编译器不应该对其进行优化。 …

2024年AMC8往年真题练一练和答案详解(6),还有全真模拟题

今天是1月13日&#xff0c;2024年AMC8正式比赛已经倒计时了&#xff0c;昨天AMC主办方给所有参赛选手发了短信通知&#xff0c;关于模拟竞赛的操作方式和实际比赛的要求指南&#xff0c;大家一定要认真阅读&#xff0c;严格按指南操作&#xff0c;六分成长也会详细为大家解读和…

Stable Diffusion的 webui 如何在Windows上使用 AMD GPU显卡?

根据Stable Diffusion官方说明 webui 是不支持AMD GPU显卡的&#xff0c;所以在国内如果想省点事情要玩Stable Diffusion (SD) 推荐用黄教主的英伟达显卡NVIDIA GPU&#xff0c;可以省心不少。 AMD显卡得用 webui-directml&#xff0c;这是另外的包&#xff0c;按官方的说明实…

编程竞赛-消息存取

目录链接&#xff1a; 力扣编程题-解法汇总_分享记录-CSDN博客 GitHub同步刷题项目&#xff1a; GitHub - September26/java-algorithms: 算法题汇总&#xff0c;包含牛客&#xff0c;leetCode&#xff0c;lintCode等网站题目的解法和代码&#xff0c;以及完整的mode类&#…

LinkedList和ArrayList

LinkedList和ArrayList都是Java中的List接口的实现 内部数据结构&#xff1a; ArrayList是基于动态数组实现的&#xff0c;它支持快速的随机访问&#xff0c;也就是说&#xff0c;获取指定索引位置的元素非常快&#xff0c;时间复杂度为O(1)。 LinkedList是基于双向链表…

input框不可编辑的方法

input框不可编辑的方法 大家好&#xff0c;我是免费搭建查券返利机器人赚佣金就用微赚淘客系统3.0的小编&#xff0c;也是冬天不穿秋裤&#xff0c;天冷也要风度的程序猿&#xff01;今天&#xff0c;我们将探讨一个在前端开发中常见的问题——“input框不可编辑的方法”。无论…

在 Nvidia Docker 容器编译构建显存优化加速组件 xFormers

本篇文章&#xff0c;聊聊如何在新版本 PyTorch 和 CUDA 容器环境中完成 xFormers 的编译构建。 让你的模型应用能够跑的更快。 写在前面 xFormers 是 FaceBook Research &#xff08;Meta&#xff09;开源的使用率非常高的 Transformers 加速选型&#xff0c;当我们使用大模…

掌握 gRPC 和 RPC 的关键区别

一、远程过程调用协议简介 1、RPC 的本质 首先&#xff0c;我们探讨一下什么是 RPC。RPC&#xff0c;缩写为 Remote Procedure Call Protocol&#xff0c;直译来看就是远程过程调用协议。 讲得通俗一些&#xff1a; RPC 是一种通信机制RPC 实现了客户端/服务器通信模型 官…

教程-右键用vscode(新窗口)打开文件或目录

通过本文可以提高效率&#xff0c;用起来更爽更高效。 本文实现了&#xff08;windows系统&#xff09;&#xff1a; 右键-用vscode(当前窗口)打开文件或目录右键-用vscode-新窗口打开文件或目录 注意&#xff1a; 下面的安装路径要更改为您实际的路径 具体配置步骤&#x…

TS报错:类型‘object‘上不存在属性‘product_id’

问题&#xff1a; TS报错&#xff1a;类型object上不存在属性product_id。 解决办法&#xff1a; 下面是一个示例代码&#xff0c;演示了如何使用条件语句来安全地从对象中获取属性值&#xff1a; // 使用条件语句进行安全访问 if (dataSource.value.length > 0 &&…

边缘计算:连接实时数据的力量与未来发展之路

边缘计算是一种分布式计算范式&#xff0c;它旨在将数据处理、存储和应用服务带到数据源的近端&#xff0c;即网络的“边缘”。在边缘计算模型中&#xff0c;算力和存储资源距离末端用户或数据源更近&#xff0c;这减少了数据在网络中传输的距离&#xff0c;从而降低延迟&#…

imgaug库指南(19):从入门到精通的【图像增强】之旅

引言 在深度学习和计算机视觉的世界里&#xff0c;数据是模型训练的基石&#xff0c;其质量与数量直接影响着模型的性能。然而&#xff0c;获取大量高质量的标注数据往往需要耗费大量的时间和资源。正因如此&#xff0c;数据增强技术应运而生&#xff0c;成为了解决这一问题的…

常见的传感器技术汇总简介

传感器技术是现代信息技术的关键组成部分之一&#xff0c;涉及到物理学、化学、生物学等多个学科领域&#xff0c;其应用范围广泛&#xff0c;包括工业自动化、环境监测、医疗保健、智能家居等领域。下面将介绍一些常见的传感器技术&#xff1a; 温度传感器&#xff1a;用于测…

高防ip是什么,防护效果好吗

DDoS攻击是互联网最常见的网络攻击方式之一&#xff0c;通过大量虚假流量对目标服务器进行攻击&#xff0c;堵塞网络耗尽服务器性能&#xff0c;导致服务器崩溃&#xff0c;真正的用户无法访问。以前企业常用的防御手段就是高防服务器&#xff0c;也就是硬防&#xff0c;但由于…

Chrome DevTools 常用面板攻略

文章目录 前言一、概述1.1 简介1.2 DevTools 初步了解 二、设备模式&#xff08;Device Mode&#xff09;2.1 面板概述2.2 设备切换 三、元素面板&#xff08;Elements&#xff09;3.1 面板概述3.2 编辑样式3.2.1 添加、启用和停用 CSS 类3.2.2 添加或移除动态样式3.2.3 快速向…

如何优雅的只在当前页面中覆盖ui库中组件的样式(vue的问题)

首先我们vue文件的样式都是写在<style lang"less" scoped></style>标签中的&#xff0c;加scoped是为了使得样式只在当前页面有效。那么问题来了&#xff0c;看图&#xff1a; 我们正常写的所有样式&#xff0c;都会被加上[data-v-23d425f8]这个属性&…

XYplorer:双栏多标签文件资源管理器的高效选择

在文件管理的世界中&#xff0c;效率和便捷性是用户追求的关键。XYplorer作为一款专为Windows设计的文件资源管理器&#xff0c;以其独特的双栏多标签浏览、强大的文件搜索功能、以及高度可定制的界面&#xff0c;为用户提供了一种全新的文件管理体验。 XYplorer&#xff1a;速…

微信小程序开发学习笔记《11》导航传参

微信小程序开发学习笔记《11》导航传参 博主正在学习微信小程序开发&#xff0c;希望记录自己学习过程同时与广大网友共同学习讨论。导航传参 官方文档 一、声明式导航传参 navigator组件的url属性用来指定将要跳转到的页面的路径。同时&#xff0c;路径的后面还可以携带参数…

第七讲 单片机驱动彩色液晶屏 控制RA8889软件:显示文字:Part3.自建字库

单片机驱动TFT彩色液晶屏系列讲座 目录 第一讲 单片机最小系统STM32F103C6T6通过RA8889驱动彩色液晶屏播放视频 第二讲 单片机最小系统STM32F103C6T6控制RA8889驱动彩色液晶屏硬件框架 第三讲 单片机驱动彩色液晶屏 控制RA8889软件:如何初始化 第四讲 单片机驱动彩色液晶屏 控…