2017Final进位与借位(C++)

凤湖小学二年级的陈老师发现学生在三位数加减法运算中存在三种错误模式,分别为完全正确、忽略借位和忽略进位。通过继承基类Group创建了三个子类GroupA、GroupB和GroupC,分别对应三种运算能力的学生。

题目详情

凤湖小学二年级的陈老师吃惊地发现班上的同学竟然可以分成三类,一类总是可以正确地完成三位整数加减法(GroupA);一类总是可以正确地完成三位整数的加法,但对于减法运算来说,总是忘记借位的处理(GroupB);剩下的人总是忘记加法的进位,也总是忘记减法的借位(GroupC)。

现在请给出一次陈老师在课堂提问时,同学们会给出的回答。

实现时请基于下面的基类框架

class Group

{

public:

virtual int add(int x, int y)=0;//输出加法的运算结果

virtual int sub(int x, int y)=0;//输出减法的运算结果

}

构建出GroupA, GroupB和GroupC三个派出类:

并编写主函数,要求主函数中有一个基类Group指针数组,通过该数组元素统一地进行add和sub运算。

输入格式:

首先输入一个整数n,这是班级的人数, 不超过20。

接下来再输入n个数字(取值为1,2,或3),它是各个学生所属的类别,第一个数字是第一位学生的类别,接下来是第二位学生的类别,..., 最后是第n位学生的类别。类别为1时,表明该学生是第A类;为2时,表明该生是B类,为3时表明是C类。

接下来每一行输入一个数学问题。数学问题由两部分构成,第一部分被提问学生的编号,它是一个不超过n的正整数,1表示第一位学生,2表示第二位学生,n表示第n位学生; 第二部分是具体的数学题,可能是加法,也可能是减法。注意:运算对象和加减号之间没有空格,两个运算对象均是不超过999的非负整数, 减法时,被减数不小于减数。

如果某一行以0开头,则说明提问结束。

输出格式:

输出指定学生对于给定的问题的回答。

输入样例:

4
1 2 3 3
1 79+81
2 81-79
4 183+69
0

输出样例:

160
12
142

 




一开始我是用两个数组分别记录下每个数上各个位数上的值来计算的,但后面发现有更方便的计算方法。

一开始的AC代码(最多3位数和3位数的计算) 

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <stdlib.h>
#include <algorithm>
using namespace std;

class Group
{
public:
	virtual int add(int x, int y)=0;//输出加法的运算结果
	virtual int sub(int x, int y)=0;//输出减法的运算结果
};

class GroupA:public Group
{
public:
	int add(int x, int y){
		return x+y;
	}
	int sub(int x, int y){
		return x-y;
	}
};

class GroupB:public Group
{
public:
	int add(int x, int y){
		return x+y;
	}
	int sub(int x, int y){
		int num1[4]={0};
		int num2[4]={0};
		int i=0, j=0;
		do{
			num1[i++]=x%10;
			num2[j++]=y%10;
			x/=10;
			y/=10;
		}while(x||y);
		
		int n=i, tmp=1, sum=0;
		for(int k=0;k<n;k++)
		{
			if(num1[k]<num2[k]) {
				sum=sum+tmp*(10+num1[k]-num2[k]);
			}else{
				sum=sum+tmp*(num1[k]-num2[k]);
			}
			tmp=tmp*10;
		}
		
		return sum;
	}
};
		
class GroupC:public Group
{
public:
	int add(int x, int y){
		int num1[4]={0};
		int num2[4]={0};
		int i=0, j=0;
		do{
			num1[i++]=x%10;
			num2[j++]=y%10;
			x/=10;
			y/=10;
		}while(x||y);
		
		int n=i, tmp=1, sum=0;
		for(int k=0;k<n;k++)
		{
			sum=sum+(num1[k]+num2[k])%10*tmp;
			tmp=tmp*10;
		}
		
		return sum;
	}
	
