guguabiu

导航

实验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 private:
15     string label;
16 };
17 Button::Button(const string &text):label{text}{
18 }
19 inline string Button::get_label() const {
20     return label;
21 }
22 
23 void Button::click(){
24     cout << "Button'" << label << "'clicked\n";
25 }
View Code

window.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 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 private:
17     string title;
18     vector<Button> buttons;
19 };
20 window::window(const string &win_title):title{win_title}{
21     buttons.push_back(Button("close"));
22 }
23 
24 inline void window::display() const {
25     string s(40,'*');
26     
27     cout << s << endl;
28     cout << "window title:" << title << endl;
29     cout << "It has " << buttons.size() << "buttons: " << endl;
30     for(const auto &i:buttons)
31         cout << i.get_label() << "button" << endl;
32     cout << s << endl;
33 }
34 
35 void window::close(){
36     cout << "close window '" << title << "'" << endl;
37     buttons.at(0).click();
38 }
39 
40 void window::add_button(const string &label){
41     buttons.push_back(Button(label));
42 }
View Code

task1.cpp:

 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 }
View Code

问题1:自定义了Button类、Window类,使用到了标准库中的string类、vector类、iostream类;Button类和Window类存在组合关系。

问题2:不适合。Button类中click是修改目标状态,不适合加const,同时涉及到输出操作,不适合设置成inline;

                           Window类中display较长,不适合设置成inline;close会调用click,不适合加const,同时close相对较长,不适合设置成inline;

问题3:创建s字符串,并初始化为包含40个*的字符串。

任务2:

task2.cpp:

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

 

问题1:将v1初始化为42,42,42,42,42;复制构造v2,让v2初始化为v1的值;将v1内0号元素42替换成-999;

问题2:将v1初始化为{1,2,3},{4,5,6,7};复制构造v2,让v2初始化为v1的值,v2的值不可改变;让v1内{1,2,3}最末尾加上-999;

问题3:让t1等于{1,2,3,-999},然后输出t1中3号元素-999;让t2等于{1,2,3},然后输出2号元素3.

问题4:深复制 ;需要。

任务3:

vectorInt.hpp:

 1 #pragma once
 2 #include <iostream>
 3 #include <cassert>
 4 
 5 using std::cout;
 6 using std::endl;
 7 
 8 class vectorInt{
 9 public:
10     vectorInt(int n);
11     vectorInt(int n, int value);
12     vectorInt(const vectorInt &vi);
13     ~vectorInt();
14     int& at(int index);
15     const int& at(int index) const;
16     vectorInt& assign(const vectorInt &v);
17     int get_size() const;
18 private:
19     int size;
20     int *ptr;      
21 };
22 
23 vectorInt::vectorInt(int n): size{n}, ptr{new int[size]} {
24 }
25 
26 vectorInt::vectorInt(int n, int value): size{n}, ptr{new int[size]} {
27     for(auto i = 0; i < size; ++i)
28         ptr[i] = value;
29 }
30 
31 vectorInt::vectorInt(const vectorInt &vi): size{vi.size}, ptr{new int[size]} {
32     for(auto i = 0; i < size; ++i)
33         ptr[i] = vi.ptr[i];
34 }
35 
36 vectorInt::~vectorInt() {
37     delete [] ptr;
38 }
39 
40 const int& vectorInt::at(int index) const {
41     assert(index >= 0 && index < size);
42 
43     return ptr[index];
44 }
45 
46 int& vectorInt::at(int index) {
47     assert(index >= 0 && index < size);
48 
49     return ptr[index];
50 }
51 
52 vectorInt& vectorInt::assign(const vectorInt &v) {  
53     delete[] ptr;       
54     size = v.size;
55     ptr = new int[size];
56     for(int i = 0; i < size; ++i)
57         ptr[i] = v.ptr[i];
58     return *this;
59 }
60 
61 int vectorInt::get_size() const {
62     return size;
63 }
View Code

task3.cpp:

 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 void test1() {
14     int n;
15     cout << "Enter n: ";
16     cin >> n;
17     vectorInt x1(n);
18     for(auto i = 0; i < n; ++i)
19         x1.at(i) = i*i;
20     cout << "x1: ";  output(x1);
21     vectorInt x2(n, 42);
22     vectorInt x3(x2);
23     x2.at(0) = -999;
24     cout << "x2: ";  output(x2);
25     cout << "x3: ";  output(x3);
26 }
27 
28 void test2() {
29     const vectorInt  x(5, 42);
30     vectorInt y(10, 0);
31     cout << "y: ";  output(y);
32     y.assign(x);
33     cout << "y: ";  output(y);
34     cout << "x.at(0) = " << x.at(0) << endl;
35     cout << "y.at(0) = " << y.at(0) << endl;
36 }
37 
38 int main() {
39     cout << "测试1: \n";
40     test1();
41     cout << "\n测试2: \n";
42     test2();
43 }
View Code

