实验3 类和对象_基础编程2

实验任务一

 1 #pragma once
 2 #include <iostream>
 3 #include <string>
 4 
 5 using std::string;
 6 using std::cout;
 7 
 8 // 按钮类
 9 class Button {
10 public:
11     Button(const string& text);
12     string get_label() const;
13     void click();
14 
15 private:
16     string label;
17 };
18 
19 Button::Button(const string& text) : label{ text } {
20 }
21 
22 inline string Button::get_label() const {
23     return label;
24 }
25 
26 void Button::click() {
27     cout << "Button '" << label << "' clicked\n";
28 }
button.hpp
 1 #pragma once
 2 #include "button.hpp"
 3 #include <vector>
 4 #include <iostream>
 5 
 6 using std::vector;
 7 using std::cout;
 8 using std::endl;
 9 
10 // 窗口类
11 class Window {
12 public:
13     Window(const string& win_title);
14     void display() const;
15     void close();
16     void add_button(const string& label);
17 
18 private:
19     string title;
20     vector<Button> buttons;
21 };
22 
23 Window::Window(const string& win_title) : title{ win_title } {
24     buttons.push_back(Button("close"));
25 }
26 
27 inline void Window::display() const {
28     string s(40, '*');
29 
30     cout << s << endl;
31     cout << "window title: " << title << endl;
32     cout << "It has " << buttons.size() << " buttons: " << endl;
33     for (const auto& i : buttons)
34         cout << i.get_label() << " button" << endl;
35     cout << s << endl;
36 }
37 
38 void Window::close() {
39     cout << "close window '" << title << "'" << endl;
40     buttons.at(0).click();
41 }
42 
43 void Window::add_button(const string& label) {
44     buttons.push_back(Button(label));
45 }
window.hpp
 1 #include "window.hpp"
 2 #include <iostream>
 3 
 4 using std::cout;
 5 using std::cin;
 6 
 7 void test() {
 8     Window w1("new window");
 9     w1.add_button("maximize");
10     w1.display();
11     w1.close();
12 }
13 
14 int main() {
15     cout << "用组合类模拟简单GUI:\n";
16     test();
17 }
task.cpp

问题一:

自定义了两个类window,button,使用了标准库的string,vector,vector包含button,window包含vector,string则被button和window包含。

问题二:

不适合,它们有的改变了类成员,不能设为const函数,有的比较复杂,不适合做内联函数。

问题三:

构造的string可用作分割线。

实验任务二

 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 }
task2.cpp

问题一:

建立vector v1,其中有5个int元素,都为42;建立一个vector v2,用v1赋值;把v1中下表为0的元素改为-999。

问题二:

建立vector v1,其中有2个vector<int>元素;建立一个vector v2,用v1赋值,并设为常量;在v1中下表为0的元素,即第一个vector<int>后插入-999。

问题三:

建立vector t1,用v1中下表为0的元素,即第一个vector<int>赋值;输出t1的最后一项元素;建立vector t2,用v2中下表为0的元素,即第一个vector<int>赋值,因为v2是常量,所以t2必须也是常量;输出t2的最后一项元素。

实验任务三

 

 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 }
vectorint.hpp
 1 #include "vectorInt.hpp"
 2 #include <iostream>
 3 
 4 using std::cin;
 5 using std::cout;
 6 
 7 void output(const vectorInt& vi) {
 8     for (auto i = 0; i < vi.get_size(); ++i)
 9         cout << vi.at(i) << ", ";
10     cout << "\b\b \n";
11 }
12 
13 
14 void test1() {
15     int n;
16     cout << "Enter n: ";
17     cin >> n;
18 
19     vectorInt x1(n);
20     for (auto i = 0; i < n; ++i)
21         x1.at(i) = i * i;
22     cout << "x1: ";  output(x1);
23 
24     vectorInt x2(n, 42);
25     vectorInt x3(x2);
26     x2.at(0) = -999;
27     cout << "x2: ";  output(x2);
28     cout << "x3: ";  output(x3);
29 }
30 
31 void test2() {
32     const vectorInt  x(5, 42);
33     vectorInt y(10, 0);
34 
35     cout << "y: ";  output(y);
36     y.assign(x);
37     cout << "y: ";  output(y);
38 
39     cout << "x.at(0) = " << x.at(0) << endl;
40     cout << "y.at(0) = " << y.at(0) << endl;
41 }
42 
43 int main() {
44     cout << "测试1: \n";
45     test1();
46 
47     cout << "\n测试2: \n";
48     test2();
49 }
task3.cpp

