实验3

任务1:

button.hpp:

 1 #pragma once
 2 
 3 #include<iostream>
 4 #include<string>
 5 
 6 using std::string;
 7 using std::cout;
 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 }

window.hpp:

 1 #include "button.hpp"
 2 
 3 #include<iostream>
 4 #include<vector>
 5 
 6 using std::vector;
 7 using std::cout;
 8 using std::endl;
 9 
10 class window{
11     public:
12         window(const string &win_title);
13         void display() const;
14         void close();
15         void add_button(const string &label);
16 
17     private:
18         string title;
19         vector<Button> buttons;    
20 };
21 
22 window::window(const string &win_title):title{win_title}{
23     buttons.push_back(Button("close"));
24 }
25 
26 inline void window::display() const{
27     string s(40,'*');
28     
29     cout << s <<endl;
30     cout << "window title: " << title << endl;
31     cout << "It has " << buttons.size() << " buttons: " << endl;
32     for(const auto &i:buttons)
33         cout << i.get_label() << " button" <<endl;
34     cout << s <<endl;     
35 }
36 
37 void window::close(){
38     cout << "close window '"<< title << "'" <<endl;
39     buttons.at(0).click();
40 }
41 
42 void window::add_button(const string &label){
43     buttons.push_back(Button(label));
44 }

 

task1.cpp:

 1 #include "window.hpp"
 2 
 3 #include<iostream>
 4 
 5 using std::cout;
 6 using std::cin;
 7 
 8 void test(){
 9     window w1("new window");
10     w1.add_button("maximize");
11     w1.display();
12     w1.close();
13 }
14 
15 int main(){
16     cout << "用组合类模拟简单GUI:\n";
17     test();
18 }
结果:

 

 
问题1:这个模拟简单GUI的示例代码中,自定义了几个类?使用到了标准库的哪几个类?,哪些类和类之间存在组合关系?
答:button类和window类;用到了iostream类、string类、vector类;
问题2:在自定义类Button和Window中,有些成员函数定义时加了const, 有些设置成了inline。如果你是类的设计者,目前那些没有加const或没有设置成inline的,适合添加const,适合设置成inline吗?你的思考依据是?
答:不适合。const不可更改数据元素,而inline可以提高执行效率。
问题3:类Window的定义中,有这样一行代码,其功能是?
答:连续输出40个“*”号

 

任务2:

 

 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: ";
26     output1(v1);
27     cout << "v2: ";
28     output1(v2);
29     cout << "v1.at(0) = " << v1.at(0) << endl;
30     cout << "v2.at(0) = " << v2.at(0) << endl;
31 }
32 void test2() {
33     vector<vector<int>> v1 {{1, 2, 3}, {4, 5, 6, 7}};
34     const vector<vector<int>> v2(v1);
35     v1.at(0).push_back(-999);
36     cout << "v1: \n";
37     output2(v1);
38     cout << "v2: \n";
39     output2(v2);
40     vector<int> t1 = v1.at(0);
41     cout << t1.at(t1.size()-1) << endl;
42     const vector<int> t2 = v2.at(0);
43     cout << t2.at(t2.size()-1) << endl;
44 }
45 int main() {
46     cout << "测试1:\n";
47     test1();
48     cout << "\n测试2:\n";
49     test2();
50 }

结果:

 

问题1:

vector<int> v1(5, 42); 创建一个含5个元素均为42的vector对象v1;

const vector<int> v2(v1);创建一个vector对象v2,初始值为v1;

v1.at(0) = -999; v1中索引为0的元素赋值为-999;

问题2:

vector<vector<int>> v1{{1, 2, 3}, {4, 5, 6, 7}}; 创建一个vector类对象,包含{1, 2, 3}和{4, 5, 6, 7};
const vector<vector<int>> v2(v1);创建一个vector类对象v2,初始值为v1;

v1.at(0).push_back(-999); 在v1中索引为0的子vecto后面添加一个元素,它的值是-999

问题3:

vector<int> t1 = v1.at(0); 创建一个vector类对象t1,赋值为v1索引为0的子vector;
cout << t1.at(t1.size()-1) << endl; 输出t1的最后一个元素;

