C++巩固之输入输出流

C++巩固之输入输出流

笔者在同一个地方又一次跌倒了。来看看题目的要求吧。

【问题描述】

某校运动会的跳高比赛成绩保存在一个文本文件中,里面保存有多名参赛选手的号码、姓名和跳高成绩。读取文件,输出跳高冠军的号码、姓名和跳高成绩。输入输出格式参考样例。

【输入形式】

文件输入。比赛成绩文件"scores.txt"里保存有多行内容(行数不定,最少0行),每行保存一名参赛选手的号码、姓名和跳高成绩(中间以空格分隔)。每位选手的号码为一个由数字字符组成的4位连续字符串(中间不含空格和其他字符),姓名为一个只包含大小写英文字母的连续字符串(长度不超过20,中间不含空格和其他字符),成绩为一个开区间(0,3)内的带两位小数的实数(单位为米)。文件内容格式参考样例。

【输出形式】

屏幕输出。在提示语"The champion is: “之后输出跳高冠军的号码、姓名和跳高成绩(中间均以一个空格分隔,跳高成绩保留小数点后两位,成绩后加字符’m’)。如果比赛成绩文件不存在或文件内容为空,则输出提示语"Invalid file.”。输出内容格式参考样例。

【样例输入】(文件内容)

0310 Tom 1.72

0126 Jerry 1.81

0205 Jack 1.56

【样例输出】(屏幕输出)

The champion is: 0126 Jerry 1.81m

【评分标准】

共5组测试数据,全部正确得满分。

#include <iostream>
#include <fstream>
#include <string>
#include <iomanip>
using namespace std;

/************ Begin ************/


/************* End *************/

int main()
{
    char fileName[200] = "scores.txt";
    string num, name;
    double height;
    bool bSuccess = GetChampionFromFile(fileName, &num, &name, &height);
    if(bSuccess){
        cout << fixed << setprecision(2);
        cout << "The champion is: " << num << " " << name << " " << height << "m";
    }
    else{
        cout << "Invalid file.";
    }
    return 0;
}

接下来,注意看是怎么错的。知道错在哪里很重要!!!

/** Begin **/
bool GetChampionFromFile(string fName, string * pNum, 
    string * pName, double * pHeight)
{
    fstream inFile(fName, ios::in);
    if(!inFile.is_open())
    {
        return false;
    }
    if(inFile.eof())           // 这个检验无效
        return false;

    string num, name;
    double height = -1.00;
    double temp = -1.00;
    while(inFile.good())
    {

        inFile>>num>>name>>temp;
        if(inFile.eof() && height == -1.00)
            return false;
        if(temp > height)
        {
            height = temp;
            *pNum = num;
            *pName = name;
            *pHeight = height;
        }
        height = temp;
    }
}
/*** End ***/

问题分析

1.试图用 if(inFile.eof()) return false; 在文件打开后立即判断是否为空。

inFile.eof() 仅在尝试读取到文本末尾后才会被设置为 true。直接打开空文件时 eofbit 初始状态为 0,因为尚未发生任何读取操作。

修正说明

  • 使用 while (inFile >> num >> name >> *pHeight) 作为循环条件。
  • 引入 hasValidData 变量,仅在成功读取至少一行数据时标记为 true。
  • 处理无效数据。若文件中存在格式错误(如非数字字符),inFile >> *pHeight 会失败,循环自动终止,函数返回 false。
bool GetChampionFromFile(string fName, string* pNum, string* pName, double* pHeight) {
    ifstream inFile(fName);
    if (!inFile.is_open()) 
    {
        return false; // 文件无法打开
    }

    string num, name;
    double height = -1.0;
    bool hasValidData = false;

    while (inFile >> num >> name >> *pHeight) { // 直接在条件中读取数据
        if (*pHeight > height) {
            height = *pHeight;
            *pNum = num;
            *pName = name;
            hasValidData = true; // 标记存在有效数据
        }
    }

    // 检查是否成功读取至少一条数据
    if (!hasValidData) 
    {
        return false; // 文件为空或数据无效
    }

    *pHeight = height; // 确保返回最高成绩
    return true;
}
eof() 具有滞后性:它只反映“上一次读取操作是否触发了文件末尾”,而非“文件是否为空”。

正确做法:通过实际读取操作(如 inFile >> var)的返回值或流状态判断文件是否有效。

欢迎在评论区交流你的想法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值