问题一:

深复制。

问题二:

不行,不返回引用类型无法对原对象操作;不行,不设为const,若ptr值改变,会导致内存泄漏。

问题三:

可以,返回值不使用引用产生的副本是浅复制,是两个不一样但指向相同地址的指针(这个类主要就是个指针)。这样不会占用很多额外内存,对指针指向成员操作也是互通的。但两个指向相同地址的指针容易导致混淆,后续想析构时也很麻烦,所以还是推荐返回值使用引用。

实验任务四

 matrix.hpp

 1 #pragma once
 2 
 3 #include <iostream>
 4 #include <cassert>
 5 
 6 using std::cout;
 7 using std::endl;
 8 
 9 // 类Matrix的声明
10 class Matrix {
11 public:
12     Matrix(int n, int m);           // 构造函数,构造一个n*m的矩阵, 初始值为value
13     Matrix(int n);                  // 构造函数,构造一个n*n的矩阵, 初始值为value
14     Matrix(const Matrix& x);        // 复制构造函数, 使用已有的矩阵X构造
15     ~Matrix();
16 
17     void set(const double* pvalue);         // 用pvalue指向的连续内存块数据按行为矩阵赋值
18     void clear();                           // 把矩阵对象的值置0
19 
20     const double& at(int i, int j) const;   // 返回矩阵对象索引(i,j)的元素const引用
21     double& at(int i, int j);               // 返回矩阵对象索引(i,j)的元素引用
22 
23     int get_lines() const;                  // 返回矩阵对象行数
24     int get_cols() const;                   // 返回矩阵对象列数
25 
26     void display() const;                    // 按行显示矩阵对象元素值
27 
28 private:
29     int lines;      // 矩阵对象内元素行数
30     int cols;       // 矩阵对象内元素列数
31     double* ptr;
32 };
33 
34 // 类Matrix的实现:matrix.cpp

matrix.cpp

 1 #include<iostream>
 2 #include<cassert>
 3 #include"matrix.hpp"
 4 
 5 int value = 0;
 6 Matrix::Matrix(int n, int m) :lines{ n }, cols{ m }
 7 {
 8     ptr = new double[m * n];
 9     double* p = ptr;
10     for (int i = 0; i < m * n; i++)
11     {
12         *p = value;
13         p++;
14     }
15 }
16 Matrix::Matrix(int n) :lines{ n }, cols{ n }
17 {
18     ptr = new double[n * n];
19     double* p = ptr;
20     for (int i = 0; i < n * n; i++)
21     {
22         *p = value;
23         p++;
24     }
25 }
26 Matrix::Matrix(const Matrix& x) :lines{ x.lines }, cols{ x.cols }
27 {
28     ptr = new double[x.lines * x.cols];
29     double* p1 = ptr, * p2 = x.ptr;
30     for (int i = 0; i < x.lines * x.cols; i++)
31     {
32         *p1 = *p2;
33         p1++;
34         p2++;
35     }
36 }
37 void Matrix::set(const double* pvalue)
38 {
39     double* p1 = ptr;
40     const double* p2 = pvalue;
41     for (int i = 0; i < lines * cols; i++)
42     {
43         *p1 = *p2;
44         p1++;
45         p2++;
46     }
47 }
48 Matrix::~Matrix()
49 {
50     delete[] ptr;
51 }
52 void Matrix::clear()
53 {
54     double* p = ptr;
55     for (int i = 0; i < lines * cols; i++)
56     {
57         *p = 0;
58         p++;
59     }
60 }
61 const double& Matrix::at(int i, int j) const
62 {
63     return *(ptr + i * cols + j);
64 }
65 double& Matrix::at(int i, int j)
66 {
67     return *(ptr + i * cols + j);
68 }
69 int Matrix::get_lines() const
70 {
71     return lines;
72 }
73 int Matrix::get_cols() const
74 {
75     return cols;
76 }
77 void Matrix::display() const
78 {
79     for (int i = 0; i < lines; i++)
80     {
81         for (int j = 0; j < cols; j++)
82         {
83             cout << *(ptr + i * cols + j) << " ";
84         }
85         cout << endl;
86     }
87 }

