实验6 模板类、文件I/O和异常处理

实验任务一

  1 #pragma once
  2 
  3 #include <iostream>
  4 #include <stdexcept>
  5 
  6 // 声明
  7 ////////////////////////////////////////////////////
  8 // 复数模板类声明
  9 template<typename T>
 10 class Complex {
 11 public:
 12     Complex(T r = 0, T i = 0);
 13     Complex(const Complex<T>& c);
 14 
 15     T get_real() const;
 16     T get_imag() const;
 17 
 18     // 重载+=为成员函数
 19     Complex<T>& operator+=(const Complex<T>& c);
 20 
 21     // 重载<<、>>为友元函数
 22     template<typename T1>
 23     friend std::ostream& operator<<(std::ostream& out, const Complex<T1>& c);
 24 
 25     template<typename T1>
 26     friend std::istream& operator>>(std::istream& in, Complex<T1>& c);
 27 
 28 private:
 29     T real, imag;
 30 };
 31 
 32 // 普通函数声明
 33 // 重载+用于Complex类型
 34 template<typename T>
 35 Complex<T> operator+(const Complex<T>& c1, const Complex<T>& c2);
 36 
 37 // 重载==用于Complex类型
 38 template<typename T>
 39 bool operator==(const Complex<T>& c1, const Complex<T>& c2);
 40 
 41 
 42 // 实现
 43 ////////////////////////////////////////////////////
 44 // 成员函数模板实现
 45 template<typename T>
 46 Complex<T>::Complex(T r, T i) : real{ r }, imag{ i } {
 47 }
 48 
 49 template<typename T>
 50 Complex<T>::Complex(const Complex<T>& c) : real{ c.real }, imag{ c.imag } {
 51 }
 52 
 53 template<typename T>
 54 T Complex<T>::get_real() const {
 55     return real;
 56 }
 57 
 58 template<typename T>
 59 T Complex<T>::get_imag() const {
 60     return imag;
 61 }
 62 
 63 // 重载+=为成员函数
 64 template<typename T>
 65 Complex<T>& Complex<T>::operator+=(const Complex<T>& c) {
 66     real += c.real;
 67     imag += c.imag;
 68 
 69     return *this;
 70 }
 71 
 72 ///////////////////////////////////////
 73 // 友元函数模板实现
 74 template<typename T1>
 75 std::ostream& operator<<(std::ostream& out, const Complex<T1>& c) {
 76     if (c.imag >= 0)
 77         out << c.real << " + " << c.imag << "i";
 78     else
 79         out << c.real << " - " << -c.imag << "i";
 80 
 81     return out;
 82 }
 83 
 84 template<typename T1>
 85 std::istream& operator>>(std::istream& in, Complex<T1>& c) {
 86     in >> c.real >> c.imag;
 87 
 88     return in;
 89 }
 90 
 91 ///////////////////////////////////////
 92 // 普通函数模板实现
 93 // 重载+用于Complex类型
 94 template<typename T>
 95 Complex<T> operator+(const Complex<T>& c1, const Complex<T>& c2) {
 96     return Complex<T>(c1.get_real() + c2.get_real(),
 97         c1.get_imag() + c2.get_imag());
 98 }
 99 
100 // 重载==用于Complex类型
101 template<typename T>
102 bool operator==(const Complex<T>& c1, const Complex<T>& c2) {
103     return c1.get_real() == c2.get_real() &&
104         c1.get_imag() == c2.get_imag();
105 }
Complex.hpp

