实验3

task1:

 1 #pragma once
 2 
 3 #include <iostream>
 4 #include <string>
 5 
 6 using std::string;
 7 using std::cout;
 8 
 9 // 按钮类
10 class Button {
11 public:
12     Button(const string &text);
13     string get_label() const;
14     void click();
15 
16 private:
17     string label;
18 };
19 
20 Button::Button(const string &text): label{text} {
21 }
22 
23 inline string Button::get_label() const {
24     return label;
25 }
26 
27 void Button::click() {
28     cout << "Button '" << label << "' clicked\n";
29 }
30 
31 #pragma once
32 #include "button.hpp"
33 #include <vector>
34 #include <iostream>
35 
36 using std::vector;
37 using std::cout;
38 using std::endl;
39 
40 // 窗口类
41 class Window{
42 public:
43     Window(const string &win_title);
44     void display() const;
45     void close();
46     void add_button(const string &label);
47 
48 private:
49     string title;
50     vector<Button> buttons;
51 };
52 
53 Window::Window(const string &win_title): title{win_title} {
54     buttons.push_back(Button("close"));
55 }
56 
57 inline void Window::display() const {
58     string s(40, '*');
59 
60     cout << s << endl;
61     cout << "window title: " << title << endl;
62     cout << "It has " << buttons.size() << " buttons: " << endl;
63     for(const auto &i: buttons)
64         cout << i.get_label() << " button" << endl;
65     cout << s << endl;
66 }
67 
68 void Window::close() {
69     cout << "close window '" << title << "'" << endl;
70     buttons.at(0).click();
71 }
72 
73 void Window::add_button(const string &label) {
74     buttons.push_back(Button(label));
75 }
76 #include "window.hpp"
77 #include <iostream>
78 
79 using std::cout;
80 using std::cin;
81 
82 void test() {
83     Window w1("new window");
84     w1.add_button("maximize");
85     w1.display();
86     w1.close();
87 }
88 
89 int main() {
90     cout << "用组合类模拟简单GUI:\n";
91     test();
92 }
View Code

问题1:定义了button类和window类,使用了标准库中的string类和vector类,window类和button类之间存在组合关系

问题2:如果一个成员函数不修改类的成员变量,那么它可以被声明为const成员函数。如果Button类和Window类中的某些函数体较小且调用频繁,可以考虑设置为inline。但是,过度使用inline可能会导致代码膨胀,因此需要谨慎使用。

问题3:创建一个包含 40 个星号‘*’的string对象s

task2:

 1 #include <iostream>
 2 #include <vector>
 3 
 4 using namespace std;
 5 
 6 void output1(const vector<int> &v) {
 7     for(auto &i: v)
 8         cout << i << ", ";
 9     cout << "\b\b \n";
10 }
11 
12 void output2(const vector<vector<int>> v) {
13     for(auto &i: v) {
14         for(auto &j: i)
15             cout << j << ", ";
16         cout << "\b\b \n";
17     }
18 }
19 
20 void test1() {
21     vector<int> v1(5, 42);
22     const vector<int> v2(v1);
23 
24     v1.at(0) = -999;
25     cout << "v1: ";  output1(v1);
26     cout << "v2: ";  output1(v2);
27     cout << "v1.at(0) = " << v1.at(0) << endl;
28     cout << "v2.at(0) = " << v2.at(0) << endl;
29 }
30 
31 void test2() {
32     vector<vector<int>> v1{{1, 2, 3}, {4, 5, 6, 7}};
33     const vector<vector<int>> v2(v1);
34 
35     v1.at(0).push_back(-999);
36     cout << "v1: \n";  output2(v1);
37     cout << "v2: \n";  output2(v2);
38 
39     vector<int> t1 = v1.at(0);
40     cout << t1.at(t1.size()-1) << endl;
41     
42     const vector<int> t2 = v2.at(0);
43     cout << t2.at(t2.size()-1) << endl;
44 }
45 
46 int main() {
47     cout << "测试1:\n";
48     test1();
49 
50     cout << "\n测试2:\n";
51     test2();
52 }
View Code