task4.cpp

 1 #include "matrix.hpp"
 2 #include <iostream>
 3 #include <cassert>
 4 
 5 using std::cin;
 6 using std::cout;
 7 using std::endl;
 8 
 9 
10 const int N = 1000;
11 
12 // 输出矩阵对象索引为index所在行的所有元素
13 void output(const Matrix& m, int index) {
14     assert(index >= 0 && index < m.get_lines());
15 
16     for (auto j = 0; j < m.get_cols(); ++j)
17         cout << m.at(index, j) << ", ";
18     cout << "\b\b \n";
19 }
20 
21 
22 void test1() {
23     double x[1000] = { 1, 3, 5, 7, 9, 11, 13, 15, 17 };
24 
25     int n, m;
26     cout << "Enter n and m: ";
27     cin >> n >> m;
28 
29     Matrix m1(n, m);    // 创建矩阵对象m1, 大小n×m
30     m1.set(x);          // 用一维数组x的值按行为矩阵m1赋值
31 
32     Matrix m2(m, n);    // 创建矩阵对象m1, 大小m×n
33     m2.set(x);          // 用一维数组x的值按行为矩阵m1赋值
34 
35     Matrix m3(2);       // 创建一个2×2矩阵对象
36     m3.set(x);          // 用一维数组x的值按行为矩阵m4赋值
37 
38     cout << "矩阵对象m1: \n";   m1.display();  cout << endl;
39     cout << "矩阵对象m2: \n";   m2.display();  cout << endl;
40     cout << "矩阵对象m3: \n";   m3.display();  cout << endl;
41 }
42 
43 void test2() {
44     Matrix m1(2, 3);
45     m1.clear();
46 
47     const Matrix m2(m1);
48     m1.at(0, 0) = -999;
49 
50     cout << "m1.at(0, 0) = " << m1.at(0, 0) << endl;
51     cout << "m2.at(0, 0) = " << m2.at(0, 0) << endl;
52     cout << "矩阵对象m1第0行: "; output(m1, 0);
53     cout << "矩阵对象m2第0行: "; output(m2, 0);
54 }
55 
56 int main() {
57     cout << "测试1: \n";
58     test1();
59 
60     cout << "测试2: \n";
61     test2();
62 }

 