(最后一行&&应改为==)

 1 #include "Complex.hpp"
 2 #include <iostream>
 3 #include <fstream>
 4 #include <stdexcept>
 5 
 6 void test1();
 7 void test2();
 8 
 9 int main() {
10     using namespace std;
11 
12     cout << "测试1: 复数模板类测试" << endl;
13     test1();
14 
15     cout << "\n测试2: 文件I/O测试" << endl;
16     test2();
17 }
18 
19 void test1() {
20     using namespace std;
21 
22     Complex<double> c1{ 3.5, 2 }, c2;
23     cout << "Enter c2: ";
24     cin >> c2;
25     cout << "c1 = " << c1 << endl;
26     cout << "c2 = " << c2 << endl;
27     cout << "c1 == c2: " << boolalpha << (c1 == c2) << endl;
28 
29     cout << "c1 + c2 = " << c1 + c2 << endl;
30     c1 += c2;
31     cout << "c1.real = " << c1.get_real() << endl;
32     cout << "c1.imag = " << c1.get_imag() << endl;
33 
34     cout << "c1 == c2: " << boolalpha << (c1 == c2) << endl;
35 }
36 
37 void test2() {
38     using namespace std;
39 
40     Complex<int> c1{ 1, 2 }, c2{ 9, -7 };
41     ofstream out("ans.txt");
42     if (!out.is_open()) {
43         cout << "fail to open file ans.txt to write\n";
44         return;
45     }
46 
47     out << "c1 = " << c1 << endl;
48     out << "c2 = " << c2 << endl;
49     out << "c1 + c2 = " << c1 + c2 << endl;
50     out << "(c1 == c2) = " << boolalpha << (c1 == c2) << endl;
51 
52     out.close();
53     cout << "测试ok!" << endl;
54 }
task1.cpp

 

实验任务二

 1 #include "Contestant.hpp"
 2 #include "utils.hpp"
 3 #include <iostream>
 4 #include <vector>
 5 #include <algorithm>
 6 
 7 
 8 void test() {
 9     using namespace std;
10 
11     vector<Contestant> v;
12 
13     load("data2.txt", v);   // 从文件加载选手信息到对象v
14     sort(v.begin(), v.end(), compare_by_solutionInfo);  // 按解题情况排序
15     output(cout, v);    // 输出对象v中信息到屏幕
16     save("ans.txt", v); // 把对象v中选手信息保存到文件
17 }
18 
19 int main() {
20     test();
21 }
task2.cpp
 1 #pragma once
 2 
 3 #include <iostream>
 4 #include <iomanip>
 5 #include <string>
 6 
 7 using std::string;
 8 using std::ostream;
 9 using std::istream;
10 using std::setw;
11 using std::setprecision;
12 using std::setiosflags;
13 using std::ios_base;
14 
15 // Contestant类声明
16 class Contestant {
17 public:
18     Contestant() = default;
19     ~Contestant() = default;
20 
21     int get_num() const { return num; }
22     float get_time_usage() const { return time_usage; }
23 
24     friend ostream& operator<<(ostream& out, const Contestant& c);
25     friend istream& operator>>(istream& in, Contestant& c);
26 
27 private:
28     string no;          // 学号
29     string name;        // 姓名
30     string major;       // 专业
31     int num;            // 解题数
32     float time_usage;   // 总用时
33 };
34 
35 // 友元函数实现
36 // 重载流插入运算符<<
37 ostream& operator<<(ostream& out, const Contestant& c) {
38     out << setiosflags(ios_base::left);
39     out << setw(15) << c.no
40         << setw(15) << c.name
41         << setw(15) << c.major
42         << setw(5) << c.num
43         << setprecision(2) << c.time_usage;
44 
45     return out;
46 }
47 
48 // 重载流提取运算符>>
49 istream& operator>>(istream& in, Contestant& c) {
50     in >> c.no >> c.name >> c.major >> c.num >> c.time_usage;
51 
52     return in;
53 }
Contestant.hpp
 1 #pragma once
 2 
 3 #include "Contestant.hpp"
 4 #include <fstream>
 5 #include <iostream>
 6 #include <string>
 7 #include <vector>
 8 
 9 // 排序函数
10 // 按解题数比较,解题数相同的情况下,按总用时比较,总用时越少,排名越靠前
11 bool compare_by_solutionInfo(const Contestant& c1, const Contestant& c2) {
12     if (c1.get_num() > c2.get_num())
13         return true;
14 
15     if (c1.get_num() == c2.get_num())
16         return c1.get_time_usage() < c2.get_time_usage();
17 
18     return false;
19 }
20 
21 // 把vector<Constestant>对象中的元素插入到输出流out
22 void output(std::ostream& out, const std::vector<Contestant>& v) {
23     for (auto& i : v)
24         out << i << std::endl;
25 }
26 
27 
28 // 把vector<Contestant>对象中的元素写到filename文件中
29 void save(const std::string& filename, std::vector<Contestant>& v) {
30     using std::ofstream;
31 
32     ofstream out(filename);
33     if (!out.is_open()) {
34         std::cout << "fail to open file to write\n";
35         return;
36     }
37 
38     output(out, v);
39     out.close();
40 }
41 
42 // 从文件filename读取参赛选手信息到vector<Contestant>对象
43 void load(const std::string& filename, std::vector<Contestant>& v) {
44     using std::ifstream;
45 
46     ifstream in(filename);
47     if (!in.is_open()) {
48         std::cout << "fail to open file to read\n";
49         return;
50     }
51 
52     std::string title_line;
53     getline(in, title_line);     // 跳过标题行
54 
55     int first_column;
56     Contestant t;
57     while (in >> first_column >> t)
58         v.push_back(t);
59 
60     in.close();
61 }
utils.hpp

 