问题1:

  1. vector<int> v1(5, 42);:创建一个名为 v1 的 vector 容器,其中包含 5 个整数元素,每个元素的值都为 42。
  2. const vector<int> v2(v1);:使用 v1 初始化一个常量 vector 容器 v2,使得 v2 的内容与 v1 完全相同。
  3. v1.at(0) = -999;:将 v1 容器中的第一个元素的值修改为 -999。

问题2:

  1. vector<vector<int>> v1{{1, 2, 3}, {4, 5, 6, 7}};:创建一个名为 v1 的二维 vector 容器,其中包含两个一维 vector,第一个一维 vector 存储 123,第二个一维 vector 存储 4567
  2. const vector<vector<int>> v2(v1);:使用 v1 初始化一个常量二维 vector 容器 v2,使得 v2 的内容与 v1 相同。
  3. v1.at(0).push_back(-999);:访问 v1 中的第一个一维 vector,然后向这个一维 vector 中添加一个元素 -999

问题3:

  1. vector<int> t1 = v1.at(0);:将 v1 中的第一个一维 vector(即最初包含 1, 2, 3 的那个)赋值给新创建的一维 vector t1
  2. cout << t1.at(t1.size()-1) << endl;:输出 t1 中最后一个元素的值。
  3. const vector<int> t2 = v2.at(0);:将 v2 中的第一个一维 vector赋值给新创建的常量一维 vector t2
  4. cout << t2.at(t2.size()-1) << endl;:输出 t2 中最后一个元素的值。

问题4:深复制;需要提供一个const成员函数作为接口。

 

task3:

  1 #pragma once
  2 
  3 #include <iostream>
  4 #include <cassert>
  5 
  6 using std::cout;
  7 using std::endl;
  8 
  9 // 动态int数组对象类
 10 class vectorInt{
 11 public:
 12     vectorInt(int n);
 13     vectorInt(int n, int value);
 14     vectorInt(const vectorInt &vi);
 15     ~vectorInt();
 16 
 17     int& at(int index);
 18     const int& at(int index) const;
 19 
 20     vectorInt& assign(const vectorInt &v);
 21     int get_size() const;
 22 
 23 private:
 24     int size;
 25     int *ptr;       // ptr指向包含size个int的数组
 26 };
 27 
 28 vectorInt::vectorInt(int n): size{n}, ptr{new int[size]} {
 29 }
 30 
 31 vectorInt::vectorInt(int n, int value): size{n}, ptr{new int[size]} {
 32     for(auto i = 0; i < size; ++i)
 33         ptr[i] = value;
 34 }
 35 
 36 vectorInt::vectorInt(const vectorInt &vi): size{vi.size}, ptr{new int[size]} {
 37     for(auto i = 0; i < size; ++i)
 38         ptr[i] = vi.ptr[i];
 39 }
 40 
 41 vectorInt::~vectorInt() {
 42     delete [] ptr;
 43 }
 44 
 45 const int& vectorInt::at(int index) const {
 46     assert(index >= 0 && index < size);
 47 
 48     return ptr[index];
 49 }
 50 
 51 int& vectorInt::at(int index) {
 52     assert(index >= 0 && index < size);
 53 
 54     return ptr[index];
 55 }
 56 
 57 vectorInt& vectorInt::assign(const vectorInt &v) {  
 58     delete[] ptr;       // 释放对象中ptr原来指向的资源
 59 
 60     size = v.size;
 61     ptr = new int[size];
 62 
 63     for(int i = 0; i < size; ++i)
 64         ptr[i] = v.ptr[i];
 65 
 66     return *this;
 67 }
 68 
 69 int vectorInt::get_size() const {
 70     return size;
 71 }
 72 #include <iostream>
 73 
 74 using std::cin;
 75 using std::cout;
 76 
 77 void output(const vectorInt &vi) {
 78     for(auto i = 0; i < vi.get_size(); ++i)
 79         cout << vi.at(i) << ", ";
 80     cout << "\b\b \n";
 81 }
 82 
 83 
 84 void test1() {
 85     int n;
 86     cout << "Enter n: ";
 87     cin >> n;
 88 
 89     vectorInt x1(n);
 90     for(auto i = 0; i < n; ++i)
 91         x1.at(i) = i*i;
 92     cout << "x1: ";  output(x1);
 93 
 94     vectorInt x2(n, 42);
 95     vectorInt x3(x2);
 96     x2.at(0) = -999;
 97     cout << "x2: ";  output(x2);
 98     cout << "x3: ";  output(x3);
 99 }
