当前位置: 首页 > news >正文

实验06

任务1

代码

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

#include <algorithm>
#include <iostream>
#include <stdexcept>
#include <vector>
#include "contestant.hpp"
#include "utils.hpp"const std::string in_file = "./data.txt";
const std::string out_file = "./ans.txt";void app() {std::vector<Contestant> contestants;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;}
}int main() {app();
}

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;
}

运行截图

image

 

image

问题回答

问题1

(1)因为多态性,std::cout 的类型是 std::ostream,std::ofstream 继承自 std::ostream,子类对象可以隐式转换为父类引用,通过基类指针或引用可以操作派生类对象。

(2)不需要改动。

问题2

异常:

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

(1)save()函数std::ofstream打开失败时触发,可能的具体原因有输出文件无写权限、路径错误、磁盘满了等;load()函数std::ifstream打开失败,具体可能是输入文件不存在、无读权限等。

(2)异常被task1.cpp 中 app() 函数的 try-catch 块捕获。处理:

catch (const std::exception& e) {std::cerr << e.what() << '\n';  // 打印错误信息到标准错误流return;                          // 正常退出,不中断程序
}

问题3

可以。功能完全相同,性能几乎相同,结果一致。

问题4

(1)结果

image

 问题:注意到学号跑到最后去了,说明数据错位了,getline()跳过标题后,遇到空行时 is >> seq >> t 会失败,某些数据未被读取或读取错误。

任务2

代码

student.cpp

#include "student.hpp"
#include <string>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 << "\t" << s.name << "\t" << s.major << "\t" << 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 "stumgr.hpp"
#include <fstream>
#include <algorithm>
#include <stdexcept>void StuMgr::load(const std::string& file) {std::ifstream in(file);if (!in.is_open()) {throw std::runtime_error("无法打开文件: " + file);}// 跳过标题行std::string line;std::getline(in, line);students.clear();Student s;while (in >> s) {students.push_back(s);}
}void StuMgr::sort() {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 {std::cout << "学号\t姓名\t专业\t成绩\n";for (const auto& s : students) {std::cout << s << "\n";}
}void StuMgr::save(const std::string& file) const {std::ofstream out(file);if (!out.is_open()) {throw std::runtime_error("无法打开文件: " + file);}write(out);
}void StuMgr::write(std::ostream& os) const {os << "学号\t姓名\t专业\t成绩\n";for (const auto& s : students) {os << s << "\n";}
}

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();
}

运行截图

 

 

 

屏幕截图 2025-12-24 020340

222

 

http://www.jsqmd.com/news/131371/

相关文章:

  • 掌握Multisim与Ultiboard接口配置核心要点
  • 8、高效管理打印机资源:Windows 2000 服务器打印服务指南
  • 49、WPF 与其他技术的互操作性实践
  • 高边驱动MOSFET电路原理与应用:通俗解释
  • MongoDB 使用文档
  • 6、《数据处理与魅力应用开发:从本地存储到云端服务及搜索功能实现》
  • 命令行工具CLI版:程序员最爱的操作方式
  • Redis防重复点击与分布式锁
  • H7-TOOL隔离再出二代升级版,支持UART和SWD接口隔离,支持由TOOL或者目标板为隔离侧供电
  • 7、打造魅力应用:搜索与筛选功能全解析
  • 【期末复习03】单选+判断作业
  • 金属废料再造优质3D打印粉末,中体新材已打造行业应用的标杆
  • 8、打造迷人应用:共享与设置功能全解析
  • 虚拟主播后台支持:直播内容即时应答
  • 20、Windows Server 备份与恢复全攻略
  • 5、使用用户组组织用户账户的全面指南
  • 51、系统错误与崩溃问题的排查与解决
  • 1、Windows 8 开发入门与环境搭建
  • Java SpringBoot+Vue3+MyBatis 高校就业招聘系统系统源码|前后端分离+MySQL数据库
  • 2025年中间件厂商品牌全景报告:趋势、评估与选型指南
  • 飞象说口语剑桥评分报告:破解KP备考与教学痛点,提分与效率双提升
  • 21、服务器备份与恢复操作指南
  • Multisim仿真电路图实例中OTL功放的完整示例
  • 跨部门知识共享平台:打破企业信息壁垒
  • 三极管在电源控制中的角色:操作指南与安全设计
  • 2、Windows 8 开发项目模板与模拟器使用指南
  • 19、深入理解组策略管理与应用
  • 52、软件故障与性能问题排查案例解析
  • 3、构建首个项目全攻略
  • Vivado 2019.1安装空间与依赖要求解析