实验任务三

 1 #pragma once
 2 #include <iostream>
 3 #include <stdexcept>
 4 #include <cmath>
 5 
 6 using namespace std;
 7 
 8 class Triangle {
 9 public:
10     Triangle(double s1, double s2, double s3);
11     ~Triangle() = default;
12 
13     double area() const;
14 
15 private:
16     double a, b, c;
17 };
18 
19 Triangle::Triangle(double s1, double s2, double s3) : a{ s1 }, b{ s2 }, c{ s3 } {
20     if (a <= 0 || b <= 0 || c <= 0)
21         throw invalid_argument("边长出现负值");
22 
23     if (a + b <= c || b + c <= a || a + c <= b)
24         throw invalid_argument("不满足任意两边之和大于第三边");
25 }
26 
27 double Triangle::area() const {
28     double s = (a + b + c) / 2;
29     return sqrt(s * (s - a) * (s - b) * (s - c));
30 }
Triangle.hpp
 1 #include "Triangle.hpp"
 2 #include <iostream>
 3 #include <fstream>
 4 
 5 void test() {
 6     using namespace std;
 7 
 8     cout << "从文件读入三角形三边边长,计算面积" << endl;
 9 
10     ifstream in("data3.txt");
11     if (!in.is_open()) {
12         cout << "fail to open file to read\n";
13         return;
14     }
15 
16     double a, b, c;
17     do {
18         cout << "三角形边长: ";
19         in >> a >> b >> c;
20         cout << a << " " << b << " " << c << endl;
21 
22         try {
23             Triangle t(a, b, c);
24             cout << "三角形面积: " << t.area() << endl << endl;
25         }
26         catch (const exception& e) {
27             cout << "error: " << e.what() << endl << endl;
28         }
29 
30         if (in.peek() == EOF)
31             break;
32     } while (1);
33 
34     in.close();
35 }
36 
37 int main() {
38     test();
39 }
task3.cpp

 

实验任务四

Vector.hpp

 1 #pragma once
 2 
 3 #include<iostream>
 4 #include<stdexcept>
 5 #include <type_traits>
 6 
 7 using namespace std;
 8 
 9 template<typename T>
10 class Vector {
11 private:
12     int size;//元素数量
13     T* base;//基址
14 public:
15     static T Value() {
16         if constexpr (is_same<T, int>::value)
17             return 0;
18         if constexpr (is_same<T, float>::value)
19             return float(0);
20         if constexpr (is_same<T, double>::value)
21             return double(0);
22         if constexpr (is_same<T, char>::value)
23             return '\0';
24     }
25     Vector(int a,T b = Value()) {
26         if (a < 0)
27             throw length_error("negetive size!!!");
28         size = a;
29         base = new T[size];
30         for (int i = 0; i < size; i++)
31             *(base + i) = b;
32     }
33     Vector(Vector& v) {
34         size = v.size;
35         base = new T[size];
36         for (int i = 0; i < size; i++)
37             *(base + i) = *(v.base + i);
38     }
39     int get_size() const {
40         return size;
41     }
42     T& at(int a){
43         if (a > size)
44             throw out_of_range("index out of range!!!");
45         return *(base+a-1);
46     }
47     T& operator[](int a) {
48         if (a > size)
49             throw out_of_range("index out of range!!!");
50         return *(base + a - 1);
51     }
52     template<typename T>
53     friend void output(const Vector<T>& v) ;
54 
55 };
56 
57 template<typename T>
58 void output(const Vector<T>& v) {
59     for (int i = 0; i < v.size; i++)
60         cout << *(v.base + i) << " ";
61     cout << endl;
62 }
 1 #include <iostream>
 2 #include "Vector.hpp"
 3 
 4 void test1() {
 5     using namespace std;
 6 
 7     int n;
 8     cout << "Enter n: ";
 9     cin >> n;
10 
11     Vector<double> x1(n);
12     for (auto i = 0; i < n; ++i)
13         x1.at(i) = i * 0.7;
14 
15     cout << "x1: "; output(x1);
16 
17     Vector<int> x2(n, 42);
18     const Vector<int> x3(x2);
19 
20     cout << "x2: "; output(x2);
21     cout << "x3: "; output(x3);
22 
23     x2.at(0) = 77;
24     x2.at(1) = 777;
25     cout << "x2: "; output(x2);
26     cout << "x3: "; output(x3);
27 }
28 
29 void test2() {
30     using namespace std;
31 
32     int n, index;
33     while (cout << "Enter n and index: ", cin >> n >> index) {
34         try {
35             Vector<int> v(n, n);
36             v.at(index) = -999;
37             cout << "v: "; output(v);
38         }
39         catch (const exception& e) {
40             cout << e.what() << endl;
41         }
42     }
43 }
44 
45 int main() {
46     std::cout << "测试1: 模板类接口测试\n";
47     test1();
48 
49     std::cout << "\n测试2: 模板类异常处理测试\n";
50     test2();
51 }
task4.cpp

 