const vector<int> t2 = v2.at(0); 创建一个vector类对象t2,赋值为v2的索引为0的子vector;
cout << t2.at(t2.size()-1) << endl; 输出t2的最后一个元素

问题4:

(1)是深复制,因为v1和v2改变数据互不影响

(2)需要。

 

任务3:

 vectorInt.hpp

#pragma once
#include <iostream>
#include <cassert>
using std::cout;
using std::endl;
// 动态int数组对象类
class vectorInt {
    public:
        vectorInt(int n);
        vectorInt(int n, int value);
        vectorInt(const vectorInt &vi);
        ~vectorInt();
        int& at(int index);
        const int& at(int index) const;
        vectorInt& assign(const vectorInt &v);
        int get_size() const;
    private:
        int size;
        int *ptr; // ptr指向包含size个int的数组
};
vectorInt::vectorInt(int n): size {n}, ptr {new int[size]} {
}
vectorInt::vectorInt(int n, int value): size {n}, ptr {new int[size]} {
    for(auto i = 0; i < size; ++i)
        ptr[i] = value;
}
vectorInt::vectorInt(const vectorInt &vi): size {vi.size}, ptr {new int[size]} {
    for(auto i = 0; i < size; ++i)
        ptr[i] = vi.ptr[i];
}
vectorInt::~vectorInt() {
    delete [] ptr;
}
const int& vectorInt::at(int index) const {
    assert(index >= 0 && index < size);
    return ptr[index];
}
int& vectorInt::at(int index) {
    assert(index >= 0 && index < size);
    return ptr[index];
}
vectorInt& vectorInt::assign(const vectorInt &v) {
    delete[] ptr; // 释放对象中ptr原来指向的资源
    size = v.size;
    ptr = new int[size];
    for(int i = 0; i < size; ++i)
        ptr[i] = v.ptr[i];
    return *this;
}
int vectorInt::get_size() const {
    return size;
}

task3.cpp

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

结果:

问题1:深复制;

问题2:不能;存在安全隐患,此时返回值可被修改

问题3:可以,因为此时是深复制

 

任务4:

matrix.hpp

 1 #pragma once
 2 #include <iostream>
 3 #include <cassert>
 4 using std::cout;
 5 using std::endl;
 6 // 类Matrix的声明
 7 class Matrix {
 8     public:
 9         Matrix(int n, int m); // 构造函数,构造一个n*m的矩阵, 初始值为value
10         Matrix(int n); // 构造函数,构造一个n*n的矩阵, 初始值为value
11         Matrix(const Matrix &x); // 复制构造函数, 使用已有的矩阵X构造
12         ~Matrix();
13         void set(const double *pvalue); // 用pvalue指向的连续内存块数据按行为矩阵赋值
14         void clear(); // 把矩阵对象的值置0
15         const double& at(int i, int j) const; // 返回矩阵对象索引(i,j)的元素const引用
16         double& at(int i, int j); // 返回矩阵对象索引(i,j)的元素引用
17         int get_lines() const; // 返回矩阵对象行数
18         int get_cols() const; // 返回矩阵对象列数
19         void display() const;
20     private:
21         int lines; // 矩阵对象内元素行数
22         int cols; // 矩阵对象内元素列数
23         double *ptr;
24 };
25 // 类Matrix的实现:待补足
26 Matrix::Matrix(int n,int m):lines {n},cols {m} {
27     ptr = new double[n*m];
28 }
29 Matrix::Matrix(int n) :lines { n }, cols { n } {
30     ptr = new double[n * n];
31 }
32 Matrix::Matrix(const Matrix& x) :lines { x.lines }, cols {x.cols} {
33     ptr = new double[lines * cols];
34     for (int i = 0; i < lines * cols; i++) ptr[i] = x.ptr[i];
35 }
36 Matrix::~Matrix() {
37     delete[] ptr;
38 }
39 void Matrix::set(const double* pvalue) {
40     for (int i = 0; i < lines * cols; i++)
41         ptr[i] = pvalue[i];
42 }
43 void Matrix::clear() {
44     for (int i = 0; i < lines * cols; i++)
45         ptr[i] = 0;
46 }
47 const double& Matrix::at(int i, int j) const {
48     assert(i >= 0 && i < lines && j >= 0 && j < cols);
49     return ptr[i * cols + j];
50 }
51 double& Matrix::at(int i, int j) {
52     assert(i >= 0 && i < lines && j >= 0 && j < cols);
53     return ptr[i * cols + j];
54 }
55 int Matrix::get_lines()const {
56     return lines;
57 }
58 int Matrix::get_cols()const {
59     return cols;
60 }
61 void Matrix::display() const {
62     for (int i = 0; i < lines; i++) {
63         for (int j = 0; j < cols; j++)
64             cout << ptr[i * cols + j] << ", ";
65         cout << "\b\b \n";
66     }
67 }
68 // xxx