	int sub(int x, int y){
		int num1[4]={0};
		int num2[4]={0};
		int i=0, j=0;
		do{
			num1[i++]=x%10;
			num2[j++]=y%10;
			x/=10;
			y/=10;
		}while(x||y);
		
		int n=i, tmp=1, sum=0;
		for(int k=0;k<n;k++)
		{
			if(num1[k]<num2[k]) {
				sum=sum+tmp*(10+num1[k]-num2[k]);
			}else{
				sum=sum+tmp*(num1[k]-num2[k]);
			}
			tmp=tmp*10;
		}
		
		return sum;
	}
};

int main()
{
	int n,i=0, stu[22]={0}, temp,x,y;
	char ch;
	cin>>n;
	while(++i<=n && cin>>stu[i]) ;
	
	while(cin>>temp && temp!=0) {
		cin>>x>>ch>>y;
		if(stu[temp]==1){
			GroupA a;
			if(ch=='+'){
				cout<<a.add(x,y)<<endl;
			}else if(ch=='-'){
				cout<<a.sub(x,y)<<endl;
			}
		}else if(stu[temp]==2){
			GroupB b;
			if(ch=='+'){
				cout<<b.add(x,y)<<endl;
			}else if(ch=='-'){
				cout<<b.sub(x,y)<<endl;
			}
		}else if(stu[temp]==3){
			GroupC c;
			if(ch=='+'){
				cout<<c.add(x,y)<<endl;
			}else if(ch=='-'){
				cout<<c.sub(x,y)<<endl;
			}
		}
	}
	return 0;
}

 

后来发现的更好的解法,这里只放GroupB和GroupC的关键函数sub和GroupC的add函数 (任意位数,不用数组)

int sub(int x,int y) { //忘记借位的减法 
int z = x-y, i=10; //先算出正确的值 
while(x && y) { //x和y只要有1个为0就退出循环 
	if(x%10<y%10) c+=i; //x的某位比y的对于位的数值更小说明要加i ,因为这类同学减法是不借位的
	
		x/=10; 
		y/=10;
		i*=10;
	}
	return z;
}

int add(int x,int y) { //忘记进位的加法
	int z = x+y, i=10; //先算出正确的值
	while(x && y) { //x和y只要有1个为0就退出循环 
		if(x%10 + y%10 >= 10) c-=i; //x和y的某位上的数值相加大于10则需要减去i
		
		x/=10;
		y/=10;
		i*=10;
	}
	return z;
}
	


 

2-1 2017Final进位借位 分数 20 作者 何振峰 单位 福州大学 凤湖小学二年级的陈老师吃惊地发现班上的同学竟然可以分成三类,一类总是可以正确地完成三位整数加减法(GroupA);一类总是可以正确地完成三位整数的加法,但对于减法运算来说,总是忘记借位的处理(GroupB);剩下的人总是忘记加法的进位,也总是忘记减法的借位(GroupC)。 现在请给出一次陈老师在课堂提问时,同学们会给出的回答。 实现时请基于下面的基类框架 class Group { public: virtual int add(int x, int y)=0;//输出加法的运算结果 virtual int sub(int x, int y)=0;//输出减法的运算结果 } 构建出GroupA, GroupB和GroupC三个派出类: 并编写主函数,要求主函数中有一个基类Group指针数组,通过该数组元素统一地进行add和sub运算。 输入格式: 首先输入一个整数n,这是班级的人数, 不超过20。 接下来再输入n个数字(取值为1,2,或3),它是各个学生所属的类别,第一个数字是第一位学生的类别,接下来是第二位学生的类别,..., 最后是第n位学生的类别。类别为1时,表明该学生是第A类;为2时,表明该生是B类,为3时表明是C类。 接下来每一行输入一个数学问题。数学问题由两部分构成,第一部分被提问学生的编号,它是一个不超过n的正整数,1表示第一位学生,2表示第二位学生,n表示第n位学生; 第二部分是具体的数学题,可能是加法,也可能是减法。注意:运算对象和加减号之间没有空格,两个运算对象均是不超过999的非负整数, 减法时,被减数不小于减数。 如果某一行以0开头,则说明提问结束。 输出格式: 输出指定学生对于给定的问题的回答。 输入样例: 4 1 2 3 3 1 79+81 2 81-79 4 183+69 0 输出样例: 160 12 142
最新发布
05-17
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

重剑DS

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值