文章目录
零、前言
为了验证自己是否真正掌握学校所学C++内容,正所谓,能把一个知识点教会别人,才算自己掌握了。故而,在完成作业后,我选择记录自己的解题思路。
若遇到同课程同学,您可以参考思路,对照自己的代码,如果更好的想法欢迎提出来,
不建议抄,会封号。
一、问题 A: 类设计练习:定义Tree类
1、题目描述
定义一个Tree(树)类,有成员age(树龄),成员函数 grow(int years) 对 age 加上 years,age() 显示 Tree 对象的 age 的值。
下面的程序不完整,请编程完善:
#include <iostream>
using namespace std;
class Tree {
你写的代码放在这里
};
int main() {
Tree t;
t.setages( 3 );
t.age();
t.grow( 20 );
t.age();
return 0;
}
输入
本题无输入数据
输出
见输出样例
样例输入
NULL
样例输出
3
23
2、解题思路
由题意可知,需要构建一个 Tree 的类,并包含一个私有变量 age;同时含有三个公共函数 grow(int years)
、 setages()
、 age()
。其中 grow() 函数用于修改 ages,setages() 函数用于输入 ages,age()函数用于输出当前年龄。
3、AC代码
#include <iostream>
using namespace std;
class Tree {
private:
int ages = 0; //(1)
public:
void setages(int age) //(2)
{
ages = age;
}
void grow(int years) //(3)
{
ages += years;
}
void age() //(4)
{
cout<<ages<<endl;
}
};
int main() {
Tree t;
t.setages( 3 );
t.age();
t.grow( 20 );
t.age();
return 0;
}
4、代码解析
- (1) 设置私有变量 ages 由于变量years 、age 都为 int 类型,所以 ages 也可为 int 类型
- (2) 由样例输出可知,该函数为 ages 的赋值。
- (3) grow() 可以理解为 之前年龄 ages + 经过 years 年后,求当前年龄 ages 。所以直接加上即可。
- (4) 样例输出有两个输出 和两个 age() 函数,因此可以很自然地想到,该函数的作用为输出当前年龄 ages ,所以直接输出即可 。
二、问题 B: 类设计练习:定义点类Point
1、题目描述
定义点类 Point,其中有数据成员 x 和 y,表示点的横坐标与纵坐标。成员函数 double Distance( const Point & ) 的功能是求两点之间的距离。
请完善下面的程序。
#include <iostream>
#include <cmath>
using namespace std;
你写的代码放在这里
int main() {
Point a, b;
a.setPoint(); // 这里读入a点的横坐标、纵坐标
b.setPoint(); // 这里读入b点的横坐标、纵坐标
cout << a.Distance( b ) << endl;
return 0;
}
输入
两行:第一行是 点a 的横坐标 和 纵坐标;
第二行是 点b 的横坐标 和 纵坐标。
输出
两点之间的距离,精确到整数部分。
样例输入
0 0
3 4
样例输出
5
2、解题思路
1、由题意可知,setPoint()
用于获取 对象的坐标x,y,直接输入即可。
2、Distance( const Point & )
函数用于计算两点间距离,用两点间公式计算并输出即可(头文件有math函数,是一个提示),注意需要用 double 类型,并且 main() 内由一行输出 该函数,说明该函数只是计算,并不输出。
3、AC代码
#include <iostream>
#include <cmath>
using namespace std;
class Point{
private:
double x,y;
public:
void setPoint() //(1)
{
cin>>x>>y;
}
double Distance(const Point& b) //(2)
{
double s = sqrt((x-b.x) * (x-b.x) + (y - b.y) * (y - b.y));
return s;
}
};
int main() {
Point a, b;
a.setPoint(); // 这里读入a点的横坐标、纵坐标
b.setPoint(); // 这里读入b点的横坐标、纵坐标
cout << a.Distance( b ) << endl;
return 0;
}
4、代码解析
- (1) 读取x,y坐标,使用 cin 即可。
- (2) 使用两点间距离公式计算即可。
三、问题 C: 类设计练习:编写一个stack类.part.1
问题描述
编写一个 stack 栈类,约定:
- 封装数据和操作
- 数据成员为私有属性,包括:
data :保存栈内元素,栈元素类型为 int
tt : 指示栈顶位置
len : 当前栈空间的大小- 成员函数为公有属性,包括:
默认构造函数,完成初始化动作,栈的默认大小是 1000 。最后输出一行:constructing
析构函数只输出一行:destructing
top( &v ),函数返回如果为真,参数 v 带回栈顶元素的值;函数返回如果为假,参数 v 的值没有变化
pop(),如果栈不空,弹走栈顶元素;如果栈空,没有动作
push( v ),如果栈已满,没有动作;如果栈未满,参数 v 的值进栈
size(),返回当前栈内元素个数,如果栈空,返回 0
output(),自栈底到栈顶,输出栈内元素,每一个元素后面跟一个空格,作为分隔。最后换行。如果栈空,没有输出
输入
本题需要解释执行的5种命令定义如下:
1 a :表示把元素 a 压入栈
2 :表示弹走栈顶元素
3 :表示读取栈顶元素的值
4 :表示取得当前栈内元素的个数
5 :表示调用 output() 函数
第一行是命令的数量 n
接下来 n 行,每行是一条命令
输出
对第 3、4、5 类命令,输出一行:该命令对应取得的结果
样例输入
10
1 3
1 5
1 7
3
2
4
2
1 9
5
3
样例输出
constructing <---- 默认构造函数输出
7 <---- 当前栈顶元素是7
2 <---- 弹走了7,所以只剩下2个元素
3 9 <---- 弹走了5,压入了9,所以栈内的元素是3,9
9 <---- 栈顶元素是9
destructing <---- 析构函数输出
提示
下面这个测似用例是容易错的情况:
5
1 3
2
2 <---- 这里容易错,就是栈空时调用pop()
3 <---- 这里也容易错,就是栈空时调用top()
5 <---- 这里也容易错,就是栈空时调用output()
输出结果:
1
3
2
2 <---- 这时栈空,pop()无需任何动作
3 <---- 这时栈空,top()函数返回值应该是false。如果这里输出了内容,就是错了
5 <---- 这里栈空,output()无需输出任何内容
解题思路
AC代码
#include <iostream>
#include<cstdlib>
using namespace std;
class stack{
private:
int data[1010];
int tt,len;
public:
stack()
{
int *data = new int[1010];
tt = -1;
len = 0;
cout<< "constructing" <<endl;
}
void push(int temp)
{
tt++;
len++;
data[tt] = temp;
}
void pop()
{
if(len <= 0) len = 0;
else
{
len-- ;
data[tt] = -11;
tt--;
}
return ;
}
void top()
{
if(len<=0)
return ;
else
{
cout<<data[tt]<<endl;
return ;
}
}
void size()
{
cout<< len <<endl;
}
void output()
{
if(len <= 0)
return ;
else
{
for(int i = 0;i<len;i++)
{
cout<< data[i] << " ";
}
cout<<endl;
}
}
~stack()
{
cout<< "destructing" <<endl;
}
};
int main() {
stack s;
int n ;
cin>>n;
while(n--)
{
int t;
cin>>t;
if(t == 1)
{
int temp ;
cin>>temp;
s.push(temp);
}
else if( t == 2)
s.pop();
else if( t == 3)
s.top();
else if( t == 4)
s.size();
else if( t == 5)
s.output();
}
return 0;
}
4、代码解析
- (1)
- (2)
- (3)
- (4)
四、问题 D: 类设计练习:设计整型链表类List
问题描述
设计一个整型链表类 List,能够实现链表节点的插入 insert() 、按位置删除节点 deleteByPos() 、按值删除节点 deleteByVAlue() ,以及链表数据的输出操作 print()。
构造函数、析构函数这些都不用说也知道要写的吧。
提示:链表节点用如下结构定义:
// 节点的结构
struct Node {
int data;
Node *next;
Node() {
data = 0;
next = nullptr;
}
~Node() { }
};
链表类 List 有一个数据成员 head,类型是 Node *
根据题目要求完善下面的程序:
#include <iostream>
using namespace std;
/// 节点的结构
struct Node {
int data;
Node *next;
Node() {
data = 0;
next = nullptr;
}
~Node() { }
};
/// 链表类
class List {
private:
Node *head;
public:
你写的代码放在这里
};
int main() {
List l1; /// 创建一个空链表对象 l1
l1.insert( 0, 10 ); /// 在第 0 个节点的后面插入值为 10 的新节点,也即在链表头部插入新的节点
l1.insert( 0, 66 );
l1.insert( 1, 292 ); /// 在第 1 个节点的后面插入值为 10 的新节点
l1.print( ); /// 从头到尾输出链表节点的值,每个值后跟一空格
l1.deleteByValue( 66 ); /// 删除链表中第一个值为 66 的节点
l1.print( );
l1.insert( 2, -2 ); /// 在第 2 个节点的后面插入值为 -2 的新节点
l1.insert( 1, 3 ); /// 在第 1 个节点的后面插入值为 3 的新节点
l1.print( );
l1.deleteByPos( 2 ); /// 删除链表中第2个位置的节点,那么“3”就被删掉了
l1.print( );
l1.deleteByValue( 999 );
l1.print( );
return 0;
}
输入
本题没有输入数据
输出
见样例输出
样例输入
NULL
样例输出
66 292 10
292 10
292 3 10 -2
292 10 -2
not found data: 999
292 10 -2
解题思路
AC代码
#include <iostream>
using namespace std;
/// 节点的结构
struct Node {
int data;
Node *next;
Node() {
data = 0;
next = nullptr;
}
~Node() { }
};
/// 链表类
class List {
private:
Node *head;
public:
List()
{
head=new Node;
}
void insert(int n,int m)
{
Node *q,*p;
q = head;
for(int i = 0;i <= n;i++)
{
if(q->next == nullptr)
{
q->next =new Node;
}
q = q -> next;
}
p = new Node;
p -> data = m;
p -> next = q -> next;
q -> next = p;
}
void deleteByPos(int n)
{
Node *p = head,*q;
for(int i = 0;i <= n;i++)
{
p=p->next;
}
q = p -> next;
p -> next = q -> next;
delete q;
}
void deleteByValue(int n)
{
Node *q,*p = head;
while(p -> next -> next)
{
p = p -> next;
if(p -> next -> data == n)
{
q = p -> next;
p -> next = q -> next;
delete q;
return ;
}
}
cout << "not found data: "<< n <<endl;
}
void print()
{
Node *p;
p = head -> next;
while(p -> next)
{
p = p -> next;
cout<< p->data << " ";
}
cout<<endl;
}
~List()
{
Node *p=head,*q;
while(p)
{
q=p;
delete q;
p=p->next;
}
}
};
int main() {
List l1; /// 创建一个空链表对象 l1
l1.insert( 0, 10 ); /// 在第 0 个节点的后面插入值为 10 的新节点,也即在链表头部插入新的节点
l1.insert( 0, 66 );
l1.insert( 1, 292 ); /// 在第 1 个节点的后面插入值为 10 的新节点
l1.print( ); /// 从头到尾输出链表节点的值,每个值后跟一空格
l1.deleteByValue( 66 ); /// 删除链表中第一个值为 66 的节点
l1.print( );
l1.insert( 2, -2 ); /// 在第 2 个节点的后面插入值为 -2 的新节点
l1.insert( 1, 3 ); /// 在第 1 个节点的后面插入值为 3 的新节点
l1.print( );
l1.deleteByPos( 2 ); /// 删除链表中第2个位置的节点,那么“3”就被删掉了
l1.print( );
l1.deleteByValue( 999 );
l1.print( );
return 0;
}
4、代码解析
- (1)
- (2)
- (3)
- (4)
ps,本题输出答案虽然与给出答案一致,但一直Wrong Answer ,目前仍找不到原因,有没有佬告知一下。
五、问题 E: 类对象成员练习:设计工人类Worker
问题描述
设计工人类 Worker,它具有姓名 name,年龄 age,工作部门 Dept,工资 salary,等数据成员。
其中,salary 是 Salary 类的一个对象。
下面的程序拟完成 Worker 类的设计并用静态成员统计工人的人数,请把程序补充完整。
提示:这里成员函数 setXX() 用于设置各分项数据,成员函数 getXX() 用于获取各分项数据,XX 代表数据成员,如 age 对应的成员函数则为 setAge() 和 getAge() 。
#include <iostream>
#include <string>
using namespace std;
class Salary {
private:
double Wage, // 基本工资
Subsidy, // 岗位工资
Rent, // 房租
WaterFee, // 水费
ElecFee; // 电费
public:
// 初始化工资数据的各分项
Salary( double i1, double i2=0, double i3=0, double i4=0, double i5=0 ) {
Wage = i1;
Subsidy = i2;
Rent = i3;
WaterFee = i4;
ElecFee = i5;
}
Salary( ) { // 初始化工资的各分项数据为0
Wage = Subsidy = Rent = WaterFee = ElecFee = 0;
}
void setWage ( double f ) {
Wage = f;
}
double getWage( ) {
return Wage;
}
void setSubsidy( double f ) {
Subsidy = f;
}
double getSubsidy( ) {
return Subsidy;
}
void setRent( double f ) {
Rent=f;
}
double getRent(){
return Rent;
}
void setWaterFee( double f ) {
WaterFee=f;
}
double getWaterFee( ) {
return WaterFee;
}
void setElecFee( double f ) {
ElecFee=f;
}
double getElecFee( ) {
return ElecFee;
}
// 计算实发工资, 实发工资 = Wage + Subsidy - Rent - WaterFee - ElecFee
double RealSalary( ) {
return Wage + Subsidy - Rent - WaterFee - ElecFee;
}
};
你编写的代码放在这里。Worker 类中应包含一个 Salary 对象作为一个成员
int main(){
Worker w1( "John", 30, "design" );
cout << w1.getSalary() << endl;
Worker w2;
cout << "the total num is: " << w1.getNum() << endl;
w2.setName( "Linda" );
cout << "in w2 the name is: " << w2.getName() << endl;
// 基本工资 岗位工资 房租 水费 电费
w2.setSalary( 100000, 400, 300, 200, 100 );
cout << w2.getSalary() << endl;
return 0;
}
输入
本题无需读入数据
输出
见输出样例
样例输入
NULL
样例输出
0
the total num is: 2
in w2 the name is: Linda
99800
解题思路
- 定义一个类Worker,由题目可知,该类需要包含姓名 name,年龄 age,工作部门 Dept,工资 salary,需要注意的是,salary是Salary的一个对象,所以需要 new 一下。
- 之后便是分别构造各个私有成员的输入和输出。需要注意的是,这里的名字需要与主函数保持一致,否则函数会报错。而在用到 salary 需要调用该类的函数,要注意它们的类型,保持一致,防止报错。
- 这里有员工编号,或者是说处理员工进程数目,该变量需要定义在 外头,不属于 Worker 的私有成员。调用该类时,进程数量需要加一记录。注意,不要忘记析构函数是,处理员工进程数量需要减去一。
AC代码
#include <iostream>
#include <string>
using namespace std;
class Salary {
private:
double Wage, // 基本工资
Subsidy, // 岗位工资
Rent, // 房租
WaterFee, // 水费
ElecFee; // 电费
public:
// 初始化工资数据的各分项
Salary( double i1, double i2=0, double i3=0, double i4=0, double i5=0 ) {
Wage = i1;
Subsidy = i2;
Rent = i3;
WaterFee = i4;
ElecFee = i5;
}
Salary( ) { // 初始化工资的各分项数据为0
Wage = Subsidy = Rent = WaterFee = ElecFee = 0;
}
void setWage ( double f ) {
Wage = f;
}
double getWage( ) {
return Wage;
}
void setSubsidy( double f ) {
Subsidy = f;
}
double getSubsidy( ) {
return Subsidy;
}
void setRent( double f ) {
Rent=f;
}
double getRent(){
return Rent;
}
void setWaterFee( double f ) {
WaterFee=f;
}
double getWaterFee( ) {
return WaterFee;
}
void setElecFee( double f ) {
ElecFee=f;
}
double getElecFee( ) {
return ElecFee;
}
// 计算实发工资, 实发工资 = Wage + Subsidy - Rent - WaterFee - ElecFee
double RealSalary( ) {
return Wage + Subsidy - Rent - WaterFee - ElecFee;
}
};
int num = 0; //(1)
class Worker
{
private: //(2)
string name;
int age;
string Dept;
Salary *salary = new Salary();
public: //(3)
Worker()
{
num++;
}
Worker(string n,int a,string D)
{
age = age;
name = n;
Dept = D;
num++;
}
~Worker()
{
num--;
}
int getNum()
{
return num;
}
void setAge(int a)
{
age = a;
}
int getAge()
{
return age;
}
void setName(string n)
{
name = n;
}
string getName()
{
return name;
}
void setDept(string D)
{
Dept = D;
}
string getDept()
{
return name;
}
void setSalary(double w,double s,double r,double wf,double ef)
{
salary -> setWage(w);
salary -> setSubsidy(s);
salary -> setRent(r);
salary -> setWaterFee(wf);
salary -> setElecFee(ef);
}
double getSalary()
{
return salary -> RealSalary( );
}
};
int main(){
Worker w1( "John", 30, "design" );
cout << w1.getSalary() << endl;
Worker w2;
cout << "the total num is: " << w1.getNum() << endl;
w2.setName( "Linda" );
cout << "in w2 the name is: " << w2.getName() << endl;
// 基本工资 岗位工资 房租 水费 电费
w2.setSalary( 100000, 400, 300, 200, 100 );
cout << w2.getSalary() << endl;
return 0;
}
4、代码解析
- (1) 定义员工变量,该变量需要为全局变量,注意初始化为0,防止意外。
- (2) 分别声明各个私有成员,年龄为整数型,用 int 即可。注意 salary 为 Salary 类的一个对象,所以需要 new 一下。
- (3) 声明各公有函数,注意变量名需要与 已知函数名(main 函数、以及 Salary 内函数)保持一致,否则会报错。
- (4) 如果就本题而言,其实有很多的函数可以不需要写出来,如
setAge()
、getAge()
、setDept()
、getDept()
。但我们不是为了过题而过,是需要保证编程的合理合法完整性。