實驗任務1:
原始碼button.hpp:
點選檢視程式碼
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 inline string Button::get_label() const { return label;}
23
24 void Button::click() {
25 cout<<"Button '"<<label<<"' clicked\n";
26 }
原始碼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 //視窗類
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 }
原始碼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 }
程式執行截圖:
問題1:
自定義了按鈕類Button,視窗類Window;使用到了標準庫的vector,string,iostream類
Button和Window存在組合關係
問題2:
不適合設定成inline:函式體較為複雜
不適合設定成const:涉及到了修改
問題3:
建立一個長度為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
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 cout<<"\n測試2:\n";
50 test2();
51 }
程式執行截圖:
問題1:
建立一個名為v1的vector型別物件,包含5個int型別元素,每個元素都為42
建立一個名為v2的vector型別物件,透過將v1作為引數傳遞到v2的建構函式,使v1中的所有元素複製到v2中
訪問並修改v1中的第1個成員為-999
問題2:
建立一個名為v1的vector型別物件,包含2個vector型別元素,實際上就是建立了一個二維陣列
建立一個名為v2的vector型別物件,透過將v1作為引數傳遞到v2的建構函式,使v1中的所有元素複製到v2中,且v2被宣告為const,意味著一旦建立完成將不可修改
訪問v1中的第1個成員(向量),並在其末尾新增一個新元素-999
問題3:
從v1中獲取第1個成員(向量),並將其賦值給新建立的一維向量t1
輸出一維陣列t1中的最後一個元素的值
從v2中獲取第1個成員(向量),並將其賦值給新建立的一維向量t2,且t2被宣告為const,意味著一旦建立完成將不可修改
輸出一位陣列t2中的最後一個元素的值
問題4:
①深複製
②是
實驗任務3:
原始碼vectorInt.cpp:
點選檢視程式碼
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 {
38 for(auto i=0;i<size;++i)
39 ptr[i]=vi.ptr[i];
40 }
41
42 vectorInt::~vectorInt() {
43 delete [] ptr;
44 }
45
46 const int& vectorInt::at(int index) const {
47 assert(index >= 0 && index < size);
48
49 return ptr[index];
50 }
51
52 int& vectorInt::at(int index) {
53 assert(index >= 0 && index < size);
54
55 return ptr[index];
56 }
57
58 vectorInt& vectorInt::assign(const vectorInt &v) {
59 delete[] ptr; //釋放物件中ptr原來指向的資源
60
61 size = v.size;
62 ptr = new int[size];
63
64 for(int i=0;i<size;++i)
65 ptr[i] = v.ptr[i];
66
67 return *this;
68 }
69
70 int vectorInt::get_size() const {
71 return size;
72 }
原始碼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
18 vectorInt x1(n);
19 for(auto i=0;i<n;++i)
20 x1.at(i) = i*i;
21 cout<<"x1:"; output(x1);
22
23 vectorInt x2(n,42);
24 vectorInt x3(x2);
25 x2.at(0) = -999;
26 cout<<"x2:"; output(x2);
27 cout<<"x3:"; output(x3);
28 }
29
30 void test2() {
31 const vectorInt x(5,42);
32 vectorInt y(10,0);
33
34 cout<<"y:"; output(y);
35 y.assign(x);
36 cout<<"y:"; output(y);
37
38 cout<<"x.at(0) = "<<x.at(0)<<endl;
39 cout<<"y.at(0) = "<<y.at(0)<<endl;
40 }
41
42 int main() {
43 cout<<"測試1:\n";
44 test1();
45
46 cout<<"測試2:\n";
47 test2();
48 }
程式執行截圖:
問題1:
深複製
問題2:
不能;存在安全隱患
問題3:
不能
實驗任務4:
原始碼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的實現:待補足
35 // xxx
36 Matrix::Matrix(int n, int m) : lines{ n }, cols{ m }
37 {
38 ptr = new double[n * m];
39 }
40
41 Matrix::Matrix(int n) :Matrix(n, n) {}
42
43 Matrix::Matrix(const Matrix& x) :lines{ x.lines }, cols{ x.cols }
44 {
45 ptr = new double[x.lines * x.cols];
46 for (int i = 0; i < x.lines * x.cols; i++)
47 *(ptr + i) = *(x.ptr + i);
48 }
49
50 Matrix::~Matrix() = default;
51
52 void Matrix::set(const double* pvalue)
53 {
54 for (int i = 0; i < lines * cols; i++)
55 *(ptr + i) = *(pvalue + i);
56 }
57
58 void Matrix::clear()
59 {
60 for (int i = 0; i < lines * cols; i++)
61 *(ptr + i) = 0;
62 }
63
64 const double& Matrix::at(int i, int j) const
65 {
66 return *(ptr + i * cols + j);
67 }
68
69 double& Matrix::at(int i, int j)
70 {
71 return *(ptr + i * cols + j);
72 }
73
74 int Matrix::get_lines() const
75 {
76 return lines;
77 }
78
79 int Matrix::get_cols() const
80 {
81 return cols;
82 }
83
84 void Matrix::display() const
85 {
86 for (int i = 0; i < lines; i++)
87 {
88 for (int j = 0; j < cols; j++)
89 cout << *(ptr + i * cols + j) << ", ";
90 cout << "\b\b\n";
91 }
92 }
原始碼matrix.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, 2, 3, 4, 5, 6, 7, 8, 9};
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 }
程式執行截圖:
實驗任務5:
原始碼user.hpp:
點選檢視程式碼
1 #pragma once
2
3 #include<iostream>
4 #include<string>
5
6 using std::string;
7 using std::cout;
8 using std::cin;
9 using std::endl;
10
11 class User {
12 public:
13 User(const string Name,string Password = "123456",string Email= ""): name{Name},password{Password},email{Email} {}
14 void set_email();
15 void change_password();
16 const void display();
17
18 private:
19 string name;
20 string password;
21 string email;
22 };
23
24 void User::set_email() {
25 cout<<"Enter email address:";
26
27 while(1) {
28 string temp;
29 cin>>temp;
30 if(temp.find('@') != -1) {
31 cout<<"email is set successfully..."<<endl;
32 email = temp;
33 break;
34 }
35 else
36 cout<<"illegal email.Please re-enter email:";
37 }
38 }
39
40 void User::change_password() {
41 int count = 0;
42 string oldpassword;
43 string newpassword;
44 cout<<"Enter old password:";
45 for(count = 0;count<3;count++)
46 {
47 cin>>oldpassword;
48 if(oldpassword != password) {
49 cout<<"password input error.";
50 if(count==2) {
51 cout<<"Please try after a while."<<endl;
52 }
53 else {
54 cout<<"Please re-enter again:";
55 }
56 }
57 else {
58 cout<<"Enter new password:";
59 cin>>newpassword;
60 password = newpassword;
61 cout<<"new password is set successfully..."<<endl;
62 break;
63 }
64 }
65 }
66
67 const void User::display() {
68 string temp(password.size(),'*');
69
70 cout<<"name:"<<name<<endl;
71 cout<<"password:"<< temp <<endl;
72 cout<<"email:" << email <<endl;
73 }
原始碼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 }
程式執行截圖:
實驗任務6:
原始碼date.h:
點選檢視程式碼
1 #pragma once
2 #ifndef DATE H
3 #define DATE H
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
點選檢視程式碼
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 }
點選檢視程式碼
1 #pragma once
2 #ifndef ACCOUNT H
3 #define ACCOUNT H
4 #include"date.h"
5 #include<string>
6 class SavingsAccount {
7 private:
8 std::string id;
9 double balance;
10 double rate;
11 Date lastDate;
12 double accumulation;
13 static double total;
14
15 void record(const Date& date, double amount, const std::string& desc);
16
17 void error(const std::string& msg)const;
18
19 double accumulate(const Date& date)const {
20 return accumulation + balance * date.distance(lastDate);
21 }
22 public:
23 SavingsAccount(const Date& date, const std::string& id, double rate);
24 const std::string& getId()const { return id; }
25 double getBalance()const { return balance; }
26 double getRate()const { return rate; }
27 static double getTotal() { return total; }
28
29 void deposit(const Date& date, double amount, const std::string& desc);
30
31 void withdraw(const Date& date, double amount, const std::string& desc);
32
33 void settle(const Date& date);
34
35 void show()const;
36 };
37 #endif// ACCOUNT H
點選檢視程式碼
1 #include"account.h"
2 #include<iostream>
3 #include<cmath>
4 using namespace std;
5 double SavingsAccount::total = 0;
6
7 SavingsAccount::SavingsAccount(const Date& date, const string& id, double rate) :id{ id }, balance{ 0 }, rate{ rate }, lastDate{ date }, accumulation{ 0 } {
8 date.show();
9 cout << "\t#" << id << "created" << endl;
10 }
11
12 void SavingsAccount::record(const Date& date, double amount, const string& desc) {
13 accumulation = accumulate(date);
14 lastDate = date;
15 amount = floor(amount * 100 + 0.5) / 100;
16 balance+= amount;
17 total += amount;
18 date.show();
19 cout << "\t#" << id << "\t" << amount << "\t" << balance << "\t" << desc << endl;
20 }
21
22 void SavingsAccount::error(const string& msg)const {
23 cout << "Error(#" << id << "):" << msg << endl;
24 }
25
26 void SavingsAccount::deposit(const Date& date, double amount, const string& desc) {
27 record(date, amount, desc);
28 }
29
30 void SavingsAccount::withdraw(const Date& date, double amount, const string& desc) {
31 if (amount > getBalance())
32 error("not enough money");
33 else
34 record(date, -amount, desc);
35 }
36
37 void SavingsAccount::settle(const Date& date) {
38 double interest = accumulate(date) * rate / date.distance(Date(date.getYear() - 1, 1, 1));
39 if (interest != 0)
40 record(date, interest, "interest");
41 accumulation = 0;
42 }
43
44 void SavingsAccount::show()const {
45 cout << id << "\tBalance:" << balance;
46 }
點選檢視程式碼
1 #include"account.h"
2 #include<iostream>
3 using namespace std;
4 int main() {
5 Date date(2008, 11, 1);
6
7 SavingsAccount accounts[] = {
8 SavingsAccount(date,"03755217",0.015),SavingsAccount(date,"02342342",0.015)
9 };
10 const int n = sizeof(accounts) / sizeof(SavingsAccount);
11
12 accounts[0].deposit(Date(2008, 11, 5), 5000, "salary");
13 accounts[1].deposit(Date(2008, 11, 25), 10000, "sell stock 0323");
14
15 accounts[0].deposit(Date(2008, 12, 5), 5500, "salary");
16 accounts[1].withdraw(Date(2008, 12, 20), 4000, "buy a laptop");
17
18 cout << endl;
19 for (int i = 0; i < n; i++) {
20 accounts[i].settle(Date(2009, 1, 1));
21 accounts[i].show();
22 cout << endl;
23 }
24 cout << "Total:" << SavingsAccount::getTotal() << endl;
25 return 0;
26 }
程式執行截圖: