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

C++中std::array读取文件时重复写入最后一个数值的问题求助

问题描述

我需要处理多个包含不同数量数字的文件并计算总分。当前代码的问题是:从文件读取数字存入std::array时,文件的最后一个数字会被重复写入数组,本该在文件结束时停止。我试过用for循环,还是有同样问题,代码如下:

#include <iostream>
#include <fstream>
#include <iomanip>
#include <array>

const int kMaxSize {30};

std::array < int, kMaxSize > ProcessFile(std::ifstream &infile, int &num_grades);
double CalculateFinalGrade(std::array < int, kMaxSize > grades, int &num_grades);
int CalculateTotal(std::array < int, kMaxSize > grades, int &num_grades);
char CalculateLetter(double final_grade);

int main(){

    std::string filename{};
    std::cout << "Enter the input file: ";
    std::cin >> filename;

    std::ifstream infile { filename };

    if (!infile){
            std::cout << '\n' << filename << " does not exist.\n";
            return 1;
        }

    int num_grades {};
    double final_grade {};
    char letter_grade {};
    int points_earned {};
    int max_points {};
    std::array < int, kMaxSize > grades {};

    max_points = num_grades * 100;
    grades = ProcessFile(infile, num_grades);

    // this is block checking contents to array
    std::cout << '\n';
    for (int i{0}; i < kMaxSize; i++){
            std::cout << grades.at(i) << " ";
        }
    std::cout << '\n';
    // end of block

    final_grade = CalculateFinalGrade(grades, num_grades);
    points_earned = CalculateTotal(grades, num_grades);
    letter_grade = CalculateLetter(final_grade);

    infile.close();

    std::cout << '\n' << "Number of Grades: " << std::setw(11) << std::right << num_grades;
    std::cout << '\n' << "Total Points Earned: " << std::setw(8) << std::right << points_earned;
    std::cout << '\n'  << "Max Possible Points: " << std::setw(8) << std::right << max_points << '\n';
    std::cout << std::fixed << std::setprecision(1);
    std::cout << '\n' << "Final Grade: " << std::setw(7) << std::right << letter_grade << std::setw(8) << std::right << final_grade << "%" << '\n';

    return 0;
}

std::array <int, kMaxSize >  ProcessFile(std::ifstream &infile, int &num_grades){
    int number {};
    std::array < int, kMaxSize > grades {};
    
    infile >> number;
    while (infile){
        for (int i{0}; i < kMaxSize; i++){
            grades.at(i) = number;
            num_grades = num_grades + 1;
            infile >> number;
        }
    }

    return grades;
}

double CalculateFinalGrade(std::array < int, kMaxSize > grades, int &num_grades){
    double final_grade{};
    int max_points {};
    max_points = num_grades * 100;
    double points_earned {};
    for (int i{0}; i < kMaxSize; i++){
            points_earned += grades.at(i);
        }
    if (max_points != 0){
        final_grade = points_earned / max_points * 100;
    } else {
        final_grade = 0;
    }
    return final_grade;
}

int CalculateTotal(std::array < int, kMaxSize > grades, int &num_grades){
    double points_earned {};
    for (int i{0}; i < num_grades; i++){
            points_earned += grades.at(i);
        }
    return points_earned;
}

char CalculateLetter(double final_grade){
    if (final_grade >= 90){
        return 'A';
    } else if (final_grade < 90 && final_grade >= 80){
        return 'B';
    } else if (final_grade < 80 && final_grade >= 70){
        return 'C';
    } else if (final_grade < 70 && final_grade >= 60){
        return 'D';
    } else {
        return 'F';
    }
}
问题分析