实验任务五

 user.hpp

 1 #pragma once
 2 #include<iostream>
 3 #include<string>
 4 using namespace std;
 5 
 6 class User
 7 {
 8 private:
 9     string name, password, email;
10 public:
11     User(string x);
12     User(string x, string y, string z);
13     void set_email();
14     void change_password();
15     void display() const;
16 };
17 User::User(string x) :name{ x }
18 {
19     password = "123456";
20     email = "\0";
21 }
22 User::User(string x, string y, string z) :name{ x }, password{ y }, email{ z }{}
23 void User::set_email()
24 {
25     cout << "请输入邮箱:";
26     cin >> email;
27     int t = 1;
28     while(t)
29     {
30         for (char c : email)
31         {
32             if (c == '@')
33                 t = 0;
34         }
35         if (t == 0);
36         else
37         {
38             cout << "邮箱格式错误,请再次输入:";
39             cin >> email;
40         }
41     }
42     cout << "邮箱成功创建" << endl;
43 }
44 void User::change_password()
45 {
46     string old;
47     cout << "请输入旧密码:";
48     cin >> old;
49     int i = 2;
50     while (old != password&&i)
51     {
52         cout << "密码输入错误,请重新输入:";
53         cin >> old;
54         i--;
55     }
56     if (i == 0)
57     {
58         cout << "密码输入错误次数过多,请稍后再试";
59     }
60     else
61     {
62         cout << "请输入新密码";
63         cin >> password;
64     }
65 }
66 
67 void User::display() const
68 {
69     cout << "name: " << name << endl;
70     cout << "pass:";
71     for (int i = 0; i < password.size(); i++)
72     {
73         cout << "*";
74     }
75     cout << endl;
76     cout << "email:" << email << endl;
77 }

task5.cpp

 1 #include "user.hpp"
 2 #include <iostream>
 3 #include <vector>
 4 #include <string>
 5 
 6 using std::cin;
 7 using std::cout;
 8 using std::endl;
 9 using std::vector;
10 using std::string;
11 
12 void test() {
13     vector<User> user_lst;
14 
15     User u1("Alice", "2024113", "Alice@hotmail.com");
16     user_lst.push_back(u1);
17     cout << endl;
18 
19     User u2("Bob");
20     u2.set_email();
21     u2.change_password();
22     user_lst.push_back(u2);
23     cout << endl;
24 
25     User u3("Hellen");
26     u3.set_email();
27     u3.change_password();
28     user_lst.push_back(u3);
29     cout << endl;
30 
31     cout << "There are " << user_lst.size() << " users. they are: " << endl;
32     for (auto& i : user_lst) {
33         i.display();
34         cout << endl;
35     }
36 }
37 
38 int main() {
39     test();
40 }

实验任务六

 1 #pragma once
 2 class Date 
 3 {
 4 private:
 5     int year;
 6     int month;
 7     int day;
 8     int totalDays;
 9 public:
10     Date(int year, int month, int day);
11     int getYear()const { return year; }
12     int getMonth() const { return month; }
13     int getDay()const { return day; }
14     int getMaxDay()const;
15     bool isLeapYear()const 
16     {
17         return year % 4 == 0 && year % 100 != 0 || year % 400 == 0;
18     }
19     void show()const;
20     int distance(const Date& date)const 
21     {
22         return totalDays - date.totalDays;
23     }
24 };
date.h
 1 #include"date.h"
 2 #include<iostream>
 3 #include<cstdlib>
 4 
 5 using namespace std;
 6 
 7 namespace 
 8 {
 9     const int DAYS_BEFORE_MONTH[] = { 0,31,59,90,120,151,181,212,243,273,304,334,365 };
10 }
11 Date::Date(int year, int month, int day) :year(year), month(month), day(day) 
12 {
13     if (day <= 0 || day > getMaxDay()) 
14     {
15         cout << "Invalid date: ";
16         show();
17         cout << endl;
18         exit(1);
19     }
20     int years = year - 1;
21     totalDays = year * 365 + years / 4 - years / 100 + years / 400 + DAYS_BEFORE_MONTH[month - 1] + day;
22     if (isLeapYear() && month > 2) totalDays++;
23 }
24 int Date::getMaxDay()const 
25 {
26     if (isLeapYear() && month == 2)
27         return 29;
28     else
29         return DAYS_BEFORE_MONTH[month] - DAYS_BEFORE_MONTH[month - 1];
30 }
31 void Date::show() const 
32 {
33     cout << getYear() << "-" << getMonth() << "-" << getDay();
34 }
date.cpp
 1 #pragma once
 2 #include"date.h"
 3 #include<string>
 4 
 5 class SavingsAccount 
 6 {
 7 private:
 8     std::string id;
 9     double balance;
10     double rate;
11     Date  lastDate;
12     double accumulation;
13     static double total;
14     void record(const Date& date, double amount, const std::string& desc);
15 
16     void error(const std::string& msg)const;
17 
18     double accumulate(const Date& date) const 
19     {
20         return accumulation + balance * date.distance(lastDate);
21 
22     }
23 public:
24     SavingsAccount(const Date& date, const std::string& id, double rate);
25 
26     const std::string& getId() const { return id; }
27     double getBalance() const { return balance; }
28 
29     double getRate() const { return rate; }
30 
31     static double getTotal() { return total; }
32 
33     void deposit(const Date& date, double amount, const std::string& desc);
34 
35     void withdraw(const Date& date, double amount, const std::string& desc);
36 
37     void settle(const Date& date);
38 
39     void show() const;
40 };
account.h
 1 #include "account.h"
 2 #include<cmath>
 3 #include<iostream>
 4 
 5 using namespace std;
 6 
 7 double SavingsAccount::total = 0;
 8 
 9 SavingsAccount::SavingsAccount(const Date& date, const string& id, double rate) : id(id), balance(0), rate(rate), lastDate(date), accumulation(0) 