100 
101 void test2() {
102     const vectorInt  x(5, 42);
103     vectorInt y(10, 0);
104 
105     cout << "y: ";  output(y);
106     y.assign(x);
107     cout << "y: ";  output(y);
108     
109     cout << "x.at(0) = " << x.at(0) << endl;
110     cout << "y.at(0) = " << y.at(0) << endl;
111 }
112 
113 int main() {
114     cout << "测试1: \n";
115     test1();
116 
117     cout << "\n测试2: \n";
118     test2();
119 }
View Code

问题1:由于新对象的ptr指向的是新分配的内存空间,并且元素是从被复制对象逐个复制过来的,而不是简单地复制指针,所以这个复制构造函数实现的是深复制。

问题2:不能正确运行;这个const成员函数用于在const对象上访问元素。如果去掉const,那么在使用const对象调用at()函数时会出现问题。这就存在潜在的安全隐患,因为它违反了const对象的常量性原则,可能会导致在不应该修改对象的情况下意外地修改了对象。

 

task4:

  1 #include <iostream>
  2 #include <cassert>
  3 
  4 using std::cout;
  5 using std::endl;
  6 
  7 // 类Matrix的声明
  8 class Matrix {
  9 public:
 10     Matrix(int n, int m);           // 构造函数,构造一个n*m的矩阵, 初始值为value
 11     Matrix(int n);                  // 构造函数,构造一个n*n的矩阵, 初始值为value
 12     Matrix(const Matrix &x);        // 复制构造函数, 使用已有的矩阵X构造
 13     ~Matrix();
 14 
 15     void set(const double *pvalue);         // 用pvalue指向的连续内存块数据按行为矩阵赋值
 16     void clear();                           // 把矩阵对象的值置0
 17     
 18     const double& at(int i, int j) const;   // 返回矩阵对象索引(i,j)的元素const引用
 19     double& at(int i, int j);               // 返回矩阵对象索引(i,j)的元素引用
 20     
 21     int get_lines() const;                  // 返回矩阵对象行数
 22     int get_cols() const;                   // 返回矩阵对象列数
 23 
 24     void display() const;                    // 按行显示矩阵对象元素值
 25 
 26 private:
 27     int lines;      // 矩阵对象内元素行数
 28     int cols;       // 矩阵对象内元素列数
 29     double *ptr;
 30 };
 31 #include <iostream>
 32 #include <cassert>
 33 using std::cout;
 34 using std::endl;
 35 
 36 // 构造函数,构造一个 n*m 的矩阵, 初始值为默认值(未指定,这里假设为 0)
 37 Matrix::Matrix(int n, int m) : lines{n}, cols{m}, ptr{new double[n * m]} {
 38     for (int i = 0; i < n * m; ++i) {
 39         ptr[i] = 0;
 40     }
 41 }
 42 
 43 // 构造函数,构造一个 n*n 的矩阵, 初始值为默认值(未指定,这里假设为 0)
 44 Matrix::Matrix(int n) : lines{n}, cols{n}, ptr{new double[n * n]} {
 45     for (int i = 0; i < n * n; ++i) {
 46         ptr[i] = 0;
 47     }
 48 }
 49 
 50 // 复制构造函数,使用已有的矩阵 X 构造
 51 Matrix::Matrix(const Matrix& x) : lines{x.lines}, cols{x.cols}, ptr{new double[x.lines * x.cols]} {
 52     for (int i = 0; i < x.lines * x.cols; ++i) {
 53         ptr[i] = x.ptr[i];
 54     }
 55 }
 56 
 57 // 析构函数
 58 Matrix::~Matrix() {
 59     delete[] ptr;
 60 }
 61 
 62 // 用 pvalue 指向的连续内存块数据按行为矩阵对象赋值
 63 void Matrix::set(const double* pvalue) {
 64     for (int i = 0; i < lines * cols; ++i) {
 65         ptr[i] = pvalue[i];
 66     }
 67 }
 68 
 69 // 把矩阵对象的值置 0
 70 void Matrix::clear() {
 71     for (int i = 0; i < lines * cols; ++i) {
 72         ptr[i] = 0;
 73     }
 74 }
 75 
 76 // 返回矩阵对象索引(i,j)的元素引用
 77 double& Matrix::at(int i, int j) {
 78     assert(i >= 0 && i < lines && j >= 0 && j < cols);
 79     return ptr[i * cols + j];
 80 }
 81 
 82 // 返回矩阵对象索引(i,j)的元素 const 引用
 83 const double& Matrix::at(int i, int j) const {
 84     assert(i >= 0 && i < lines && j >= 0 && j < cols);
 85     return ptr[i * cols + j];
 86 }
 87 
 88 // 返回矩阵对象行数
 89 int Matrix::get_lines() const {
 90     return lines;
 91 }
 92 
 93 // 返回矩阵对象列数
 94 int Matrix::get_cols() const {
 95     return cols;
 96 }
 97 
 98 // 按行显示矩阵对象元素值
 99 void Matrix::display() const {
100     for (int i = 0; i < lines; ++i) {
101         for (int j = 0; j < cols; ++j) {
102             cout << at(i, j) << ", ";
103         }
104         cout << "\b\b \n";
105     }
106 }
107 #include <iostream>
108 #include <cassert>
109 
110 using std::cin;
111 using std::cout;
112 using std::endl;
113 
114 
115 const int N = 1000;
116 
117 // 输出矩阵对象索引为index所在行的所有元素
118 void output(const Matrix &m, int index) {
119     assert(index >= 0 && index < m.get_lines());
120 
121     for(auto j = 0; j < m.get_cols(); ++j)
122         cout << m.at(index, j) << ", ";
123     cout << "\b\b \n";
124 }
125 
126 
127 void test1() {
128     double x[1000] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
129 
130     int n, m;
131     cout << "Enter n and m: ";
132     cin >> n >> m;
133 
134     Matrix m1(n, m);    // 创建矩阵对象m1, 大小n×m
135     m1.set(x);          // 用一维数组x的值按行为矩阵m1赋值
136 
137     Matrix m2(m, n);    // 创建矩阵对象m1, 大小m×n
138     m2.set(x);          // 用一维数组x的值按行为矩阵m1赋值
139 
140     Matrix m3(2);       // 创建一个2×2矩阵对象
141     m3.set(x);          // 用一维数组x的值按行为矩阵m4赋值
142 
143     cout << "矩阵对象m1: \n";   m1.display();  cout << endl;
144     cout << "矩阵对象m2: \n";   m2.display();  cout << endl;
145     cout << "矩阵对象m3: \n";   m3.display();  cout << endl;
146 }
147 
148 void test2() {
149     Matrix m1(2, 3);
150     m1.clear();
151     
152     const Matrix m2(m1);
153     m1.at(0, 0) = -999;
154 
155     cout << "m1.at(0, 0) = " << m1.at(0, 0) << endl;
156     cout << "m2.at(0, 0) = " << m2.at(0, 0) << endl;
157     cout << "矩阵对象m1第0行: "; output(m1, 0);
158     cout << "矩阵对象m2第0行: "; output(m2, 0);
159 }
160 
161 int main() {
162     cout << "测试1: \n";
163     test1();
164 
165     cout << "测试2: \n";
166     test2();
167 }
View Code

 

 