问题1:深复制;

问题2:能正确运行;在const方法中返回一个非const引用,可能导致编译错误;

问题3:可以改,但意义不大。返回*this可以确保获得对同一对象的引用;

问题4:标准库可以自动扩展和缩减容量,自定义需要手动管理内存,容易内存泄漏;标准库能够在多种情况下提供较好的性能,自定义性能取决于实现语句,可能会表现不佳。

任务4:

matrix.hpp:

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

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 const int N = 1000;
10 
11 void output(const Matrix &m, int index) {
12     assert(index >= 0 && index < m.get_lines());
13     for(auto j = 0; j < m.get_cols(); ++j)
14         cout << m.at(index, j) << ", ";
15     cout << "\b\b \n";
16 }
17 
18 void test1() {
19     double x[1000] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
20     int n, m;
21     cout << "Enter n and m: ";
22     cin >> n >> m;
23     Matrix m1(n, m);   
24     m1.set(x);          
25     Matrix m2(m, n);    
26     m2.set(x);          
27     Matrix m3(2);       
28     m3.set(x);          
29     cout << "矩阵对象m1: \n";   m1.display();  cout << endl;
30     cout << "矩阵对象m2: \n";   m2.display();  cout << endl;
31     cout << "矩阵对象m3: \n";   m3.display();  cout << endl;
32 }
33 
34 void test2() {
35     Matrix m1(2, 3);
36     m1.clear();
37     const Matrix m2(m1);
38     m1.at(0, 0) = -999;
39     cout << "m1.at(0, 0) = " << m1.at(0, 0) << endl;
40     cout << "m2.at(0, 0) = " << m2.at(0, 0) << endl;
41     cout << "矩阵对象m1第0行: "; output(m1, 0);
42     cout << "矩阵对象m2第0行: "; output(m2, 0);
43 }
44 
45 int main() {
46     cout << "测试1: \n";
47     test1();
48     cout << "测试2: \n";
49     test2();
50 }
View Code

任务5:

user.hpp:

 1 #pragma once
 2 
 3 #include<iostream>
 4 #include<string>
 5 #include<vector>
 6 
 7 using namespace std;
 8 
 9 class User {
10 public:
11     User(const string &name, const string &password = "123456", const string &email = "");
12     void set_email();
13     void change_password();
14     void display() const;
15 private:
16     string name;     
17     string password; 
18     string email;    
19 };
20 
21 User(const string &name, const string &password = "123456", const string &email = "")
22         : name(name), password(password), email(email) {}
23 
24 void set_email() {
25     cout << "Enter email address: ";
26     cin >> email; 
27     cout << "email is set successfully..." << endl;
28 }
29     
30 void change_password() {
31     string old_password;
32     cout << "Enter old password: ";
33     cin >> old_password;
34     int i = 1;
35     while (i < 3) {
36         if (old_password == password) {
37             string new_password;
38             cout << "Enter new password: ";
39             cin >> new_password;
40             password = new_password;
41             cout << "eew password is set successfully..." << endl;
42             return;
43         } else {
44             cout << "password input error. Please re-enter again: ";
45             cin >> old_password;
46             i++;
47         }
48     }
49     cout << "password input error. Please try after a while." << endl;
50 }
51 
52 void display() const {
53     cout << "name:  " << name << endl;
54     cout << "pass:  " << string(password.length(), '*') << endl; 
55     cout << "email: " << email << endl;
56 }

 

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 }
View Code

任务6:

date.h:

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

date.cpp:

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

account.h:

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

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 std::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 std::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 std::string& msg) const {
20     cout << "Error(#" << id << "): " << msg << endl;
21 }
22 void SavingsAccount::deposit(const Date& date, double amount, const std::string& desc) {
23     record(date, amount, desc);
24 }
25 void SavingsAccount::withdraw(const Date& date, double amount, const std::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 /date.distance(Date(date.getYear()-1,1,1));
33     if (interest != 0)
34         record(date, interest, "interest");
35     accumulation = 0;
36 }
37 void SavingsAccount::show() const {
38     cout << id << "\tBalance: " << balance;
39 }
View Code

6_25.cpp:

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

 总结:

浅复制:浅复制创建一个新对象,但它并不会递归地复制对象内部的所有嵌套对象。相反,浅复制会复制对象的引用;

深复制:深复制则会创建一个新对象,并递归地复制所有嵌套对象。这样,新对象与原始对象之间完全独立,修改新对象中的任何内容都不会影响原始对象。

posted on 2024-11-10 21:00  絮尘。  阅读(3)  评论(0编辑  收藏  举报