C++电话簿程序Case 2无法执行:无法显示文件存储数据求助
问题分析与解决方案
你的电话簿程序中选项2无法显示数据,核心原因是文件打开模式不正确,导致你根本无法向phone.dat中写入数据,自然也就读不到任何内容。下面详细拆解问题并给出修复方案:
1. 最关键的问题:文件打开模式错误
在main函数开头,你用以下方式打开文件:
file.open("phone.dat", ios::in | ios::binary);
ios::in模式只允许读取文件,不支持写入操作。当你选择选项1添加新记录时,file.write((char *)&rec, sizeof(rec))会执行失败,数据根本没被写入到phone.dat里,所以选项2自然看不到任何记录。
你需要修改打开模式,同时支持读写,并且如果文件不存在则创建它:
// 先尝试打开,若不存在则创建 file.open("phone.dat", ios::in | ios::out | ios::binary); if (!file) { // 文件不存在,重新打开为写入模式创建文件 file.open("phone.dat", ios::out | ios::binary); file.close(); // 再以读写模式打开 file.open("phone.dat", ios::in | ios::out | ios::binary); }
2. 选项2的循环逻辑优化
当前选项2的循环写法有潜在冗余问题:
while(file) { file.read((char *)&rec, sizeof(rec)); if(!file.eof()) rec.showdata(); }
这种写法会在文件末尾时多读一次(虽然你加了!file.eof()判断避免显示无效数据),更简洁可靠的写法是把read操作放在循环条件中:
file.seekg(0, ios::beg); cout<<"\n\nRecords in Phone Book\n"; phoneBook tempRec; // 用临时变量避免覆盖原rec while(file.read((char *)&tempRec, sizeof(tempRec))) { tempRec.showdata(); } file.clear(); getch();
这样只有当read成功读取到完整对象时,才进入循环显示数据,逻辑更清晰直观。
3. 其他细节修复
- 选项5中的缓冲区问题:在读取用户输入新电话号码前,
cin.get(ch)可能无法正确清除换行符,建议用cin.ignore()替代(需要包含<limits>头文件):cin.ignore(numeric_limits<streamsize>::max(), '\n'); cout<<"Enter New Telephone No : "; cin>>telno; - 程序退出时关闭文件:当前只有选择默认选项时才会关闭文件,建议在
case 6中添加file.close();,确保文件资源被正确释放。 telno数组长度问题:你定义telno[6],但电话号码通常不止5位(加上终止符),建议改为telno[15],和类中的phno[15]保持一致,避免字符串截断。
修正后的完整代码(关键部分修改)
//Telephone Directory #include <iostream> #include <fstream> #include <string.h> #include <iomanip> #include <conio.h> #include<stdlib.h> #include <limits> // 用于cin.ignore using namespace std; class phoneBook{ char name[20],phno[15]; public: void getdata(); void showdata(); char *getname(){ return name; } char *getphno(){ return phno; } void update(char *nm,char *telno){ strcpy(name,nm); strcpy(phno,telno); } }; void phoneBook :: getdata(){ cout<<"\nEnter Name : "; cin>>name; cout<<"Enter Phone No. : "; cin>>phno; } void phoneBook :: showdata(){ cout<<"\n"; cout<<setw(20)<<name; cout<<setw(15)<<phno; } int main(){ phoneBook rec; fstream file; // 修正文件打开逻辑 file.open("phone.dat", ios::in | ios::out | ios::binary); if (!file) { file.open("phone.dat", ios::out | ios::binary); file.close(); file.open("phone.dat", ios::in | ios::out | ios::binary); } char ch,nm[20],telno[15]; // 修正telno长度 int choice,found=0; int cnt=0; while(1) { system("cls"); cout<<"\n*****Phone Book*****\n"; cout<<"1) Add New Record\n"; cout<<"2) Display All Records\n"; cout<<"3) Search Telephone No.\n"; cout<<"4) Search Person Name\n"; cout<<"5) Update Telephone No.\n"; cout<<"6) Exit\n"; cout<<"Choose your choice : "; cin>>choice; switch(choice) { case 1 : //New Record rec.getdata(); cin.ignore(numeric_limits<streamsize>::max(), '\n'); // 替换cin.get(ch) file.write((char *)&rec, sizeof(rec)); break; case 2 : //Display All Records file.seekg(0,ios::beg); cout<<"\n\nRecords in Phone Book\n"; phoneBook tempRec; while(file.read((char *)&tempRec, sizeof(tempRec))) { tempRec.showdata(); } file.clear(); getch(); break; case 3 : //Search Tel. no. when person name is known. cout<<"\n\nEnter Name : "; cin>>nm; file.seekg(0,ios::beg); found=0; while(file.read((char *) &rec, sizeof(rec))) { if(strcmp(nm,rec.getname())==0) { found=1; rec.showdata(); } } file.clear(); if(found==0) cout<<"\n\n---Record Not found---\n"; getch(); break; case 4 : //Search name on basis of tel. no cout<<"\n\nEnter Telephone No : "; cin>>telno; file.seekg(0,ios::beg); found=0; while(file.read((char *) &rec, sizeof(rec))) { if(strcmp(telno,rec.getphno())==0) { found=1; rec.showdata(); } } file.clear(); if(found==0) cout<<"\n\n---Record Not found---\n"; getch(); break; case 5 : //Update Telephone No. cout<<"\n\nEnter Name : "; cin>>nm; file.seekg(0,ios::beg); found=0; cnt=0; // 重置cnt,避免多次查询导致累计 while(file.read((char *) &rec, sizeof(rec))) { cnt++; if(strcmp(nm,rec.getname())==0) { found=1; break; } } file.clear(); if(found==0) cout<<"\n\n---Record Not found---\n"; else { int location = (cnt-1) * sizeof(rec); cin.ignore(numeric_limits<streamsize>::max(), '\n'); cout<<"Enter New Telephone No : "; cin>>telno; file.seekp(location); rec.update(nm,telno); file.write((char *) &rec, sizeof(rec)); file.flush(); } break; case 6 : file.close(); // 关闭文件 return 0; default: file.close(); cout<<"Invalid choice!"; getch(); } } }
现在你可以测试修改后的程序:添加几条记录后,选择选项2就能正常显示所有数据了。
内容的提问来源于stack exchange,提问作者user11281354
相关产品推荐
相关产品推荐

