面向对象与C++程序设计
期末考试试卷(A卷)
2022年12月18日
题目说明
智能锁是一种近年来逐步深入千家万户的新型门锁装置。智能锁在内部构造上除了有常规的锁体结构以外,还增加了CPU和电池等电子部件。
图1 某品牌智能锁
请各位考生从课程信息发布网站或老师指定的途径下载文本数据文件elelockers.txt和源程序文件main.cpp。将上述两个文件保存在D盘根目录下。文件elelockers.txt中存储了若干智能锁的基本信息,每行存储了一种智能锁的相关信息,存储格式如图2所示(每行中的各项之间以制表符'\t'进行分隔。斜线文字和线条是用于对文件格式进行解释说明的,在文件中并不存在):
品牌 | 型号 | 锁芯级别 | CPU系列 | 电池容量 |
DESSMANN | Q50FMax | 1 | ARM7 | 800 |
PHILIPS | DDL708-VP | 2 | ARM9 | 1000 |
图2 数据文件格式示意图
请根据要求完成如下编程工作:
类1(门锁类)说明
现有CLocker类描述如下:
该类所有的定义(含成员函数和友元函数)均已在与试卷一起提供的main.cpp中实现。
类2(智能锁)说明
请以CLocker类为基类进行public继承,派生出CEleLocker类用于描述智能锁。要求如下:
- CEleLocker类在继承CLocker类所有成员的基础上,还需要添加以下成员变量:
- string m_CPU; //CPU系列
- int m_Capacity; //电池容量。必须是正数。
- static int m_Counts; //智能锁总数
- 为CEleLocker类添加一个普通有参构造函数。构造函数通过5个形式参数对智能锁进行初始化:
- string Factory,缺省值:”SUDA”
- string Model,缺省值:”111”
- int CoreGrade,缺省值:1
- string CPU,缺省值:”ARM9”
- int Capacity,缺省值:1000。如输入负数,则m_Capacity固定等于500
- 为CEleLocker类添加一个拷贝构造函数;
- 为CEleLocker类添加一个用于返回智能电视机数量的静态成员函数GetCounts;
static int GetCounts();
- 为CEleLocker类添加一个用于返回智能锁CPU系列数据的成员函数GetCPU;
string GetCPU()const;
- 为CEleLocker类添加一个用于返回智能锁电池容量数据的成员函数GetCapacity;
int GetCapacity ()const;
- 为CEleLocker类添加前自增运算符++。++运算符用于实现以下要求:
- 将基类部分数据按照与CLocker类部分相同的要求进行++
- CPU系列数据中的数字增加1,例如“ARM7”自增后变成“ARM8”,“ARM9”自增后变成“ARM10”。CPU系列数据中的数字字符只会在字符串的最后出现。选修的同学本步不需要实现,也就是说CPU系列数据不需要进行自增。
- 电池容量增加100。
- 为CEleLocker类添加后自增运算符++。要求与前++运算符相同
- 为CEleLocker类添加析构函数
- 为CEleLocker类添加重载流输出运算符<<,格式要求如下:
- 基类部分数据的输出格式与CLocker类的operator<<函数相同
- m_CPU成员的输出格式:右对齐,占10列,不足部分补空格
- m_Capacity成员的输出格式:右对齐,占8列,不足部分补空格
- 不允许在题目要求以外对该类添加任何其它成员变量、成员函数或友元函数。
程序业务流程说明
- 编写一个函数readFile。从下载的数据文件elelockers.txt中读取数据,逐个生成CEleLocker类的对象,并将这些对象存储到CEleLocker类型的向量A中。
- 编写一个函数ShowData。显示向量A中前X条智能锁信息。每个智能锁数据占一行,每行中显示格式的要求与CEleLocker类operator<<函数的要求相同。如A中智能锁数量不足X条,则全部显示。如不指定X的具体数值,默认显示前5条。
- 编写一个函数IncData。对向量A中所有智能锁依次执行前自增运算,结果仍然保存在A中。
- 选修的同学本步不需要实现,直接屏蔽所给主函数中的相应语句行。编写一个函数SortData。对向量A中所有智能锁按照锁芯级别进行递增排列,在锁芯级别相同的情况下按照电池容量进行降序排列。
- 编写一个函数WriteFile。将经过上述处理后的所有智能锁信息保存到指定文件中。每个钳工数据占一行,每行中文件保存格式的要求与CEleLocker类operator<<函数的要求相同。
- 选修的同学本步不需要实现,直接屏蔽所给主函数中的相应语句行。编写一个函数GetAverage。求解在前面步骤中已经排序后的向量A中各相同锁芯级别的平均电池容量,并分别将包含锁芯级别和对应平均电池容量保存在struct AVER类型的向量B中。在生成B向量的过程中,锁芯级别的顺序可以任意处理。struct AVER类型的具体定义如下:
struct AVER
{
int CoreGrade;
double AverCapacity;
};
- 程序运行结果如图3和图4所示(示意图仅为参考答案)。
图3 程序运行显示结果示意图
图4 程序运行保存文件结果示意图
编程要求
- 根据业务流程和main.cpp中的注释,在main.cpp的基础上将程序补充完整。
- 不可以修改CLocker类的代码。每修改一处编程题总得分扣2分,最多扣10分。
- 不允许在题目要求以外为CEleLocker类添加其它成员变量、成员函数或友元函数。。每修改一处编程题总得分扣2分,最多扣10分。
- 不可以修改main函数的代码。每修改一处编程题总得分扣2分,最多扣10分。
评分标准(非选修)
大项 | 子项 | 评分项 | 应得分 | 实得分 |
正 确 性 90分 | 结果(90分) | CEleLocker类结构 | 5 | |
CEleLocker类普通构造函数 | 5 | |||
CEleLocker类拷贝构造函数 | 7 | |||
CEleLocker类3个Get函数 | 3 | |||
CEleLocker类前和后自增 | 10 | |||
CBenchWorker类流输出 | 10 | |||
CEleLocker析构函数 | 5 | |||
readFile函数 | 10 | |||
ShowData函数 | 5 | |||
IncData函数 | 5 | |||
SortData函数 | 10 | |||
WriteFile函数 | 5 | |||
GetAverage函数 | 10 | |||
异常情况 | 程序运行出现异常(运行错、死循环等) | -10 | ||
修改main函数 | 每处-2/最多-10分 | |||
修改基类 | 每处-2/最多-10分 | |||
修改子类接口 | 每处-2/最多-10分 | |||
编译、连接不通过 | 以上合计为0分 | |||
可 读 性 10分 | 缩进对齐(4分) | 正确运用缩进对齐规则 | 4 | |
有缩进对齐但不完全符合要求 | 2 | |||
没有使用缩进对齐规则 | 0 | |||
注释(4分) | 有详细且正确的注释 | 4 | ||
有注释,但不够详细 | 2 | |||
完全没有注释 | 0 | |||
变量命名(2分) | 变量命名有规则 | 2 | ||
变量命名有规则、但规则使用不一致 | 1 | |||
变量命名无规则 | 0 |
评分标准(选修)
大项 | 子项 | 评分项 | 应得分 | 实得分 |
正 确 性 90分 | 结果(90分) | CEleLocker类结构 | 6 | |
CEleLocker类普通构造函数 | 8 | |||
CEleLocker类拷贝构造函数 | 10 | |||
CEleLocker类3个Get函数 | 6 | |||
CEleLocker类前和后自增 | 10 | |||
CBenchWorker类流输出 | 10 | |||
CEleLocker析构函数 | 6 | |||
readFile函数 | 10 | |||
ShowData函数 | 8 | |||
IncData函数 | 6 | |||
WriteFile函数 | 10 | |||
异常情况 | 程序运行出现异常(运行错、死循环等) | -10 | ||
修改main函数 | 每处-2/最多-10分 | |||
修改基类 | 每处-2/最多-10分 | |||
修改子类接口 | 每处-2/最多-10分 | |||
编译、连接不通过 | 以上合计为0分 | |||
可 读 性 10分 | 缩进对齐(4分) | 正确运用缩进对齐规则 | 4 | |
有缩进对齐但不完全符合要求 | 2 | |||
没有使用缩进对齐规则 | 0 | |||
注释(4分) | 有详细且正确的注释 | 4 | ||
有注释,但不够详细 | 2 | |||
完全没有注释 | 0 | |||
变量命名(2分) | 变量命名有规则 | 2 | ||
变量命名有规则、但规则使用不一致 | 1 | |||
变量命名无规则 | 0 |
#include <iostream>
#include <iomanip>
#include <fstream>
#include <sstream>
#include<string>
#include <vector>
#include <algorithm>
using namespace std;
struct AVER
{
int CoreGrade;
double AverCapacity;
};
//void ProcessCPUString(string &CPU);
class CLocker
{
private:
string m_Factory; //���ң�Ʒ�ƣ�
string m_Model; //�ͺ�
int m_CoreGrade; //�����
public:
CLocker(const string& Factory, const string& Model, int CoreGrade) //��ͨ�вι��캯��
{
m_Factory = Factory;
m_Model = Model;
m_CoreGrade = CoreGrade;
}
string GetFactory()const { return m_Factory; } //���س���
string GetModel()const { return m_Model; } //�����ͺ�
int GetCoreGrade()const { return m_CoreGrade; } //���������
CLocker& operator++() //ǰ��������о����+1
{
m_CoreGrade++;
return *this;
}
CLocker operator++(int) //�������������+1
{
CLocker temp(*this);
m_CoreGrade++;
return temp;
}
friend ostream& operator<<(ostream& Out, const CLocker& Data) //�����������
{
Out << right << setw(10) << Data.m_Factory;
Out << right << setw(10) << Data.m_Model;
Out << right << setw(5) << Data.m_CoreGrade;
return Out;
}
};
class CEleLocker:public CLocker{
private:
string m_CPU; //CPU系列
int m_Capacity; //电池容量。必须是正数。
static int m_Counts; //智能锁总数
public:
CEleLocker(string Factory="SUDA",string Model="111",int CoreGrade=1,string CPU="ARM9",int Capacity=1000):CLocker(Factory,Model,CoreGrade),m_CPU(CPU){
if(Capacity<0){Capacity=500;}
m_Capacity=Capacity;
m_Counts++;
}
CEleLocker(const CEleLocker&C):CLocker(C),m_CPU(C.m_CPU),m_Capacity(C.m_Capacity){
m_Counts++;
}
static int GetCounts();
string GetCPU()const;
int GetCapacity ()const;
CEleLocker& operator++(){
++(*(static_cast<CLocker*>(this)));
/*
CPU系列数据中的数字增加1,例如“ARM7”自增后变成“ARM8”,
“ARM9”自增后变成“ARM10”。CPU系列数据中的数字字符只会在字符串的最后出现。
*/
string temp;
int j;
for(j=0;j<m_CPU.length();j++){
if(m_CPU[j]>='0' and m_CPU[j]<='9'){
break;
}
else{
temp+=m_CPU[j];
}
}
string tempnum="";
for(j;j<m_CPU.length();j++){
tempnum+=m_CPU[j];
}
stringstream ss(tempnum);
int k;
ss>>k;
k++;
ostringstream ss1(k);
string k1;
ss1<<k1;
m_CPU=temp+k1;
m_Capacity+=100;
return (*this);
}
CEleLocker operator++(int){
CEleLocker C(*this);
++(*this);
return C;
}
~CEleLocker(){m_Counts--;}
friend ostream& operator<<(ostream&Out,const CEleLocker&c){
/*
基类部分数据的输出格式与CLocker类的operator<<函数相同
m_CPU成员的输出格式:右对齐,占10列,不足部分补空格
m_Capacity成员的输出格式:右对齐,占8列,不足部分补空格
*/
Out<<*(static_cast<const CLocker*>(&c));
Out<<right<<setw(10)<<c.m_CPU;
Out<<right<<setw(8)<<c.m_Capacity;
return Out;
}
};
int CEleLocker::m_Counts=0;
int CEleLocker::GetCounts(){
return m_Counts;
}
string CEleLocker::GetCPU()const{
return m_CPU;
}
int CEleLocker::GetCapacity ()const{
return m_Capacity;
}
vector<CEleLocker> readFile(string path){
ifstream ifile(path);
if(ifile.is_open()==false){exit(0);}
vector<CEleLocker> a;
while(!ifile.eof()){
string Factory;
string Model;
int CoreGrade;
string CPU;
int Capacity;
if(ifile>>Factory>>Model>>CoreGrade>>CPU>>Capacity){
a.push_back(CEleLocker(Factory,Model,CoreGrade,CPU,Capacity));
}
}
return a;
}
void ShowData(const vector<CEleLocker>&a,int X=5){
for(int i=0;i<a.size();i++){
cout<<a[i]<<endl;
if(i+1==X){return ;}
}
}
void IncData(vector<CEleLocker>&a){
for(int i=0;i<a.size();i++){
++a[i];
}
}
bool cmp(CEleLocker a, CEleLocker b){
if(a.GetCoreGrade()==b.GetCoreGrade()){
return a.GetCapacity()>b.GetCapacity();
}
return a.GetCoreGrade()<b.GetCoreGrade();
}
void SortData(vector<CEleLocker>&a){
sort(a.begin(),a.end(),cmp);
}
void WriteFile(string path, const vector<CEleLocker>&a){
ofstream ofile(path);
if(ofile.is_open()==false){exit(0);}
for(int i=0;i<a.size();i++){
ofile<<a[i]<<endl;
}
}
vector<struct AVER>GetAverage(const vector<CEleLocker>&a){
vector<struct AVER> b;
for(int i=0;i<a.size();i++){
int j;
for(j=0;j<b.size();j++){
if(a[i].GetCoreGrade()==b[j].CoreGrade){
break;
}
}
if(j==b.size()){//未统计
double cont=0;
double n=0;
for(int k=i;k<a.size();k++){
if(a[i].GetCoreGrade()==a[k].GetCoreGrade()){
cont+=a[k].GetCapacity();
n++;
}
}
cont/=n;
struct AVER tmpb;
tmpb.CoreGrade=a[i].GetCoreGrade();
tmpb.AverCapacity=cont;
b.push_back(tmpb);
}
}
return b;
}
int main()
{
int i;
vector<CEleLocker> A;
vector<struct AVER> B;
A=readFile("/Users/apple/Downloads/20221217/elelockers.txt");
cout << "ǰ5������������:" << endl;
ShowData(A);
IncData(A);
SortData(A); //ѡ������ע�ʹ���
WriteFile("/Users/apple/Downloads/20221217/res.txt", A); //���浽D�̸�Ŀ¼�µ�res.txt�ļ��У��翼����������û��D�̣���������и����̷�
//ѡ������ע�����¼��д���
B = GetAverage(A);
cout << "ƽ�����������������:" << endl;
for (i = 0; i < B.size(); i++)
{
cout << right << setw(5) << B[i].CoreGrade;
cout << right << fixed << setw(10) << setprecision(2) << B[i].AverCapacity << endl;
}
//ѡ������ע�����ϼ��д���
cout << "������֤����:" << endl;
cout << "�ϼƶ�������1:" << CEleLocker::GetCounts() << endl;
CEleLocker t;
cout << t << endl;
cout << "�ϼƶ�������2:" << t.GetCounts()<<endl;
cout << t++<< endl;
cout <<"�ϼƶ�������3:"<< t.GetCounts() << endl;
return 1;
}
总结一下:和之前的相比,主要问题已经浓缩进:如何在int和string之间转换。
S为string,stringstream ss(S),ss>>I
I为int,stringstream ss(I),ss<<S