task5:

  1 #include <iostream>
  2 #include <string>
  3 #include <vector>
  4 class User {
  5 private:
  6     std::string name;
  7     std::string password;
  8     std::string email;
  9 
 10 public:
 11     User(const std::string& n, const std::string& p = "123456", const std::string& e = "");
 12     void set_email();
 13     void change_password();
 14     void display();
 15 };
 16 
 17 // 类成员函数的实现直接放在这里
 18 User::User(const std::string& n, const std::string& p, const std::string& e) : name(n), password(p), email(e) {}
 19 
 20 void User::set_email() {
 21     std::string input_email;
 22     while (true) {
 23         std::cout << "Please enter your email: ";
 24         std::cin >> input_email;
 25         bool has_at = false;
 26         for (char c : input_email) {
 27             if (c == '@') {
 28                 has_at = true;
 29                 break;
 30             }
 31         }
 32         if (has_at) {
 33             email = input_email;
 34             break;
 35         } else {
 36             std::cout << "Invalid email. Please try again." << std::endl;
 37         }
 38     }
 39 }
 40 
 41 void User::change_password() {
 42     int attempts = 0;
 43     while (attempts < 3) {
 44         std::string old_password;
 45         std::cout << "Please enter your old password: ";
 46         std::cin >> old_password;
 47         if (old_password == password) {
 48             std::string new_password;
 49             std::cout << "Please enter your new password: ";
 50             std::cin >> new_password;
 51             password = new_password;
 52             break;
 53         } else {
 54             attempts++;
 55             std::cout << "Incorrect password. Attempts left: " << 3 - attempts << std::endl;
 56         }
 57     }
 58     if (attempts == 3) {
 59         std::cout << "Too many incorrect attempts. Try again later." << std::endl;
 60     }
 61 }
 62 
 63 void User::display() {
 64     std::string masked_password;
 65     for (size_t i = 0; i < password.length(); ++i) {
 66         masked_password += '*';
 67     }
 68     std::cout << "Name: " << name << ", Password: " << masked_password << ", Email: " << email << std::endl;
 69 }
 70 
 71 
 72 
 73 
 74 using std::cin;
 75 using std::cout;
 76 using std::endl;
 77 using std::vector;
 78 using std::string;
 79 
 80 void test() {
 81     vector<User> user_lst;
 82 
 83     User u1("Alice", "2024113", "Alice@hotmail.com");
 84     user_lst.push_back(u1);
 85     cout << endl;
 86 
 87     User u2("Bob");
 88     u2.set_email();
 89     u2.change_password();
 90     user_lst.push_back(u2);
 91     cout << endl;
 92 
 93     User u3("Hellen");
 94     u3.set_email();
 95     u3.change_password();
 96     user_lst.push_back(u3);
 97     cout << endl;
 98 
 99     cout << "There are " << user_lst.size() << " users. they are: " << endl;
100     for(auto &i: user_lst) {
101         i.display();
102         cout << endl;
103     }
104 }
105 
106 int main() {
107     test();
108 }
View Code

 

 

 

 task6:
 
  1 #pragma once
  2 class Date {
  3 private:
  4     int year;
  5     int month;
  6     int day;
  7     int totalDays;
  8 public:
  9     Date(int year, int month, int day);
 10     int getYear()const { return year; }
 11     int getMonth()const { return month; }
 12     int getDay()const { return day; }
 13     int getMaxDay()const;
 14     bool isLeapYear()const {
 15         return year % 4 == 0 && year % 100 != 0 || year % 400 == 0;
 16     }
 17     void show() const;
 18     int distance(const Date& date)const {
 19         return totalDays - date.totalDays;
 20     }
 21 };
 22  
 23 
 24 
 25 #include"date.h"
 26 #include<iostream>
 27 #include<cstdlib>
 28 using namespace std;
 29 namespace {
 30     const int DAYS_BEFIRE_MONTH[] = { 0,31,59,90,120,151,181,212,243,273,304 ,334,365 };
 31 }
 32 Date::Date(int year, int month, int day) :year(year), month(month), day(day) {
 33     if (day <= 0 || day > getMaxDay()) {
 34         cout << "Invalid date: ";
 35         show();
 36         cout << endl;
 37         exit(1);
 38     }
 39     int years = year - 1;
 40     totalDays = years * 365 + years / 4 - years / 100 + years / 400 + DAYS_BEFIRE_MONTH[month - 1] + day;
 41     if (isLeapYear() && month > 2) totalDays++;
 42 }
 43 int Date::getMaxDay()const {
 44     if (isLeapYear() &&month == 2)
 45         return 29;
 46     else return DAYS_BEFIRE_MONTH[month] - DAYS_BEFIRE_MONTH[month - 1];
 47 }
 48 void Date::show()const {
 49     cout << getYear() << "-" << getMonth() << "-" << getDay();
 50 }
 51 
 52 
 53 
 54 #pragma once
 55 #include"date.h"
 56 #include<string>
 57 using namespace std;
 58 class SavingsAccount {
 59 private:
 60     string id;
 61     double balance;
 62     double rate;
 63     Date lastDate;
 64     double accumulation;
 65     static double total;
 66     void record(const Date& date, double amount, const string& desc);
 67     void error(const string& msg) const;
 68     double accumulate(const Date& date)const {
 69         return accumulation + balance * date.distance(lastDate);
 70     }
 71 public:
 72     SavingsAccount(const Date& date, const string& id, double rate);
 73     const string& getId()const { return id; }
 74     double getBalance()const { return balance; }
 75     double getRate()const { return rate; }
 76     static double getTotal() { return total; }
 77     void deposit(const Date& date, double amount, const string& desc);
 78     void withdraw(const Date& date, double amount, const string& desc);
 79     void settle(const Date& date);
 80     void show() const;
 81 };
 82 
 83 
 84 
 85 #include"account.h"
 86 #include<cmath>
 87 #include<iostream>
 88 using namespace std;
 89 double SavingsAccount::total = 0;
 90 SavingsAccount::SavingsAccount(const Date& date, const string& id, double rate) :
 91     id(id), balance(0), rate(rate), lastDate(date), accumulation(0) {
 92     date.show();
 93     cout << "\t#" << id << "created" << endl;
 94 }
 95 void SavingsAccount::record(const Date& date, double amount, const string& desc) {
 96     accumulation = accumulate(date);
 97     lastDate = date;
 98     amount = floor(amount * 100 + 0.5) / 100;
 99     balance += amount;
100     total += amount;
101     date.show();
102     cout << "\t#" << id << "\t" << amount << "\t" << balance << "\t" << desc << endl;
103 }
104 void SavingsAccount::error(const string& msg) const {
105     cout << "Error(#" << id << "):" << msg << endl;
106 }
107 void SavingsAccount::deposit(const Date& date, double amount, const string& desc) {
108     record(date, amount, desc);
109 }
110 void SavingsAccount::withdraw(const Date& date, double amount, const string& desc) {
111     if (amount > getBalance())
112         error("not enough money");
113     else
114         record(date, -amount, desc);
115 }
116 void SavingsAccount::settle(const Date& date) {
117     double interest = accumulate(date) * rate / date.distance(Date(date.getYear() - 1, 1, 1));
118     if (interest != 0) record( date,interest,"interest" );
119     accumulation = 0;
120 }
121 void SavingsAccount::show()const {
122     cout << id << "\tBalance: " << balance;
123 }
124 
125 
126 #include"account.h"
127 #include<iostream>
128 using namespace std;
129 int main() {
130     Date date{ 2008,11,1 };
131     SavingsAccount accounts[] = {
132         SavingsAccount(date,"03755217",0.015),
133         SavingsAccount(date,"02342342",0.015)
134     };
135     const int n = sizeof(accounts) / sizeof(SavingsAccount);
136     accounts[0].deposit(Date(2008, 11, 5), 5000, "salary");
137     accounts[1].deposit(Date(2008, 11, 25), 10000, "sell stock 0323");
138     accounts[0].deposit(Date(2008, 12, 5), 5500, "salary");
139     accounts[1].withdraw(Date(2008, 12, 20), 4000, "buy a laptop");
140     cout << endl;
141     for (int i = 0; i < n; i++) {
142         accounts[i].settle(Date(2009, 1, 1));
143         accounts[i].show();
144         cout << endl;
145     }
146     cout << "Total: " << SavingsAccount::getTotal() << endl;
147     return 0;
148 }
View Code

 

posted @ 2024-11-04 17:26  瑞思白  阅读(3)  评论(0编辑  收藏  举报