实验六

任务一

contestant.hpp

#pragma once
#include <iomanip>
#include <iostream>
#include <string>

struct Contestant {
    long   id;              // 学号
    std::string name;       // 姓名
    std::string major;      // 专业
    int    solved;          // 解题数
    int    penalty;         // 总罚时
};

// 重载<<
// 要求:姓名/专业里不含空白符
inline std::ostream& operator<<(std::ostream& out, const Contestant& c) {
    out << std::left;
    out << std::setw(15) << c.id
        << std::setw(15) << c.name
        << std::setw(15) << c.major
        << std::setw(10) << c.solved
        << std::setw(10) << c.penalty;

    return out;
}

// 重载>>
inline std::istream& operator>>(std::istream& in, Contestant& c) {
    in >> c.id >> c.name >> c.major >> c.solved >> c.penalty;

    return in;
}

utils.hpp

#pragma once
#include <fstream>
#include <iostream>
#include <stdexcept>
#include <string>
#include <vector>
#include "contestant.hpp"

// ACM 排序规则:先按解题数降序,再按罚时升序
inline bool cmp_by_solve(const Contestant& a, const Contestant& b) {
    if (a.solved != b.solved)
        return a.solved > b.solved;

    return a.penalty < b.penalty;
}

// 将结果写至任意输出流
inline void write(std::ostream& os, const std::vector<Contestant>& v) {
    for (const auto& x : v)
        os << x << '\n';
}

// 将结果打印到屏幕
inline void print(const std::vector<Contestant>& v) {
    write(std::cout, v);
}

// 将结果保存到文件
inline void save(const std::string& filename, const std::vector<Contestant>& v) {
    std::ofstream os(filename);
    if (!os)
        throw std::runtime_error("fail to open " + filename);

    write(os, v);
}

// 从文件读取信息(跳过标题行)
inline std::vector<Contestant> load(const std::string& filename) {
    std::ifstream is(filename);
    if (!is)
        throw std::runtime_error("fail to open " + filename);

    std::string line;
    std::getline(is, line);          // 跳过标题

    std::vector<Contestant> v;
    Contestant t;
    int seq;
    while (is >> seq >> t)
        v.push_back(t);

    return v;
}

task1.cpp

#pragma once
#include <fstream>
#include <iostream>
#include <stdexcept>
#include <string>
#include <vector>
#include "contestant.hpp"

// ACM 排序规则:先按解题数降序,再按罚时升序
inline bool cmp_by_solve(const Contestant& a, const Contestant& b) {
    if (a.solved != b.solved)
        return a.solved > b.solved;

    return a.penalty < b.penalty;
}

// 将结果写至任意输出流
inline void write(std::ostream& os, const std::vector<Contestant>& v) {
    for (const auto& x : v)
        os << x << '\n';
}

// 将结果打印到屏幕
inline void print(const std::vector<Contestant>& v) {
    write(std::cout, v);
}

// 将结果保存到文件
inline void save(const std::string& filename, const std::vector<Contestant>& v) {
    std::ofstream os(filename);
    if (!os)
        throw std::runtime_error("fail to open " + filename);

    write(os, v);
}

// 从文件读取信息(跳过标题行)
inline std::vector<Contestant> load(const std::string& filename) {
    std::ifstream is(filename);
    if (!is)
        throw std::runtime_error("fail to open " + filename);

    std::string line;
    std::getline(is, line);          // 跳过标题

    std::vector<Contestant> v;
    Contestant t;
    int seq;
    while (is >> seq >> t)
        v.push_back(t);

    return v;
}

data.txt

序号    学号        姓名        专业        解题数(道)    总罚时(分钟)
1    204942005    Jeny        未来专业1        4        210        
2    204942302    Alex           未来专业2        3        180
3    204942059    Bob        未来专业2        5        350                 
4    204942111    Hellen        未来专业3        2        90     
5    204942017    chappie        未来专业4        4        260     
6    204942075    Shaw        未来专业5        3        150        
7    204942076    Thomas        未来专业6        6        420      
8    204942078    Jennie        未来专业7        1        30          
9    204942079    Tibby        未来专业7        3        200        
10    204942080    Vermont        未来专业8        5        310    

data_bad.txt

序号    学号        姓名        专业        解题数(道)    总罚时(分钟)
1    204942005    Jeny        未来专业1        4        210        
2    204942302    Alex           未来专业2        3        180

3    204942059    Bob        未来专业2        5        350                 
4    204942111    Hellen        未来专业3        2        90     
5    204942017    chappie        未来专业4        4        260     
6    204942075    Shaw        未来专业5        3        150        
7    204942076    Thomas        未来专业6              
8    204942078    Jennie        未来专业7        1        30          
9    204942079    Tibby        未来专业7        3        200        
10    204942080    Vermont        未来专业8        5        310    

结果

屏幕截图 2025-12-17 090758

 1.

(1)因为std::cout的参数类型是std::ostream,而std::ofstream继承自std::ostream

(2)不用,只要设备以std::ostream&的形式提供输出能力,write()不用改动,可以复用

 2.

    if (!os) 
        throw std::runtime_error("fail to open " + filename);
if (!is) 
        throw std::runtime_error("fail to open " + filename);

(1)第一个是当输出文件无法打开时,os为失败状态,触发抛异常

         第二个是当输入文件无法打开,is为失败状态,触发抛异常

(2)在task.cpp的app()中被捕获 

处理方式:打印错误信息到标准错误输出,并return结束app()不再继续之后的流程

    try {
        contestants = load(in_file);                                      
        std::sort(contestants.begin(), contestants.end(), cmp_by_solve); 
        print(contestants);      
        save(out_file, contestants);                         
    } catch (const std::exception& e) {
        std::cerr << e.what() << '\n';
        return;
    }

