📝實驗一 任務報告
✨實驗總結
😟遇到的問題:
略.
🧐解決方法:
略.
🤔思考:
略.
✨實驗內容
🕐任務一
驗證性實驗。
使用C++標准庫提供的復數模板類complex編碼實現簡單的復數運算。
在C++編碼環境中,輸入以下代碼,結合運行結果,體驗使用C++標准庫進行編程的便捷,同時,觀察和 理解類、對象、庫函數的使用。
📃代碼:
#include <complex.h>
#include <iostream>
#include <cmath>
int main()
{
using namespace std;
complex<double> c1(3, 4);
complex<double> c2(4.5);
complex<double> c3(c2);
cout << "c1 = " << c1 << endl;
cout << "c2 = " << c2 << endl;
cout << "c3 = " << c3 << endl;
cout << "c1 + c2 = " << c1 + c2 << endl;
cout << boolalpha; // 設置bool型值以true/false方式輸出
cout << "c1 == c2 : " << (c1 == c2) << endl;
cout << "c3 == c2 : " << (c3 == c2) << endl;
cout << "abs(c1) = " << abs(c1) << endl; // abs()對復數進行取模運算,頭文件cmath
complex<int> c4(3, 4), c5(2, 7);
cout << "c4 - c5 = " << c4 - c5 << endl;
}
🎨截圖:
🤓思考:
(1) 復數模板類complex
。由於是模板類,是對於抽象的數據類型,所以,使用時,在語法層面通過<>
指 定具體類型。比如,分別指定復數類的實部和虛部是double
類型和int
類型。
(2) 庫函數abs()
。對於復數類型,abs()
實現的是取模運算。設復數的實部和虛部分別是real
和imag
, 取模 運算規則:sqrt(real2+imag2)
🕑任務二
驗證性實驗。
設計並實現一個雇員類Employee
,滿足如下要求:
數據成員
包括員工姓名、薪水、雇佣日期,以及,員工總數
函數成員
包括構造函數、設置員工信息、更新員工信息(薪水、雇佣時間)、打印員工信息、打印員工總數 等。
其中,Employee
類定義在文件Employee.hpp
中,使用類Employee
類的測試代碼在文件task2.cpp
中。
在C++
編碼環境中,輸入以下代碼,結合運行結果,理解和鞏固C++
中類的定義、實現方法,及const
成員、static
成員等。
📃代碼:
task2.hpp
#ifndef EMPLOYEE_HPP
#define EMPLOYEE_HPP
// Employee類的定義
#include <iostream>
#include <iomanip>
#include <string>
using namespace std;
struct Date
{
int year;
int month;
int day;
};
// Employee類的聲明
class Employee
{
public:
Employee();
Employee(string name0, double salary0, int y, int m, int d);
void set_info(string name0, double salary0, int y, int m, int d); // 設置雇員信息
string get_name() const; // 獲取雇員姓名
double get_salary() const; // 獲取雇員薪水
void display_info() const; // 顯示雇員信息
void update_salary(double s); // 更新雇員薪水
void update_hire_date(int y, int m, int d); // 更新雇佣日期
void raise_salary(double by_percent); //
static void display_count();
private:
string name; // 雇員姓名
double salary; // 雇員薪水
Date hire_date; // 雇員雇佣日期
static int count; // 用於記錄雇員總人數
};
int Employee::count = 0;
// 默認構造函數
Employee::Employee()
{
++count;
}
// 帶參數的構造函數
Employee::Employee(string name0, double salary0, int y, int m, int d) :
name{name0}, salary{salary0}, hire_date{y, m, d}
{
++count;
}
// 設置員工信息
void Employee::set_info(string name0, double salary0, int y, int m, int d)
{
name = name0;
salary = salary0;
hire_date.year = y;
hire_date.month = m;
hire_date.day = d;
}
// 獲取員工姓名
string Employee::get_name() const
{
return name;
}
// 獲取員工薪水
double Employee::get_salary() const
{
return salary;
}
// 顯示雇員信息
void Employee::display_info() const
{
cout << "name: " << name << endl;
cout << "salary: " << salary << endl;
cout << "hire_date: " << hire_date.year << "-" << setfill('0') <<
setw(2) << hire_date.month << "-"
<<
setw(2) << hire_date.day;
}
// 更新薪水
void Employee::update_salary(double s)
{
salary = s;
}
// 更新雇佣日期
void Employee::update_hire_date(int y, int m, int d)
{
hire_date.year = y;
hire_date.month = m;
hire_date.day = d;
}
// 雇員提薪加成
// by_percent是提升比例
void Employee::raise_salary(double by_percent)
{
double raise = salary * by_percent / 100;
salary += raise;
}
// 顯示雇員總數
void Employee::display_count()
{
cout << "there are " << count << " employees\n";
}
#endif
task2.cpp
#include "task2.hpp"
#include <iostream>
int main()
{
using namespace std;
Employee employee1;
employee1.set_info("Sam", 30000, 2015, 1, 6);
employee1.update_hire_date(2017, 6, 30);
employee1.update_salary(35000);
employee1.display_info();
cout << endl << endl;
Employee employee2("Tony", 20000, 2020, 3, 16);
employee2.raise_salary(15);
employee2.display_info();
cout << endl << endl;
Employee::display_count();
return 0;
}
🎨截圖:
🤓思考:
略.
🕒任務三
不使用C++
標准庫,自行設計並實現一個復數類Complex
,使其滿足如下要求:
數據成員
用來表示復數的實部real
和虛部imag
,實部、虛部,均為小數形式。
函數成員
構造函數 支持以下方式定義復數對象:
Complex c1; // 不帶參數
Complex c2(3); // 只有一個參數,相當於3 + 0i
Complex c3(3, 4); // 兩個參數,相當於3 + 4i
Complex c4(c3); // 用c3構造c4
成員函數
-
get_real()
返回復數實部 -
get_imag()
返回復數虛部 -
show()
用於輸出復數。要求以3 + 4i
,3 - 4i
這樣的形式輸出add()
用於把一個復數加到自身,比如c1.add(c2)
,相當於c1 += c2
友元函數
-
add()
用於實現兩個復數相加,返回復數。比如c3 = add(c1, c2);
is_equal()
用於判斷兩個復數是否相等,返回true/false
。比如is_equal(c1, c2)
-
abs()
用於對復數進行取模運算 將類Complex
的定義及友元函數實現,單獨保存在文件Complex.hpp
中。
使用task3.cpp
中的代碼,測試類Complex
的各項接口是否正確。
📃代碼:
task3.hpp
#ifndef TASK3_HPP
#define TASK3_HPP
#include <iostream>
#include <cmath>
using namespace std;
class Complex
{
private:
double a;
double b;
public:
Complex() : a(0), b(0) {}
Complex(double num1, double num2 = 0) : a(num1), b(num2) {}
Complex(const Complex &c) : a(c.a), b(c.b) {}
friend Complex add(const Complex &c1, const Complex &c2);
friend bool is_equal(const Complex &c1, const Complex &c2);
friend double abs(const Complex &c1);
double get_real() const { return a; }
double get_imag() const { return b; }
void show() const
{
if (!b)
cout << a << endl;
else
cout << a << " " << (signed int) b << "i" << endl;
}
void add(const Complex &c2)
{
a += c2.a;
b += c2.b;
}
};
Complex add(const Complex &c1, const Complex &c2)
{
Complex c3(c1.a + c2.a, c1.b + c2.b);
return c3;
}
bool is_equal(const Complex &c1, const Complex &c2)
{
if (c1.get_imag() == c2.get_imag() && c1.get_real() == c2.get_real())
return true;
else
return false;
}
double abs(const Complex &c1)
{
return sqrt((c1.a * c1.a) + (c1.b * c1.b));
}
#endif //TASK3_HPP
task3.cpp
#include "task3.hpp"
#include <iostream>
int main()
{
using namespace std;
Complex c1(3, -4);
const Complex c2(4.5);
Complex c3(c1);
cout << "c1 = ";
c1.show();
cout << endl;
cout << "c2 = ";
c2.show();
cout << endl;
cout << "c2.imag = " << c2.get_imag() << endl;
cout << "c3 = ";
c3.show();
cout << endl;
cout << "abs(c1) = ";
cout << abs(c1) << endl;
cout << boolalpha;
cout << "c1 == c3 : " << is_equal(c1, c3) << endl;
cout << "c1 == c2 : " << is_equal(c1, c2) << endl;
Complex c4;
c4 = add(c1, c2);
cout << "c4 = c1 + c2 = ";
c4.show();
cout << endl;
c1.add(c2);
cout << "c1 += c2, " << "c1 = ";
c1.show();
cout << endl;
return 0;
}
🎨截圖:
🤓思考:
復習了一下條件運算符(?:
)
【友元函數
】在類內部,只能申明函數原型,不能定義函數體,不受訪問級別的限制。
【友元類
】友類的每個成員都可以訪問另一個類中的保護成員和私有成員。
🕓任務四
設計並實現一個用戶類User
,並在主函數中使用和測試這個類。具體要求如下:
數據成員
每個用戶有用戶名name
、密碼passwd
、聯系郵箱email
三個屬性。
還有一個類屬性,用於記錄用戶總數n
。
函數成員
構造函數 如果定義用戶對象時未設置密碼和郵箱,密碼默認為6個1
,聯系郵箱默認為空串。
User u1("Mary"); // 密碼和郵箱,使用默認設置
User u2("John", "112233", "xyz@gmail.com")
成員函數
-
set_email()
設置郵箱。提示用戶從鍵盤輸入郵箱。 -
change_passwd()
修改密碼。修改密碼前,要求先輸入舊的密碼,驗證無誤后,才允許修改;如果輸入舊 密碼時,連續三次輸入錯誤,則提示用戶稍后再試,暫時退出修改密碼程序。 -
print_info()
打印用戶名、密碼、聯系郵箱。其中,密碼以6個*
方式顯示。
User
類的定義和實現,保存在文件User.hpp
中。 User
類的使用和測試,保存在文件task4.cpp
中。
📃代碼:
task4.hpp
#ifndef TASK4_HPP
#define TASK4_HPP
#include <iostream>
#include <string>
using namespace std;
class User
{
private:
string name;
string passwd;
string email;
public:
static int num;
User(string n = "Default", string p = "111111", string e = "") : name(n), passwd(p), email(e) { num++; }
static void print_n() { cout << "Num of users is: " << num; }
void print_info() { cout << "Name:" << name << " Passwd:" << "******" << " E-mail:" << email << endl; }
void set_email()
{
cout << "Please enter your E-mail:";
cin >> email;
cout << "Setting E-mail... Done." << endl;
}
void change_passwd()
{
string temp, new_passwd;
cout << "Changing password for " << name << endl;
cout << "Old password:";
cin >> temp;
if (passwd != temp)
{
cout << "Wrong password, please try again." << endl;
}
else
{
cout << "New password:";
cin >> temp;
cout << "Ensure password:";
cin >> new_passwd;
if (temp != new_passwd)
cout << "New password doesn't match, please try again." << endl;
else
{
passwd = new_passwd;
cout << "Changing password... Done." << endl;
}
}
}
};
int User::num = 0;
#endif //TASK4_HPP
task4.cpp
#include "task4.hpp"
#include <iostream>
int main()
{
using namespace std;
cout << "testing 1......" << endl;
User user1("Jonny", "92197", "xyz@hotmail.com");
user1.print_info();
cout << endl
<< "testing 2......" << endl
<< endl;
User user2("Leonard");
user2.change_passwd();
user2.set_email();
user2.print_info();
User::print_n();
}
🎨截圖:
🤓思考:
User
類的完善及拓展豐富*(選做)
-
設置郵箱時,對郵箱地址合法性進行檢測提示,比如,是否包含@
-
設置密碼時,對密碼的長度、合法性進行校驗
使用正則表達式匹配,如果合法則修改密碼或郵箱
#ifndef TASK4_HPP
#define TASK4_HPP
#include <iostream>
#include <string>
#include <regex>
using namespace std;
class User
{
private:
string name;
string passwd;
string email;
public:
static int num;
User(string n = "Default", string p = "111111", string e = "") : name(n), passwd(p), email(e) { num++; }
void change_passwd();
void set_email();
static void print_n() { cout << "Num of users is: " << num; }
void print_info() const { cout << "Name:" << name << " Passwd:" << "******" << " E-mail:" << email << endl; }
};
int User::num = 0;
void User::change_passwd()
{
string temp, new_passwd, str;
cout << "Changing password for " << name << endl;
cout << "Old password:";
cin >> temp;
if (passwd != temp)
{
cout << "Wrong password, please try it again." << endl;
}
else
{
cout << "New password:";
cin >> temp;
cout << "Ensure password:";
cin >> new_passwd;
if (temp != new_passwd)
cout << "New password doesn't match, please try it again." << endl;
else
{
//密碼規則:長度>=8,包含大小寫和特殊字符
if (new_passwd.length() >= 8 && regex_search(new_passwd, regex("\\d")) &&
regex_search(new_passwd, regex("\\W")) && regex_search(new_passwd, regex("[a-z]")) &&
regex_search(new_passwd, regex("[A-Z]")))
{
passwd = new_passwd;
cout << "Changing password... Done." << endl;
}
else
cout
<< "Must be 8 characters or more;" << endl
<< "Needs at least one number,one uppercase letter, one lowercase letter and one symbol."
<< endl
<< "Change password failed." << endl;
}
}
}
void User::set_email()
{
string str, temp = email;
cout << "Please enter your E-mail:";
cin >> email;
//郵箱規則: 依次包含`@`和`.`
if (regex_match(email, regex(".+[@].+[.].+")))
cout << "Setting E-mail... Done." << endl;
else
{
email = temp;
cout << "Invalid E-mail. Set E-mail failed." << endl;
}
}
#endif //TASK4_HPP