C++中使用fstream修改数据文件后读取编辑数据异常问题
票务预订系统数据读写异常问题
问题背景
开发课程作业的票务预订记录系统,修改数据文件后读取数据时出现异常,尝试过eof()判断和fstream::read()两种方式,均无法正常读取修改后的完整数据。
修改记录代码
ifstream inFile; ofstream outFile; inFile.open("movieRecord.dat"); outFile.open("temp.dat"); inFile >> item.movieName >> item.movieTime >> item.hallNum >> item.moviePrice; cout << "\tPlease Enter the Movie to Edit:"; cin.ignore(); cin.getline(editMovie,20); titleMatch = strcmp (editMovie,item.movieName); while (!inFile.eof()){ if (editMovie == item.movieName){ break; } else{ outFile << item.movieName << " " << item.movieTime << " " << item.hallNum << " " << item.moviePrice << endl; break; } } cout << "\tEditing " << editMovie << "..." << endl; cin.clear(); cout << "\tReInsert Movie Title: "; cin.getline(movieTitle,20); cin.clear(); cout << flush; cout << "\tEnter Time(ie:15.00): "; cin >> movieTime2; cout << flush; cout << "\tEnter Hall Number for Movie: Hall "; cin >> hallNumber; cout << flush; cout << "\tEnter Price of Movie Ticket: RM"; cin >> ticketPrice; outFile << movieTitle << " " << movieTime2 << " " << hallNumber << " " << ticketPrice; outFile.close(); inFile.close(); remove ("movieRecord.dat"); rename ("temp.dat","movieRecord.dat"); cout << "\tEdit Saved!" << endl; system("pause"); goto adminMenu;
文件读取代码
ifstream movieCheck; movieCheck.open("movieRecord.dat",ios::in); movieCheck >> item.movieName >> item.movieTime >> item.hallNum >> item.moviePrice; if (!movieCheck.good()){ cout << "File Open Error!" << endl; } while (movieCheck.read((char*)&item,sizeof(item))){ cout << "\tMovie title: " << item.movieName << endl; cout << fixed; cout << "\tTime: " << setprecision(2) << item.movieTime << endl; cout << "\tHall Number: Hall " << item.hallNum << endl; cout << "\tMovie Ticket Price: RM " << setprecision(2) << item.moviePrice << endl; cout << "\t==============================================" << endl; movieCheck >> item.movieName >> item.movieTime >> item.hallNum >> item.moviePrice; } movieCheck.close(); cout << endl << "\t The End of the Movie Summaries!" << endl;
问题现象
- 使用
eof()判断读取时,仅显示第一条数据,修改后的记录无法显示:- 期望输出:
Hello Help2 // 修改后的记录 - 当前输出:
Hello // 未显示修改后的记录
- 期望输出:
- 使用
read()函数时,要么和eof()情况一致仅显示第一条,要么完全无输出。
问题分析
修改代码的核心问题
- 循环逻辑错误:
while (!inFile.eof())循环内,无论是否匹配目标记录,都会执行break跳出循环,导致仅处理了第一条读取的记录,后续记录完全未处理,修改后的文件丢失了其余所有数据。 - 字符串比较错误:
editMovie == item.movieName是直接比较char数组的地址,而非字符串内容,正确的比较应该使用strcmp(editMovie, item.movieName) == 0。 - 未读取后续记录:循环内没有继续读取下一条记录,导致始终处理第一条数据。
读取代码的核心问题
- 混合使用文本/二进制读写:修改代码是用文本模式(
<<运算符)写入数据,但读取代码同时使用>>文本读取和read()二进制读取,两者格式不兼容。read()会按字节直接读取内存布局,而文本文件的存储格式和结构体的内存布局完全不同,导致读取数据错乱。
修复方案
1. 修复修改记录代码
#include <limits> // ... ifstream inFile; ofstream outFile; inFile.open("movieRecord.dat"); outFile.open("temp.dat"); bool found = false; cout << "\tPlease Enter the Movie to Edit:"; cin.ignore(); cin.getline(editMovie,20); // 循环读取所有记录 while (inFile >> item.movieName >> item.movieTime >> item.hallNum >> item.moviePrice) { if (strcmp(editMovie, item.movieName) == 0) { found = true; // 读取新数据 cout << "\tEditing " << editMovie << "..." << endl; cin.clear(); // 处理cin >>后的换行符残留 cin.ignore(numeric_limits<streamsize>::max(), '\n'); cout << "\tReInsert Movie Title: "; cin.getline(movieTitle,20); cout << flush; cout << "\tEnter Time(ie:15.00): "; cin >> movieTime2; cout << flush; cout << "\tEnter Hall Number for Movie: Hall "; cin >> hallNumber; cout << flush; cout << "\tEnter Price of Movie Ticket: RM"; cin >> ticketPrice; // 写入修改后的记录 outFile << movieTitle << " " << movieTime2 << " " << hallNumber << " " << ticketPrice << endl; } else { // 写入未修改的记录 outFile << item.movieName << " " << item.movieTime << " " << item.hallNum << " " << item.moviePrice << endl; } } // 如果未找到目标记录,提示用户 if (!found) { cout << "\tMovie not found!" << endl; } outFile.close(); inFile.close(); remove("movieRecord.dat"); rename("temp.dat", "movieRecord.dat"); cout << "\tEdit Saved!" << endl; system("pause"); goto adminMenu;
关键修改点:
- 用
while (inFile >> ...)循环读取所有记录,替代eof()判断(eof()会在读取到文件末尾后才触发,容易导致多读取一次无效数据)。 - 用
strcmp正确比较字符串内容。 - 循环内处理所有记录,找到目标记录则写入修改后的内容,否则原样写入,避免数据丢失。
- 处理输入时的换行符残留,避免
getline读取空内容。
2. 修复文件读取代码
#include <iomanip> // ... ifstream movieCheck("movieRecord.dat"); if (!movieCheck.is_open()) { cout << "File Open Error!" << endl; return; // 或其他错误处理逻辑 } // 循环读取所有文本格式的记录 while (movieCheck >> item.movieName >> item.movieTime >> item.hallNum >> item.moviePrice) { cout << "\tMovie title: " << item.movieName << endl; cout << fixed << setprecision(2); cout << "\tTime: " << item.movieTime << endl; cout << "\tHall Number: Hall " << item.hallNum << endl; cout << "\tMovie Ticket Price: RM " << item.moviePrice << endl; cout << "\t==============================================" << endl; } movieCheck.close(); cout << endl << "\t The End of the Movie Summaries!" << endl;
关键修改点:
- 移除
read()二进制读取,统一使用文本模式的>>读取,和写入格式匹配。 - 用
!movieCheck.is_open()更准确判断文件是否打开成功。 - 简化循环逻辑,直接通过
>>的返回值判断是否读取到有效记录。
内容的提问来源于stack exchange,提问作者Jin
相关产品推荐
相关产品推荐