task4.cpp

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

结果:

任务5:

 User.hpp

 1 #pragma once
 2 
 3 #include<iostream>
 4 #include<cassert>
 5 #include<string>
 6 #include<vector>
 7 
 8 using namespace std;
 9 
10 class User {
11     public:
12         User(string username, string password = "123456", string userEmail = "");
13         ~User();
14 
15         void set_email();
16         void change_password();
17         void display();
18 
19 
20 
21 
22     private:
23         string name;
24         string email;
25         string password;
26 
27 };
28 
29 User::User(string username, string password, string userEmail):name {username}, password {password}, email {userEmail} {
30 }
31 
32 User::~User() {
33 }
34 void User::set_email() {
35     cout << "Enter email address: ";
36     while(1) {
37         string useremail;
38         cin >> useremail;
39         size_t pos = email.find('@');
40         if (pos != string::npos) {
41             email = useremail;
42             cout << "email is set successfully..." << endl;
43             break;
44         } else {
45             cout << "illegal email.Please re-enter email: ";
46         }
47     }
48 }
49 
50 
51 
52 void User::change_password() {
53     string t;
54     cout << "Enter old password:" << endl;
55     int c = 0;
56     while(c < 3) {
57         cin >> t;
58         if(t.compare(password) == 0) {
59             break;
60         } else {
61             cout << "password input error. Please re-enter angain:" << endl;
62             cin.clear();
63         }
64         ++c;
65     }
66 
67     if(c == 3) {
68         cout << "password input error. Please try after a while.";
69     } else {
70         cout << "Enter new password:" << endl;
71         cin >> password;
72         cout << "new password is set successfully...";
73     }
74 }
75 
76 
77 void User::display() {
78     cout << "name: " << name << endl;
79     cout << "pass: ";
80     for(int i = 0; i < password.size(); i++) {
81         cout << "*";
82     }
83     cout << endl;
84     cout << "eamil: " << email << endl;
85 }

 

task5.cpp

 

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

结果:

任务6:

account.h

 1 #ifndef __ACCOUNT_H__
 2 #define __ACCOUNT_H__
 3 #include "date.h"
 4 #include <string>
 5 class SavingsAccount {
 6 
 7     private:
 8         std::string id;
 9         double balance,rate,accumulation;
10         Date lastDate;
11         static double total;
12 
13         void record(const Date& date, double amount, const std::string& desc);
14 
15         void error(const std::string& msg) const;
16 
17         double accumulate(const Date& date) const {
18             return accumulation + balance * date.distance(lastDate);
19         }
20     public:
21         SavingsAccount(const Date& date, const std::string& id, double rate);
22         const std::string& getId() const {
23             return id;
24         }
25         double getBalance() const {
26             return balance;
27         }
28         double getRate() const {
29             return rate;
30         }
31         static double getTotal() {
32             return total;
33         }
34 
35         void deposit(const Date& date, double amount, const std::string& desc);
36 
37         void withdraw(const Date& date, double amount, const std::string& desc);
38 
39         void settle(const Date& date);
40 
41         void show() const;
42 };
43 #endif

 

account.cpp

 1 #include "account.h"
 2 #include <cmath>
 3 #include <iostream>
 4 using namespace std;
 5 double SavingsAccount::total = 0;
 6 SavingsAccount::SavingsAccount(const Date& date, const string& id, double rate) :id(id), balance(0), rate(rate), lastDate(date), accumulation(0) {
 7     date.show();
 8     cout << "\t#" << id << "created" << endl;
 9 }
10 void SavingsAccount::record(const Date& date, double amount, const string& desc) {
11     accumulation = accumulate(date);
12     lastDate = date;
13     amount = floor(amount * 100 + 0.5) / 100;
14     balance += amount;
15     total += amount;
16     date.show();
17     cout << "t\#" << id << "\t" << amount << "\t" << balance << "\t" << desc << endl;
18 }
19 void SavingsAccount::error(const string& msg) const {
20     cout << "Error(# " << id << " ):" << msg << endl;
21 }
22 void SavingsAccount::deposit(const Date & date, double amount, const string & desc) {
23     record(date, amount, desc);
24 }
25 void SavingsAccount::withdraw(const Date & date, double amount, const string& desc) {
26     if (amount > getBalance())
27         error("not enough money");
28     else
29         record(date, -amount, desc);
30 }
31 void SavingsAccount::settle(const Date& date) {
32     double interest = accumulate(date) * rate//计算年息
33                       / date.distance(Date(date.getYear() - 1, 1, 1));
34     if (interest != 0)
35         record(date, interest, "interest");
36     accumulation = 0;
37 }
38 void SavingsAccount::show() const {
39     cout << id << "\tBalance:" << balance;
40 }

 

date.h

 1 #ifndef __DATE_H__
 2 #define __DATE_H__
 3 class Date {
 4     private:
 5         int year,month,day,totalDays;
 6     public:
 7         Date(int year,int month,int day);
 8         int getYear()const {
 9             return year;
10         }
11         int getMonth()const {
12             return month;
13         }
14         int getDay() const {
15             return day;
16         }
17         int getMaxDay() const;
18         bool isLeapYear()const {
19             return year%4==0 && year%100!=0 ||year%400==0;
20         }
21         void show()const;
22         int distance(const Date &date)const {
23             return totalDays-date.totalDays;
24         }
25 
26 };
27 #endif / / _DATE_H__

 

date.cpp

 1 #include "date.h"
 2 #include <iostream>
 3 #include <cstdlib>
 4 using namespace std;
 5 namespace {
 6     const int DAYS_BEFORE_MONTH[] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 };
 7 }
 8 Date::Date(int year, int month, int day) : year(year), month(month), day(day) {
 9     if (day <= 0 || day > getMaxDay()) {
10         cout << "Invalid date:";
11         show();
12         cout << endl;
13         exit(1);
14     }
15     int years = year - 1;
16     totalDays = years * 365 + years / 4 - years / 100 + years / 400 + DAYS_BEFORE_MONTH[month - 1] + day;
17     if (isLeapYear() && month > 2) totalDays++;
18 }
19 int Date::getMaxDay()const {
20     if (isLeapYear() && month == 2)
21         return 29;
22     else
23         return DAYS_BEFORE_MONTH[month] - DAYS_BEFORE_MONTH[month - 1];
24 }
25 void Date::show() const {
26     cout << getYear() << " - " << getMonth() << " - " << getDay();
27 }

 

task6.cpp

 1 #include "account.h"
 2 #include <iostream>
 3 using namespace std;
 4 int main() {
 5     //起始日期
 6     Date date(2008, 11, 1);
 7     //建立几个账户
 8     SavingsAccount accounts[] = {
 9         SavingsAccount(date,"03755217",0.015),
10         SavingsAccount(date, "02342342", 0.015)
11     };
12     const int n = sizeof(accounts) / sizeof(SavingsAccount); //账户总数
13 
14     accounts[0].deposit(Date(2008, 11, 5), 5000, "salary");
15     accounts[1].deposit(Date(2008, 11, 25), 10000, "sell stock 0323");
16 
17     accounts[0].deposit(Date(2008, 12, 5), 5500, "salary");
18     accounts[1].withdraw(Date(2008, 12, 20), 4000, "buy a laptop");
19 
20     cout << endl;
21     for (int i = 0; i < n; i++) {
22         accounts[i].settle(Date(2009, 1, 1));
23         accounts[i].show();
24         cout << endl;
25     }
26     cout << "Total: " << SavingsAccount::getTotal() << endl;
27     return 0;
28 }

 

结果:

 

posted @ 2024-11-09 20:02  Bling888  阅读(3)  评论(0编辑  收藏  举报