程序设计实验3
实验任务1
1.共自定义了两个类;使用了标准库的<iostream>,<string>,<vector>类;自定义的<window>和<button>存在组合关系。
2.const适用于设定一个不能修改的值,可以使数据更加安全。inline一般用于函数较小且被多次调用。
click()不需要加const,因为它模拟了鼠标点击,不需要有固定值;
display()可以加inline,因为它会被多次调用且代码相对简单;
close()不适合加const或inline,因为不需要有固定值且不需要复杂的逻辑.
3.打印一个长度为40的*号字符串,用于打印输出时显示的边框
实验任务2
1.21行代码构造了长度为5,5个数据都是42的串,22行代码复制构造了v2=v1,24行代码将v1的第一个数据更换成-999;
2.32行创建一个包含两个内部向量的二维向量,33行复制构造v2=v1,但不能修改v2的值,35行v1.at(0)选中v1中的第一个向量,push_back将-999新增到其最后一个元素的后一位置
3.39行从v1中获取第一个向量并拷贝给t1,40行打印t1的最后一个元素,42行获取v2的第一个向量并拷贝给t2,t2的值未改变,所以输出最后一个元素为3
4.vector内部封装的复制构造函数实现机制是深复制;
需要,因为at()函数的主要目的是提供一种安全的访问vector元素的方式,如果不加const可能会改变vector内部的值造成错误。
实验任务3
1.是深复制
2.去掉&不可以运行;
如果把line18返回值类型前面的const去掉,测试代码存在安全隐患,因为at调用内部成员,可以进行修改,对数据安全造成隐患。
3.返回值类型不可以更改成vectorint
成员函数如果修改对象的状态,应该返回该对象的引用
实验任务4
1 // 构造函数,构造一个n*m的矩阵, 初始值为value 2 Matrix::Matrix(int n, int m) : lines(n), cols(m), ptr(new double[n * m]) { 3 double value = 0.0; 4 for (int i = 0; i < n * m; ++i) { 5 ptr[i] = value; 6 } 7 } 8 // 构造函数,构造一个n*n的矩阵, 初始值为value 9 Matrix::Matrix(int n) : Matrix(n, n) {} 10 11 // 复制构造函数, 使用已有的矩阵X构造 12 Matrix::Matrix(const Matrix& x) : lines(x.lines), cols(x.cols), ptr(new double[x.lines * x.cols]) { 13 for (int i = 0; i < lines * cols; ++i) { 14 ptr[i] = x.ptr[i]; 15 } 16 } 17 18 // 析构函数 19 Matrix::~Matrix() { 20 delete[] ptr; 21 } 22 23 // 用pvalue指向的连续内存块数据按行为矩阵赋值 24 void Matrix::set(const double* pvalue) { 25 for (int i = 0; i < lines; ++i) { 26 for (int j = 0; j < cols; ++j) { 27 ptr[i * cols + j] = pvalue[i * cols + j]; 28 } 29 } 30 } 31 32 // 把矩阵对象的值置0 33 void Matrix::clear() { 34 for (int i = 0; i < lines * cols; ++i) { 35 ptr[i] = 0.0; 36 } 37 } 38 39 // 返回矩阵对象索引(i,j)的元素const引用 40 const double& Matrix::at(int i, int j) const { 41 assert(i >= 0 && i < lines && j >= 0 && j < cols); 42 return ptr[i * cols + j]; 43 } 44 45 // 返回矩阵对象索引(i,j)的元素引用 46 double& Matrix::at(int i, int j) { 47 assert(i >= 0 && i < lines && j >= 0 && j < cols); 48 return ptr[i * cols + j]; 49 } 50 51 // 返回矩阵对象行数 52 int Matrix::get_lines() const { 53 return lines; 54 } 55 56 // 返回矩阵对象列数 57 int Matrix::get_cols() const { 58 return cols; 59 } 60 61 // 按行显示矩阵对象元素值 62 void Matrix::display() const { 63 for (int i = 0; i < lines; ++i) { 64 for (int j = 0; j < cols; ++j) { 65 cout << ptr[i * cols + j] << " "; 66 } 67 cout << endl; 68 } 69 }
运行结果
实验任务5
1 #pragma once 2 #include<iostream> 3 #include<string> 4 using namespace std; 5 6 class User { 7 public: 8 User(string na,string pw="123456",string em="") :name(na), password(pw), email(em) {} 9 // 设置邮箱,并进行简单合法性校验 10 void set_email() { 11 string input; 12 while (true) { 13 cout << "请输入邮箱: "; 14 cin >> input; 15 if (input.find('@') != string::npos) { 16 email = input; 17 break; 18 } 19 else { 20 cout << "邮箱格式不正确,请重新输入: " << endl; 21 } 22 } 23 } 24 25 // 修改密码,进行旧密码验证 26 void change_password() { 27 const int max_attempts = 3; 28 int attempt = 0; 29 string old_pwd, new_pwd; 30 31 while (attempt < max_attempts) { 32 cout << "请输入旧密码: "; 33 cin >> old_pwd; 34 if (old_pwd == password) { 35 cout << "请输入新密码: "; 36 cin >> new_pwd; 37 password = new_pwd; 38 cout << "密码修改成功!" << endl; 39 return; 40 } 41 else { 42 attempt++; 43 cout << "旧密码错误,请重试(" << (max_attempts - attempt) << "次机会剩余):" << endl; 44 } 45 } 46 cout << "密码修改失败,输入错误次数过多,请稍后再试。" << endl; 47 } 48 49 // 打印用户信息,密码以星号显示 50 void display() const { 51 cout << "用户名: " << name << endl; 52 cout << "密码: "; 53 for (char ch : password) { 54 cout << '*'; 55 } 56 cout << endl; 57 cout << "邮箱: " << email << endl; 58 } 59 private: 60 string name; 61 string password; 62 string email; 63 };
运行结果
实验任务6
1 date.h 2 3 #pragma once 4 class Date { 5 private: 6 int year; int month; int day; int totalDays; 7 public: 8 Date(int year, int month, int day); 9 int getYear()const { return year; } 10 int getMonth()const { return month; } 11 int getDay()const { return day; } 12 int getMaxDay()const; 13 bool isLeapYear()const { 14 return year % 4 == 0 && year % 100 != 0 || year % 400 == 0; 15 } 16 void show()const; 17 int distance(const Date& date)const { 18 return totalDays - date.totalDays; 19 } 20 };
1 date.cpp 2 3 #include"date.h" 4 #include<iostream> 5 #include<cstdlib> 6 using namespace std; 7 namespace { 8 const int DAYS_BEFORE_MONTH[] = { 0,31,59,90,120,151,181,212,243,273,304,334,365 }; 9 } 10 Date::Date(int year, int month, int day) : year(year), month(month), day(day) { 11 if (day <= 0 || day > getMaxDay()) { 12 cout << "Invalid date:"; 13 show(); 14 cout << endl; 15 exit(1); 16 } 17 int years = year - 1; 18 totalDays = years * 365 + years / 4 - years / 100 + years / 400 + 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 else 25 return DAYS_BEFORE_MONTH[month] - DAYS_BEFORE_MONTH[month - 1]; 26 } 27 void Date::show()const { 28 cout << getYear() << "-" << getMonth() << "-" << getDay(); 29 }
account.h #include"date.h" #include<string> class SavingsAccount { private: std::string id; double balance; double rate; Date lastDate; double accumulation; static double total; void record(const Date& date, double amount, const std::string& desc); void error(const std::string& msg)const; double accumulate(const Date& date)const { return accumulation + balance * date.distance(lastDate); } public: SavingsAccount(const Date& date, const std::string& id, double rate); const std::string& getId()const { return id; } double getBalance()const { return balance; } double getRate()const { return rate; } static double getTotal() { return total; } void deposit(const Date& date, double amount, const std::string& desc); void withdraw(const Date& date, double amount, const std::string& desc); void settle(const Date& date); void show()const; };
1 account.cpp 2 #include"account.h" 3 #include<cmath> 4 #include<iostream> 5 using namespace std; 6 double SavingsAccount::total = 0; 7 8 SavingsAccount::SavingsAccount(const Date& date, const string& id, double rate) :id(id), balance(0), rate(rate), lastDate(date), accumulation(0) { 9 date.show(); 10 cout << "\t#" << id << "created" << endl; 11 } 12 void SavingsAccount::record(const Date& date, double amount, const std::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 void SavingsAccount::error(const std::string& msg)const { 22 cout << "Error(#" << id << ");" << msg << endl; 23 } 24 void SavingsAccount::deposit(const Date& date, double amount, const std::string& desc) { 25 record(date, amount, desc); 26 } 27 void SavingsAccount::withdraw(const Date& date, double amount, const std::string& desc) { 28 if (amount > getBalance()) 29 { 30 error("not enough money"); 31 } 32 else 33 record(date, -amount, desc); 34 } 35 void SavingsAccount::settle(const Date& date) { 36 double interest = accumulate(date) * rate / date.distance(Date(date.getYear() - 1, 1, 1)); 37 if (interest != 0) 38 record(date, interest, "interest"); 39 accumulation = 0; 40 } 41 void SavingsAccount::show()const { 42 cout << id << "\tBalance:" << balance; 43 }
test.cpp #include"account.h" #include<iostream> using namespace std; int main() { Date date(2008, 11, 1); SavingsAccount accounts[] = { SavingsAccount(date,"03755217",0.015), SavingsAccount(date,"02342342",0.015) }; const int n = sizeof(accounts) / sizeof(SavingsAccount); accounts[0].deposit(Date(2008, 11, 5), 5000, "salary"); accounts[1].deposit(Date(2008, 11, 25), 10000, "sell stock 0323"); accounts[0].deposit(Date(2008, 12, 5), 5000, "salary"); accounts[1].withdraw(Date(2008, 12, 20), 4000, "buy a laptop"); cout << endl; for (int i = 0; i < n; i++) { accounts[i].settle(Date(2009, 1, 1)); accounts[i].show(); cout << endl; } cout << "Total:" << SavingsAccount::getTotal() << endl; return 0; }
运行结果