1.实验任务1
运行代码:
Complex.h:
#pragma once#include <iostream> #include <stdexcept>// 声明 //////////////////////////////////////////////////// // 复数模板类声明 template<typename T> class Complex { public:Complex(T r = 0, T i = 0);Complex(const Complex<T>& c);T get_real() const;T get_imag() const;// 重载+=为成员函数Complex<T>& operator+=(const Complex<T>& c);// 重载<<、>>为友元函数template<typename T1>friend std::ostream& operator<<(std::ostream& out, const Complex<T1>& c);template<typename T1>friend std::istream& operator>>(std::istream& in, Complex<T1>& c);private:T real, imag; };// 普通函数声明 // 重载+用于Complex类型 template<typename T> Complex<T> operator+(const Complex<T>& c1, const Complex<T>& c2);// 重载==用于Complex类型 template<typename T> bool operator==(const Complex<T>& c1, const Complex<T>& c2);// 实现 //////////////////////////////////////////////////// // 成员函数模板实现 template<typename T> Complex<T>::Complex(T r, T i) : real{ r }, imag{ i } { }template<typename T> Complex<T>::Complex(const Complex<T>& c) : real{ c.real }, imag{ c.imag } { }template<typename T> T Complex<T>::get_real() const {return real; }template<typename T> T Complex<T>::get_imag() const {return imag; }// 重载+=为成员函数 template<typename T> Complex<T>& Complex<T>::operator+=(const Complex<T>& c) {real += c.real;imag += c.imag;return *this; }/////////////////////////////////////// // 友元函数模板实现 template<typename T1> std::ostream& operator<<(std::ostream& out, const Complex<T1>& c) {if (c.imag >= 0)out << c.real << " + " << c.imag << "i";elseout << c.real << " - " << -c.imag << "i";return out; }template<typename T1> std::istream& operator>>(std::istream& in, Complex<T1>& c) {in >> c.real >> c.imag;return in; }/////////////////////////////////////// // 普通函数模板实现 // 重载+用于Complex类型 template<typename T> Complex<T> operator+(const Complex<T>& c1, const Complex<T>& c2) {return Complex<T>(c1.get_real() + c2.get_real(),c1.get_imag() + c2.get_imag()); }// 重载==用于Complex类型 template<typename T> bool operator==(const Complex<T>& c1, const Complex<T>& c2) {return c1.get_real() == c2.get_real() &&c1.get_imag() && c2.get_imag(); }
task1.cpp:
#include "Complex.hpp" #include <iostream> #include <fstream> #include <stdexcept>void test1(); void test2();int main() {using namespace std;cout << "测试1: 复数模板类测试" << endl;test1();cout << "\n测试2: 文件I/O测试" << endl;test2(); }void test1() {using namespace std;Complex<double> c1{ 3.5, 2 }, c2;cout << "Enter c2: ";cin >> c2;cout << "c1 = " << c1 << endl;cout << "c2 = " << c2 << endl;cout << "c1 == c2: " << boolalpha << (c1 == c2) << endl;cout << "c1 + c2 = " << c1 + c2 << endl;c1 += c2;cout << "c1.real = " << c1.get_real() << endl;cout << "c1.imag = " << c1.get_imag() << endl;cout << "c1 == c2: " << boolalpha << (c1 == c2) << endl; }void test2() {using namespace std;Complex<int> c1{ 1, 2 }, c2{ 9, -7 };ofstream out("ans.txt");if (!out.is_open()) {cout << "fail to open file ans.txt to write\n";return;}out << "c1 = " << c1 << endl;out << "c2 = " << c2 << endl;out << "c1 + c2 = " << c1 + c2 << endl;out << "(c1 == c2) = " << boolalpha << (c1 == c2) << endl;out.close();cout << "测试ok!" << endl; }
运行截图:
2.实验任务2
运行代码:
Contestant.hpp:
#pragma once#include <iostream> #include <iomanip> #include <string>using std::string; using std::ostream; using std::istream; using std::setw; using std::setprecision; using std::setiosflags; using std::ios_base;// Contestant类声明 class Contestant { public:Contestant() = default;~Contestant() = default;int get_num() const { return num; }float get_time_usage() const { return time_usage; }friend ostream& operator<<(ostream& out, const Contestant& c);friend istream& operator>>(istream& in, Contestant& c);private:string no; // 学号string name; // 姓名string major; // 专业int num; // 解题数float time_usage; // 总用时 };// 友元函数实现 // 重载流插入运算符<< ostream& operator<<(ostream& out, const Contestant& c) {out << setiosflags(ios_base::left);out << setw(15) << c.no<< setw(15) << c.name<< setw(15) << c.major<< setw(5) << c.num<< setprecision(2) << c.time_usage;return out; }// 重载流提取运算符>> istream& operator>>(istream& in, Contestant& c) {in >> c.no >> c.name >> c.major >> c.num >> c.time_usage;return in; }
utils.hpp:
#include "Contestant.hpp" #include <fstream> #include <iostream> #include <string> #include <vector>// 排序函数 // 按解题数比较,解题数相同的情况下,按总用时比较,总用时越少,排名越靠前 bool compare_by_solutionInfo(const Contestant& c1, const Contestant& c2) {if (c1.get_num() > c2.get_num())return true;if (c1.get_num() == c2.get_num())return c1.get_time_usage() < c2.get_time_usage();return false; }// 把vector<Constestant>对象中的元素插入到输出流out void output(std::ostream& out, const std::vector<Contestant>& v) {for (auto& i : v)out << i << std::endl; }// 把vector<Contestant>对象中的元素写到filename文件中 void save(const std::string& filename, std::vector<Contestant>& v) {using std::ofstream;ofstream out(filename);if (!out.is_open()) {std::cout << "fail to open file to write\n";return;}output(out, v);out.close(); }// 从文件filename读取参赛选手信息到vector<Contestant>对象 void load(const std::string& filename, std::vector<Contestant>& v) {using std::ifstream;ifstream in(filename);if (!in.is_open()) {std::cout << "fail to open file to read\n";return;}std::string title_line;getline(in, title_line); // 跳过标题行int first_column;Contestant t;while (in >> first_column >> t)v.push_back(t);in.close(); }
task2.cpp:
#include "Contestant.hpp" #include "utils.hpp" #include <iostream> #include <vector> #include <algorithm>void test() {using namespace std;vector<Contestant> v;load("data2.txt", v); // 从文件加载选手信息到对象vsort(v.begin(), v.end(), compare_by_solutionInfo); // 按解题情况排序output(cout, v); // 输出对象v中信息到屏幕save("ans.txt", v); // 把对象v中选手信息保存到文件 }int main() {test(); }
运行截图:
3.实验任务3
运行代码:
Triangle.hpp:
#include <iostream> #include <stdexcept> #include <cmath>using namespace std;class Triangle { public:Triangle(double s1, double s2, double s3);~Triangle() = default;double area() const;private:double a, b, c; };Triangle::Triangle(double s1, double s2, double s3) : a{ s1 }, b{ s2 }, c{ s3 } {if (a <= 0 || b <= 0 || c <= 0)throw invalid_argument("边长出现负值");if (a + b <= c || b + c <= a || a + c <= b)throw invalid_argument("不满足任意两边之和大于第三边"); }double Triangle::area() const {double s = (a + b + c) / 2;return sqrt(s * (s - a) * (s - b) * (s - c)); }
task3.cpp:
#include "Triangle.hpp" #include <iostream> #include <fstream>void test() {using namespace std;cout << "从文件读入三角形三边边长,计算面积" << endl;ifstream in("data3.txt");if (!in.is_open()) {cout << "fail to open file to read\n";return;}double a, b, c;do {cout << "三角形边长: ";in >> a >> b >> c;cout << a << " " << b << " " << c << endl;try {Triangle t(a, b, c);cout << "三角形面积: " << t.area() << endl << endl;}catch (const exception& e) {cout << "error: " << e.what() << endl << endl;}if (in.peek() == EOF)break;} while (1);in.close(); }int main() {test(); }
运行截图:
4.实验任务4
运行代码:
Vector.hpp:
#include <iostream> #include <stdexcept> using namespace std; template <typename T> class Vector { private:T* data;int n; public:Vector(int n, int element = 0) :n(n) {if (n < 0) {throw length_error("Vector constructor:negative size");}else {data = new T[n];for (int i = 0; i < n; i++) {data[i] = element;}}}Vector(const Vector<T>& x) :n(x.n), data{ new T[n] } {for (int i = 0; i < n; i++) {data[i] = x.data[i];}}int get_size()const {return n;}T& at(int i) {if (i < 0 || i >= n) {throw out_of_range("Vector:index out of range");}return data[i];}friend void output(const Vector<T>& x){for (int i = 0; i < x.get_size(); i++) {if (i == x.get_size() - 1) {cout << x.data[i];}else{cout << x.data[i] << ",";}}cout << endl;}T& operator[](int i)const {if (i < 0 || i >= n) {throw out_of_range("Vector:index out of range");}return data[i];} };
task4.cpp:
#include <iostream> #include "Vector.hpp"void test1() {using namespace std;int n;cout << "Enter n: ";cin >> n;Vector<double> x1(n);for (auto i = 0; i < n; ++i)x1.at(i) = i * 0.7;cout << "x1: "; output(x1);Vector<int> x2(n, 42);const Vector<int> x3(x2);cout << "x2: "; output(x2);cout << "x3: "; output(x3);x2.at(0) = 77;x2.at(1) = 777;cout << "x2: "; output(x2);cout << "x3: "; output(x3); }void test2() {using namespace std;int n, index;while (cout << "Enter n and index: ", cin >> n >> index) {try {Vector<int> v(n, n);v.at(index) = -999;cout << "v: "; output(v);}catch (const exception& e) {cout << e.what() << endl;}} }int main() {cout << "测试1: 模板类接口测试\n";test1();cout << "\n测试2: 模板类异常处理测试\n";test2(); }
运行截图:
5.实验任务5
运行代码:
contestant.hpp:
#pragma once #include <iostream> #include <iomanip> #include <string> using namespace std; class contestant { private:string no;string name;string major;int grades; public:contestant() = default;~contestant() = default;string get_major() {return major;}int get_grades() {return grades;}friend ostream& operator<<(ostream& out, const contestant& c) {out << setiosflags(ios_base::left);out << setw(15) << c.no<< setw(15) << c.name<< setw(15) << c.major<< setw(15) << c.grades;return out;}friend istream& operator>>(istream& in, contestant& c) {in >> c.no >> c.name >> c.major >> c.grades;return in;} };
utils.hpp:
#include "contestant.hpp" #include <fstream> #include <iostream> #include <string> #include <vector> using namespace std; bool compared( contestant& c1, contestant& c2) {if (c1.get_major() < c2.get_major()) {return true;}if (c1.get_major() == c2.get_major()) {return c1.get_grades() > c2.get_grades();}return false; } void output(ostream& out, const vector<contestant>& v) {for (auto& i : v) {out << i << endl;} } void save(const string& filename, vector<contestant>& v) {ofstream out(filename);if (!out.is_open()) {cout << "fail to open file to write\n";return;}output(out, v);out.close(); } void load(const string& filename, vector<contestant>& v) {ifstream in(filename);if (!in.is_open()) {cout << "fail to open file to read\n";return;}string title_line;getline(in, title_line);contestant t;while (in>>t) {v.push_back(t);}in.close(); }
task5.cpp:
#include "contestant.hpp" #include "utils.hpp" #include <iostream> #include <vector> #include <algorithm> int main() {vector<contestant>v;load("data5.txt", v);sort(v.begin(), v.end(), compared);output(cout, v);save("ans.txt", v);return 0; }
运行截图:
注意:
在VS中运行时,要将data5的编码格式由utf-8改为anis才可以在控制台上显示出内容,但这样改动,ans.txt文件上的内容出现乱码