实验6
task 1
Contestant.hpp
1 #pragma once 2 #include<iomanip> 3 #include<iostream> 4 #include<string> 5 6 struct Contestant { 7 long id; 8 std::string name; 9 std::string major; 10 int solved; 11 int penalty; 12 }; 13 14 inline std::ostream& operator<<(std::ostream& out, const Contestant& c) { 15 out << std::left; 16 out << std::setw(15) << c.id 17 << std::setw(15) << c.name 18 << std::setw(15) << c.major 19 << std::setw(10) << c.solved 20 << std::setw(10) << c.penalty; 21 22 return out; 23 } 24 25 inline std::istream& operator>>(std::istream& in, Contestant& c) { 26 in >> c.id >> c.name >> c.major >> c.solved >> c.penalty; 27 28 return in; 29 }
utils.hpp
1 #pragma once 2 #include <fstream> 3 #include <iostream> 4 #include <stdexcept> 5 #include <string> 6 #include <vector> 7 #include "Contestant.hpp" 8 9 inline bool cmp_by_solve(const Contestant& a, const Contestant& b) { 10 if (a.solved != b.solved) 11 return a.solved > b.solved; 12 13 return a.penalty < b.penalty; 14 } 15 16 inline void write(std::ostream& os, const std::vector<Contestant>& v) { 17 for (const auto& x : v) 18 os << x << '\n'; 19 } 20 21 inline void print(const std::vector<Contestant>& v) { 22 write(std::cout, v); 23 } 24 25 inline void save(const std::string& filename, const std::vector<Contestant>& v) { 26 std::ofstream os(filename); 27 if (!os) 28 throw std::runtime_error("fail to open" + filename); 29 30 write(os, v); 31 } 32 33 inline std::vector<Contestant> load(const std::string &filename ){ 34 std::ifstream is(filename); 35 if (!is) 36 throw std::runtime_error("fail to open" + filename); 37 38 std::string line; 39 std::getline(is, line); 40 41 std::vector<Contestant> v; 42 Contestant t; 43 int seq; 44 while (is >> seq >> t) 45 v.push_back(t); 46 47 return v; 48 }
task1.cpp
1 #include<algorithm> 2 #include<iostream> 3 #include<stdexcept> 4 #include<vector> 5 #include"Contestant.hpp" 6 #include"utils.hpp" 7 8 const std::string in_file = "./data.txt"; 9 const std::string out_file = "./ans.txt"; 10 11 void app() { 12 std::vector<Contestant> contestants; 13 14 try { 15 contestants = load(in_file); 16 std::sort(contestants.begin(), contestants.end(), cmp_by_solve); 17 print(contestants); 18 save(out_file, contestants); 19 } 20 catch (const std::exception& e) { 21 std::cerr << e.what() << '\n'; 22 return; 23 } 24 } 25 26 int main() { 27 app(); 28 }

Q1:
(1)std::ostream是所有输出流的基类,std::cout是std::ostream类的对象,std::ofstream是std::ostream的派生类对象
(2)不需要改动writr()。write()只需要std::ostream类的接口。
Q2:
std::ofstream os(filename);
if (!os) throw std::runtime_error("fail to open" + filename);
std::ifstream is(filename);
if (!is) throw std::runtime_error("fail to open" + filename);
(1)尝试打开指定文件失败的时候会抛出异常
(2)
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; }
异常被app()中的try-catch捕获,若打开文件失败,会抛出runtime_error并且跳出该函数,回到app的tyr函数,e.what()会返回throw传入的字符串,然后结束整个程序。
Q3:可以替换。sort利用迭代器实现了按照解题数的降序排序,原代码在utils.hpp中定义了cmp_by_slove函数来实现这个功能,改写的lamba表达式把cmp_by_slove实现的功能就地解决
Q4:

load函数的读取时通过重载的>>(is>>seq>>t),>>会跳过空白字符;Contestant重载中的>>读取到缺失的数据时会读取失败,导致类的对象没有被初始化
task 2
Student.hpp
1 #pragma once 2 #include<iostream> 3 #include<string> 4 5 class Student { 6 public: 7 Student() = default; 8 ~Student() = default; 9 10 const std::string get_major() const; 11 int get_grade() const; 12 13 friend std::ostream& operator<<(std::ostream& os, const Student& s); 14 friend std::istream& operator>>(std::istream& is, Student& s); 15 16 private: 17 int id; 18 std::string name; 19 std::string major; 20 int grade; 21 };
Student.cpp
1 #include "Student.hpp" 2 3 const std::string Student::get_major() const { 4 return major; 5 } 6 7 int Student::get_grade() const { 8 return grade; 9 } 10 11 std::ostream& operator<<(std::ostream& os, const Student& s) { 12 os << s.id << '\t' << s.name << '\t' << s.major << '\t' << s.grade; 13 14 return os; 15 } 16 17 std::istream& operator>>(std::istream& is, Student& s) { 18 is >> s.id >> s.name >> s.major >> s.grade; 19 20 return is; 21 }
StuMgr.hpp
1 #pragma once 2 #include <string> 3 #include <vector> 4 #include "Student.hpp" 5 6 class StuMgr { 7 public: 8 void load(const std::string& file); 9 void sort(); 10 void print() const; 11 void save(const std::string& file) const; 12 13 private: 14 void write(std::ostream& os) const; 15 16 private: 17 std::vector<Student> students; 18 };
StuMgr.cpp
1 #include "StuMgr.hpp" 2 #include<fstream> 3 #include<vector> 4 #include<algorithm> 5 6 void StuMgr::load(const std::string& file) { 7 std::ifstream is(file); 8 if (!is) 9 throw std::runtime_error("fail to open" + file); 10 11 std::string line; 12 std::getline(is, line); 13 14 Student s; 15 while (is >> s) 16 students.push_back(s); 17 } 18 19 bool cmp(const Student& s1, const Student& s2) { 20 if (s1.get_major() != s2.get_major()) 21 return s1.get_major() < s2.get_major(); 22 23 return s1.get_grade() > s2.get_grade(); 24 } 25 26 void StuMgr::sort() { 27 std::sort(students.begin(), students.end(),cmp); 28 } 29 30 void StuMgr::write(std::ostream& os) const { 31 for (const auto& x : students) 32 os << x << '\n'; 33 } 34 35 void StuMgr::print() const { 36 write(std::cout); 37 } 38 39 void StuMgr::save(const std::string& file) const { 40 std::ofstream os(file); 41 if (!os) 42 throw std::runtime_error("fail to open " + file); 43 44 write(os); 45 }
task2.cpp
1 #include <iostream> 2 #include <limits> 3 #include <string> 4 #include "StuMgr.hpp" 5 6 const std::string in_file = "./data.txt"; 7 const std::string out_file = "./ans.txt"; 8 9 void menu() { 10 std::cout << "\n**********简易应用**********\n" 11 "1. 加载文件\n" 12 "2. 排序\n" 13 "3. 打印到屏幕\n" 14 "4. 保存到文件\n" 15 "5. 退出\n" 16 "请选择:"; 17 } 18 19 void app() { 20 StuMgr mgr; 21 22 while (true) { 23 menu(); 24 int choice; 25 std::cin >> choice; 26 27 try { 28 switch (choice) { 29 case 1: mgr.load(in_file); 30 std::cout << "加载成功\n"; break; 31 case 2: mgr.sort(); 32 std::cout << "排序已完成\n"; break; 33 case 3: mgr.print(); 34 std::cout << "打印已完成\n"; break; 35 case 4: mgr.save(out_file); 36 std::cout << "导出成功\n"; break; 37 case 5: return; 38 default: std::cout << "不合法输入\n"; 39 } 40 } 41 catch (const std::exception& e) { 42 std::cout << "Error: " << e.what() << '\n'; 43 } 44 } 45 } 46 47 int main() { 48 app(); 49 }


找不到指定文件

浙公网安备 33010602011771号