实验任务五

FileSort.hpp

 1 #pragma once
 2 
 3 #include<iostream>
 4 #include<string>
 5 #include<fstream>
 6 #include<iomanip>
 7 using namespace std;
 8 
 9 class inf {
10 private:
11     int number;
12     string name;
13     string major;
14     int score;
15     friend bool compare(inf& a, inf& b);//a在前则返回ture
16     friend istream& operator>>(istream& fin, inf& a);
17     friend ostream& operator<<(ostream& fout, inf& a);
18 };
19 
20 bool compare(inf& a, inf& b){
21     if (a.major > b.major)
22         return 0;
23     else if (a.major < b.major)
24         return 1;
25     else {
26         if (a.score > b.score)
27             return 1;
28         else if (a.score < b.score)
29             return 0;
30         else {
31             if (a.number > b.number)
32                 return 1;
33             else
34                 return 0;
35         }
36     }
37 }
38 
39 istream& operator>>(istream& fin, inf& a) {
40     fin >> a.number >> a.name >> a.major >> a.score;
41     return fin;
42 }
43 
44 ostream& operator<<(ostream& fout, inf& a) {
45     fout << left
46         << setw(15) << a.number
47         << setw(15) << a.name
48         << setw(15) << a.major
49         << setw(15) << a.score << endl;
50     return fout;
51 }

FileSort.cpp

 1 #include<iostream>
 2 #include<string>
 3 #include<fstream>
 4 #include<iomanip>
 5 #include<vector>
 6 #include"Filesort.hpp"
 7 using namespace std;
 8 
 9 void sort(inf& a, inf& b, bool (*compare)(inf& , inf& )) {
10     if (!compare(a, b)) {
11         inf tmp = a;
12         a = b;
13         b = tmp;
14     }        
15 }
16 int main(){
17     ifstream fin;
18     fin.open("data5.txt");
19     if (!fin.is_open())
20         cout << "Failed to open the file!" << endl;
21     vector<inf> inf_list;
22     string firstline;//跳过首行
23     getline(fin, firstline);
24     inf tmp;//临时记录
25     while (fin >> tmp)
26         inf_list.push_back(tmp);
27     fin.close();
28     bool (*t)(inf&, inf&);
29     t = compare;
30     for (int i = 0; i < inf_list.size() - 1; i++)
31         for (int j = 0; j < inf_list.size() - 1 - i; j++)
32             sort(inf_list[j], inf_list[j + 1], t);
33     //输出到屏幕
34     for (inf i : inf_list)
35         cout << i ;
36     //输出到文件
37     ofstream fout;
38     fout.open("ans5.txt");
39     if (!fout.is_open())
40         cout << "Failed to open the file!" << endl;
41     fout << left
42         << setw(15) << "Number"
43         << setw(15) << "Name"
44         << setw(15) << "Major"
45         << setw(15) << "Score" << endl;
46     for (inf i : inf_list)
47         fout << i;
48     fout.close();
49     return 0;
50 }

 

posted @ 2024-12-18 09:23  花落遥  阅读(10)  评论(0编辑  收藏  举报