C++基础数据库记录管理程序多次执行列表功能失效求助
问题分析与解决方案
嘿,我仔细看了你的代码,发现问题出在文件流的重复打开/关闭以及状态管理上,这就是为什么第一次调用List Records正常,之后就没数据的原因:
核心问题
- 你的
group类在构造函数中已经打开了file流,但在modirec、delrec、recovrec这些函数里,又重复调用file.open()重新打开同一个流,操作完成后还调用file.close()关闭它。一旦你调用过这些函数,file就处于关闭状态了,后续再调用listrec时,尝试对关闭的流执行seekg和read操作,自然读不到任何数据。 - 另外,第一次调用
listrec后,文件指针会移动到文件末尾,并且流会设置EOF标志,如果不清除这个标志,后续的读取操作也会直接失败。
修复方案
我们需要统一管理文件流的状态,避免重复打开/关闭,同时每次操作前重置流的状态。下面是具体的修改步骤:
1. 添加析构函数统一关闭文件流
在group类中添加析构函数,确保程序结束时正确关闭所有打开的流:
group::~group() { if (file.is_open()) { file.close(); } if (fin.is_open()) fin.close(); if (fout.is_open()) fout.close(); }
2. 修改listrec函数,确保流状态正确
在读取前检查文件是否打开,清除之前的错误状态(比如EOF),并重置指针到文件开头:
void group::listrec() { int j=0; // 检查文件是否打开,未打开则重新打开 if (!file.is_open()) { file.open("EMP.DAT", ios::in|ios::out|ios::binary); if (!file) { cerr<<"Unable to open file"; cin.ignore(); getchar(); return; } } // 清除流的错误标志(比如EOF),重置指针到开头 file.clear(); file.seekg(0L, ios::beg); while(file.read((char*)&p,sizeof(p))) { if(p.flag!='*') { cout<<"\nRecord N. "<<++j; cout<<"\nEmp Code: "<<p.empcode; cout<<"\nName: "<<p.name; cout<<"\nAge: "<<p.age; cout<<"\nSalary: "<<p.sal<<endl; } } // 再次清除EOF标志,避免影响后续操作 file.clear(); cin.ignore(); getchar(); }
3. 修改modirec、delrec、recovrec函数,移除重复的打开/关闭操作
以modirec为例,移除里面的file.open()和file.close(),改为检查流状态:
void group::modirec() { char code[5]; int count=0; long int pos; cout<<"Enter Emp Code"; cin>>code; if (!file.is_open()) { file.open("EMP.DAT", ios::in|ios::out|ios::binary); if (!file) { cerr<<"Unable to open file"; getchar(); return; } } file.clear(); file.seekg(0, ios::beg); bool found = false; while(file.read((char*)&p,sizeof(p))) { if(strcmp(p.empcode,code)==0&&p.flag==' ') { cout<<"Enter new Data: "<<endl; cout<<"Enter Emp_Code, Name, age, Salary"<<endl; cin>>p.empcode>>p.name>>p.age>>p.sal; pos=count*sizeof(p); file.seekp(pos,ios::beg); file.write((char*)&p,sizeof(p)); found = true; break; } count++; } file.clear(); // 清除EOF状态 if (found) { cout<<endl<<"Press Any Key..."; } else { cout<<endl<<"No Employee In File With Code: "<<code; cout<<endl<<"Press Any Key..."; } getchar(); }
同样地,对delrec和recovrec做类似修改:移除file.open()和file.close(),添加流状态检查和file.clear()操作。
4. 修复addrec函数中的文件失效问题
当用户选择删除旧文件后,原来的file流会失效,需要重新打开:
void group::addrec() { char ch; cout<<"Do You Want To Erase Previous Records ?: "; cin>>ch; if(ch=='y'||ch=='Y') { remove("EMP.DAT"); // 关闭旧的流并重新打开 if (file.is_open()) { file.close(); } file.open("EMP.DAT",ios::in|ios::out|ios::binary); } fout.open("EMP.DAT",ios::binary); fout.seekp(0L,ios::end); system("cls"); do { cout<<"Enter Emp_Code, Name, age, Salary"<<endl; cin>>p.empcode>>p.name>>p.age>>p.sal; fout.write((char*)&p,sizeof(p)); cout<<"Add another record ?: "; cin>>ch; } while(ch=='y'||ch=='Y'); fout.close(); }
为什么这些修改能解决问题?
- 我们不再重复打开/关闭类成员
file,而是统一管理它的状态,确保所有成员函数都使用同一个有效的流。 - 每次操作前清除流的错误标志(比如EOF),保证后续的
seek和read操作能正常执行。 - 在
listrec中增加了流的打开检查,避免对关闭的流进行操作。
按照这些修改后,你应该能每次选择List Records都正常显示数据了。
内容的提问来源于stack exchange,提问作者Android Gamer Man
相关产品推荐
相关产品推荐