核心问题集中在以下几点:

  • ProcessFile函数逻辑错误:先读取一个数字后进入循环,再用for循环将该数字写入数组所有位置,同时每次写入后读取下一个数字。当文件读完最后一个数字后,读取操作失败,但之前的数字会被重复写入数组剩余位置,且num_grades被错误累加至30。
  • CalculateFinalGrade遍历整个数组而非实际读取的成绩数量,会把未初始化的0计入总分,导致计算错误。
  • main函数中max_points的计算提前,此时num_grades还是0,导致该值始终为0。
修正后的代码
#include <iostream>
#include <fstream>
#include <iomanip>
#include <array>

const int kMaxSize {30};

std::array<int, kMaxSize> ProcessFile(std::ifstream &infile, int &num_grades);
double CalculateFinalGrade(std::array<int, kMaxSize> grades, int num_grades);
int CalculateTotal(std::array<int, kMaxSize> grades, int num_grades);
char CalculateLetter(double final_grade);

int main(){

    std::string filename{};
    std::cout << "Enter the input file: ";
    std::cin >> filename;

    std::ifstream infile { filename };

    if (!infile){
        std::cout << '\n' << filename << " does not exist.\n";
        return 1;
    }

    int num_grades {};
    double final_grade {};
    char letter_grade {};
    int points_earned {};
    int max_points {};
    std::array<int, kMaxSize> grades {};

    grades = ProcessFile(infile, num_grades);
    max_points = num_grades * 100;

    // 打印实际读取的成绩
    std::cout << '\n';
    for (int i{0}; i < num_grades; i++){
        std::cout << grades.at(i) << " ";
    }
    std::cout << '\n';

    points_earned = CalculateTotal(grades, num_grades);
    final_grade = CalculateFinalGrade(grades, num_grades);
    letter_grade = CalculateLetter(final_grade);

    infile.close();

    std::cout << '\n' << "Number of Grades: " << std::setw(11) << std::right << num_grades;
    std::cout << '\n' << "Total Points Earned: " << std::setw(8) << std::right << points_earned;
    std::cout << '\n' << "Max Possible Points: " << std::setw(8) << std::right << max_points << '\n';
    std::cout << std::fixed << std::setprecision(1);
    std::cout << '\n' << "Final Grade: " << std::setw(7) << std::right << letter_grade << std::setw(8) << std::right << final_grade << "%" << '\n';

    return 0;
}

std::array<int, kMaxSize> ProcessFile(std::ifstream &infile, int &num_grades){
    int number {};
    std::array<int, kMaxSize> grades {};
    num_grades = 0;

    // 读取成功且数组未满时才写入
    while (num_grades < kMaxSize && infile >> number){
        grades.at(num_grades) = number;
        num_grades++;
    }

    return grades;
}

double CalculateFinalGrade(std::array<int, kMaxSize> grades, int num_grades){
    if (num_grades == 0){
        return 0;
    }
    double points_earned = CalculateTotal(grades, num_grades);
    int max_points = num_grades * 100;
    return (points_earned / max_points) * 100;
}

int CalculateTotal(std::array<int, kMaxSize> grades, int num_grades){
    int points_earned = 0;
    for (int i{0}; i < num_grades; i++){
        points_earned += grades.at(i);
    }
    return points_earned;
}

char CalculateLetter(double final_grade){
    if (final_grade >= 90){
        return 'A';
    } else if (final_grade >= 80){
        return 'B';
    } else if (final_grade >= 70){
        return 'C';
    } else if (final_grade >= 60){
        return 'D';
    } else {
        return 'F';
    }
}
关键修正点
  • ProcessFile函数:重构读取逻辑,仅在读取成功且数组未满时写入数字并计数,彻底避免重复写入和错误计数。
  • main函数:将max_points计算移至ProcessFile调用后,确保使用正确的成绩数量。
  • CalculateFinalGrade函数:复用CalculateTotal函数,只遍历实际读取的成绩,减少冗余并避免错误累加。
  • 调试打印:修改打印逻辑,仅输出实际读取的成绩,便于验证结果。

内容的提问来源于stack exchange,提问作者Delaney Logan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 13:17:07