3.可以,一致,因为std::sort定义为inline函数

4.

(1)

屏幕截图 2025-12-17 105328

读入使用in >> c.id >> c.name >> c.major >> c.solved >> c.penalty;,当遇到空白行时会自动跳过,但当遇到有缺失值行时,in >> c.solved 或 in >> c.penalty 会失败,流进入 failbit 状态,导致 is >> seq >> t 整体失败,while 循环终止。

 

任务二

student.hpp

#pragma once

#include <iostream>
#include <string>

class Student {
public:
    Student() = default;
    ~Student() = default;
    
    const std::string get_major() const;
    int get_grade() const;

    friend std::ostream& operator<<(std::ostream& os, const Student& s);
    friend std::istream& operator>>(std::istream& is, Student& s);

private:
    int id;   
    std::string  name;
    std::string  major;
    int          grade;  // 0-100
};

stumgr.hpp

#pragma once
#include <string>
#include <vector>
#include "student.hpp"

class StuMgr {
public:
    void load(const std::string& file);  // 加载数据文件(空格分隔)
    void sort();                         // 排序: 按专业字典序升序、同专业分数降序
    void print() const;                  // 打印到屏幕
    void save(const std::string& file) const; // 保存到文件

private:
    void write(std::ostream &os) const;  // 把数据写到任意输出流

private:
    std::vector<Student> students;
};

task2.cpp

#include <iostream>
#include <limits>
#include <string>
#include "stumgr.hpp"

const std::string in_file = "./data.txt";
const std::string out_file = "./ans.txt";

void menu() {
    std::cout << "\n**********简易应用**********\n"
                 "1. 加载文件\n"
                 "2. 排序\n"
                 "3. 打印到屏幕\n"
                 "4. 保存到文件\n"
                 "5. 退出\n"
                 "请选择:";
}

void app() {
    StuMgr mgr;

    while(true) {
        menu();
        int choice;
        std::cin >> choice;

        try {
            switch (choice) {
            case 1: mgr.load(in_file); 
                    std::cout << "加载成功\n"; break;
            case 2: mgr.sort(); 
                    std::cout << "排序已完成\n"; break;
            case 3: mgr.print(); 
                    std::cout << "打印已完成\n"; break;
            case 4: mgr.save(out_file); 
                    std::cout << "导出成功\n"; break;
            case 5: return;
            default: std::cout << "不合法输入\n";
            }
        }
        catch (const std::exception& e) {
            std::cout << "Error: " << e.what() << '\n';
        }
    }
}

int main() {
    app();
}

data.txt

学号    姓名    专业    成绩
1001    抖森    Acting    80
1002    宝爷    Music    97
1003    大眼仔    Acting    75
1004    本喵    Acting    99
1005    裘花    Acting    89
1006    小李子    Acting    92
1007    无脸男    Acting    85
1008    甜茶    Acting    91
1009    囧瑟夫    Acting    88
1010    霉霉    Music    96

data_bad.txt

学号    姓名    专业    成绩
1001    抖森    Acting    80
1002    宝爷    Music    97
1003    大眼仔    Acting    
1004    本喵    Acting    99
1005    裘花    Acting    89
1006    小李子    Acting    92
1007    无脸男    Acting    105
1008    甜茶    Acting    91
1009    囧瑟夫    Acting    88
1010    霉霉    Music    96

 

student.cpp

#include "student.hpp"

const std::string Student::get_major() const {
    return major;
}

int Student::get_grade() const {
    return grade;
}

std::ostream& operator<<(std::ostream& os, const Student& s) {
    os << s.id << ' ' << s.name << ' ' << s.major << ' ' << s.grade;
    return os;
}

std::istream& operator>>(std::istream& is, Student& s) {
    is >> s.id >> s.name >> s.major >> s.grade;
    return is;
}

 stumgr.cpp

#include <fstream>
#include <algorithm>
#include <sstream>
#include"stumgr.hpp" void StuMgr::write(std::ostream &os) const // 把数据写到任意输出流 { for (const auto& student : students) { os << student << '\n'; } } void StuMgr::load(const std::string& file) // { std::ifstream is(file); if (!is.is_open()) { throw std::runtime_error("无法打开文件: " + file); } students.clear(); std::string line; std::getline(is, line); Student t; int line_no = 1; while (std::getline(is, line)) { ++line_no; std::istringstream ss(line); if(!(ss >> t)) { std::cerr << "[load warning] bad line " << line_no << ": " << line << '\n'; continue; }else if(t.get_grade() < 0 || t.get_grade() > 100) { std::cerr << "[load warning] invalid grade at line " << line_no << ": " << line << '\n'; continue; } students.push_back(t); } } void StuMgr::sort() { if (students.empty()) { throw std::runtime_error("没有加载任何学生数据,无法排序"); return; } std::sort(students.begin(), students.end(), [](const Student& a, const Student& b) { if (a.get_major() != b.get_major()) { return a.get_major() < b.get_major(); } return a.get_grade() > b.get_grade(); }); } void StuMgr::print() const { if (students.empty()) { throw std::runtime_error("没有加载任何学生数据,无法打印"); return; } write(std::cout); } void StuMgr::save(const std::string& file) const // 保存到文件 { if(students.empty()) { throw std::runtime_error("没有加载任何学生数据,无法保存"); return; } std::ofstream out(file); if(!out) { throw std::runtime_error("无法打开文件: " + file); } write(out); }

屏幕截图 2025-12-17 112506

 

posted @ 2025-12-22 19:42  毛天佑202483290413  阅读(3)  评论(0)    收藏  举报