这几天一直在解决座位号重复问题,所以考虑到用文件读写来判断字符串是否重复。
刚开始是使用固定的长度来写入文件和替换字符串,但是考虑到代码的复用性,后来还是修改了任意字符串的读写和替换,方便以后使用。
1:添加字符串到文件:
函数原型:bool AddSeatID(char *_setNum,int length);
函数实现:
bool CFileTest::AddSeatID(char *_setNum,int length)
{
if (checkDuplicate(_setNum))
{
return false;
}
if (!openFile("ab+"))
{
printf("open file failed \n");
return false;
}
char seatBuf[length+4];
memset(seatBuf,0,length+4);
memcpy(seatBuf,"[",1);
memcpy(seatBuf+1,_setNum,length);
memcpy(seatBuf+length+1,"]\r\n",3);
fseek(m_fp,0L,SEEK_END);
fwrite(seatBuf,length+4,1,m_fp);
closeFile();
m_seatIDList.push_back(_setNum);
return true;
}
已追加方式写入文件,其中有使用判断字符串是否存在于文件中,如果有存在则返回false,不存在则写入文件。其中设置m_seatIDList为vector容器,将字符串保存到内存中
2:字符串重复判断函数:
函数原型:bool checkDuplicate(char* _seatID);
函数实现:
bool CFileTest::checkDuplicate(char* _seatID)
{
string seatID;
if (m_seatIDList.empty())
{
return false;
}
vector<string>::iterator iter;
vector<string>::iterator beginVec = m_seatIDList.begin();
vector<string>::iterator endVec = m_seatIDList.end();
for (iter = beginVec; iter!= endVec; iter++)
{
if (!strcmp(iter->c_str(),_seatID))
{
return true;
}
}
return false;
}
将需要判断重复的字符串传入,并将此字符串与文件中读出的字符串进行比较
3:替换新旧字符串函数:
函数原型:bool changeSeatID(char* _oldSeat,int _oldLength,char* _newSeat,int _newLength);
函数实现:
bool CFileTest::changeSeatID(char* _oldSeat,int _oldLength,char* _newSeat,int _newLength)
{
if (checkDuplicate(_newSeat))
{
return false;
}
if (replaceSeatID(_oldSeat,_oldLength,_newSeat,_newLength))
{
return true;
}
return false;
}
将新旧字符串以及相应的字符串长度传入,如果文件中有存在与就字符串相同的字符串,就将新字符串传入替换函数中进行替换
4:替换函数:
函数原型:bool replaceSeatID(char* _oldSeat,int _oldLength,char* _newSeat,int _newLength);
函数实现:
bool CFileTest::replaceSeatID(char* _oldSeat,int _oldLength,char* _newSeat,int _newLength)
{
int oldoffset =0;
int newoffset =0;
char buf[128];
if (!openFile("r+"))
{
printf("open file failed \n");
return false;
}
while(getline(buf,128))
{
oldoffset = newoffset;
newoffset = ftell(m_fp);
int i = 0;
char seatNumberTemp[20]={0};
while(i < 128)
{
if(buf[i] == '\0' || buf[i] == '\n')
{
break;
}
if(buf[i] == '[')
{
int i_begin;
i_begin = ++i;
while(buf[i]!=']')
{
i++;
}
i--;
memcpy(seatNumberTemp,buf+i_begin,i-i_begin+1);
if (strcmp(seatNumberTemp,_oldSeat))
{
break;
}
else
{
memset(buf+i_begin,0,i-i_begin+4);
fseek(m_fp,oldoffset+i_begin,SEEK_SET);
fwrite(buf+i_begin,i-i_begin+4,1,m_fp);
memcpy(buf+i_begin,_newSeat,_newLength);
buf[i_begin+_newLength]=']';
buf[i_begin+_newLength+1]='\r';
buf[i_begin+_newLength+2]='\n';
fseek(m_fp,oldoffset,SEEK_SET);
fwrite(buf,i_begin+_newLength+2,1,m_fp);//此处不能修改为3,不然短字符串
//修改为长字符串时,会导致下一行的字符串丢失"["
closeFile();
//update file mapping memory
vector<string>::iterator iter;
vector<string>::iterator beginVec = m_seatIDList.begin();
vector<string>::iterator endVec = m_seatIDList.end();
for (iter = beginVec; iter!= endVec; iter++)
{
if (!strcmp(iter->c_str(),_oldSeat))
{
break;
}
}
m_seatIDList.erase(iter);
m_seatIDList.push_back(_newSeat);
return true;
}
}
else
{
i++;
}
}//end of parse a line while
}//end of while file
closeFile();
AddSeatID(_newSeat,_newLength);
//update file mapping memory
return true;
}//end of func
将文件中每行字符串读出,并去除[]内的字符串与旧字符串对比,如果相同就开始将就字符串替换成新的字符串,如果不相同,就以新字符串形式写入文件中
5:整行读入函数:
函数原型:bool getline(char* buf, unsigned int length);
函数实现:
bool CFileTest::getline(char* buf, unsigned int length)
{
int len = 0;
if(fgets(buf, length, m_fp) != NULL)
return true;
else
return false;
}
6:初始化函数:
函数原型:bool init();
函数实现:
bool CFileTest::init()
{
return updataSeatList();
}
7:更新容器中字符串函数:
函数原型:bool updataSeatList();
函数实现:
bool CFileTest::updataSeatList()
{
if (!openFile("ab+"))
{
return false;
}
if (!m_seatIDList.empty())
{
m_seatIDList.clear();
}
char buf[128];
memset(buf, 0, 128);
if (m_fp != NULL)
{
while(getline(buf,128))
{
string SeatID;
int i = 0;
while(i < 128)
{
if(buf[i] == '#' || buf[i] == '\0' || buf[i] == '\n')
{
break;
}
else if(buf[i] == ' ')
{
i++;
continue;
}
else if(buf[i] == '[')
{
int i_begin;
i_begin = ++i;
while(buf[i]!=']'){
i++;
}
SeatID.assign(buf+i_begin, i-i_begin);
break;
}
else
{
i++;
}
}
m_seatIDList.push_back(SeatID);
}
}
closeFile();
return true;
}
8:打开、关闭文件函数:
函数原型: bool openFile(char* mode); void closeFile();
函数实现:
bool CFileTest::openFile(char* mode)
{
closeFile();
m_fp = fopen(SEATIDFILE,mode);
if (m_fp == NULL)
{
return false;
}
return true;
}
void CFileTest::closeFile()
{
if (m_fp!= NULL)
{
fclose(m_fp);
m_fp = NULL;
}
}
9:main函数:
#include "filetest.h"
int main()
{
CFileTest filet;
if (filet.checkDuplicate("cc003"))
{
filet.changeSeatID("cc003",5,"a04",3);
}else{
char * str = "cc032";
int len = strlen(str);
filet.AddSeatID(str,len);
filet.AddSeatID("ccjkj8967",9);
filet.AddSeatID("a01",3);
filet.AddSeatID("a02",3);
filet.AddSeatID("a03",3);
filet.AddSeatID("bb01",4);
filet.AddSeatID("bb02",4);
filet.AddSeatID("bb03",4);
filet.AddSeatID("cc001",5);
filet.AddSeatID("cc002",5);
filet.AddSeatID("cc003",5);
filet.AddSeatID("ccjkj89",7);
}
return 0;
}
10:filetest.h文件:
#ifndef FILETEST_H
#define FILETEST_H
#include <fstream>
#include <iostream>
#include <cstring>
#include <vector>
#include <sstream>
#include <stdbool.h>
using namespace std;
class CFileTest{
public:
CFileTest();
~CFileTest();
bool init();
bool checkDuplicate(char* _seatID);
bool getline(char* buf, unsigned int length);
bool updataSeatList();
bool openFile(char* mode);
void closeFile();
bool replaceSeatID(char* _oldSeat,int _oldLength,char* _newSeat,int _newLength);
bool AddSeatID(char *_setNum,int length);
bool changeSeatID(char* _oldSeat,int _oldLength,char* _newSeat,int _newLength);
FILE* m_fp;
vector<string> m_seatIDList;
};
#endif
11:字符串写入结果展示:
第一次写入文件: 第二次将[ccjkj8967]->[cc005]: 第三次将[cc0033]->[a04]:
12:总结:
因为最终的项目时在linux系统运行的,所以这部分代码最终是在Ubuntu上运行调试的并能成功写入与替换,在windows的vs2008上并没有调试,可能会因为头文件的问题导致编译不通过,添加相应的头文件应该就可以了。因为已经转战java快两年了,c++部分也忘记的差不多了,代码中可能存在不足,请大家见谅
13:demo下载地址:http://download.youkuaiyun.com/download/qq_27922603/9985024