10 {
11     date.show();
12     cout << "\t#" << id << "  created" << endl;
13 }
14 
15 void SavingsAccount::record(const Date& date, double amount, const string& desc) 
16 {
17     accumulation = accumulate(date);
18 
19     lastDate = date;
20 
21     amount = floor(amount * 100 + 0.5) / 100; //保留小数点后两位
22     balance += amount;
23     total += amount;
24     date.show();
25 
26     cout << "\t#" << id << "\t" << amount << "\t" << balance << "\t" << desc << endl;
27 
28 }
29 void SavingsAccount::error(const string& msg)const 
30 {
31     cout << "Error(#" << id << "):" << msg << endl;
32 
33 }
34 
35 void SavingsAccount::deposit(const Date& date, double amount, const string& desc) 
36 {
37     record(date, amount, desc);
38 
39 }
40 
41 void SavingsAccount::withdraw(const Date& date, double amount, const string& desc) 
42 {
43     if (amount > getBalance())
44         error("not enough money");
45     else
46         record(date, -amount, desc);
47 
48 }
49 
50 void SavingsAccount::settle(const Date& date) 
51 {
52 
53     double interest = accumulate(date) * rate / date.distance(Date(date.getYear() - 1, 1, 1)); //计算年息
54 
55     if (interest != 0)
56 
57         record(date, interest, "interest");
58 
59     accumulation = 0;
60 
61 }
62 
63 void SavingsAccount::show() const 
64 {
65     cout << id << "\tBalance:" << balance;
66 }
account.cpp
 1 #include"account.h"
 2 #include<iostream>
 3 
 4 using namespace std;
 5 
 6 int main() 
 7 {
 8     Date date(2008, 11, 1);
 9 
10     SavingsAccount accounts[] = 
11     {
12     SavingsAccount(date, "03755217", 0.015),
13     SavingsAccount(date, "02342342", 0.015)
14     };
15     const int n = sizeof(accounts) / sizeof(SavingsAccount);
16 
17     accounts[0].deposit(Date(2008, 11, 5), 5000, "salary");
18     accounts[1].deposit(Date(2008, 11, 25), 10000, "sell stock 0323");
19     accounts[0].deposit(Date(2008, 12, 5), 5500, "salary");
20     accounts[1].withdraw(Date(2008, 12, 20), 4000, "buy a laptop");
21 
22     cout << endl;
23     for (int i = 0; i < n; i++) 
24     {
25         accounts[i].settle(Date(2009, 1, 1));
26         accounts[i].show();
27         cout << endl;
28     }
29     cout << "Total: " << SavingsAccount::getTotal() << endl;
30     return 0;
31 }
task6.cpp

 

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