You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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;

问题现象

  1. 使用eof()判断读取时,仅显示第一条数据,修改后的记录无法显示:
    • 期望输出:
      Hello
      Help2  // 修改后的记录
      
    • 当前输出:
      Hello  // 未显示修改后的记录
      
  2. 使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 06:46:06