P1957 口算练习题

文章描述了一个编程任务,帮助王老师整理学生常错的口算题。程序需要接受输入的运算数据,可能包含运算符或直接的数字,然后生成详细的算式和结果,同时计算算式的总长度。提供的代码示例展示了如何处理输入和计算长度。
摘要由CSDN通过智能技术生成

题目描述

王老师正在教简单算术运算。细心的王老师收集了i道学生经常做错的口算题,并且想整理编写成一份练习。 编排这些题目是一件繁琐的事情,为此他想用计算机程序来提高工作效率。王老师希望尽量减少输入的工作量,比如 5+8 \texttt{5+8} 5+8 的算式最好只要输入 5 \texttt 5 5 8 \texttt 8 8,输出的结果要尽量详细以方便后期排版的使用,比如对于上述输入进行处理后输出 5+8=13 \texttt{5+8=13} 5+8=13 以及该算式的总长度 6 6 6。王老师把这个光荣的任务交给你,请你帮他编程实现以上功能。

输入格式

第一行为数值 i i i,接着的 i i i 行为需要输入的算式,每行可能有三个数据或两个数据。

若该行为三个数据则第一个数据表示运算类型, a \texttt a a 表示加法运算, b \texttt b b 表示减法运算, c \texttt c c 表示乘法运算,接着的两个数据表示参加运算的运算数。

若该行为两个数据,则表示本题的运算类型与上一题的运算类型相同,而这两个数据为运算数。

输出格式

输出 2 × i 2\times i 2×i 行。对于每个输入的算式,输出完整的运算式及结果,第二行输出该运算式的总长度

样例输入

4
a 64 46
275 125
c 11 99
b 46 64

样例输出

64+46=110
9
275+125=400
11
11*99=1089
10
46-64=-18
9

数据规模与约定

对于 50 % 50\% 50% 的数据,输入的算式都有三个数据,第一个算式一定有三个数据。

对于所有数据, 0 < i ≤ 50 0<i\leq 50 0<i50,运算数为非负整数且小于 10000 10000 10000

思路分析
对于一个算式:a + b = c ,其中 a 和 b 是操作数,c是运算结果,+是运算符,=是等号。
算式a + b = c 的总长度等于a、b、c的长度加上2。

本题的难点在于, 1、当运算符和上一个相同时,就省略。这就造成每行第一次读取的不一定是操作符。
所以,需要对每行的第一次读入结果进行判断,是操作符还是整数。整数可能有多位,所以,第一次读入适合以字符串的方式读入。

重点要解决的问题:
1、对每行第一次读入字符串的判断,如果是操作符,保存;否则,将字符串转换成整数
2、算式长度的计算

学过字符串、ASCII码、循环、分支的同学,经过认真思考,可以写出下面的代码。
参考代码1

#include<iostream>
#include<string>
using namespace std;
char op;
string x;
//计算算式的长度:a的长度、b的长度、运算结果的长度和两个符号
int getlen(int a, int b, int c) {
	int len = 0;
	//累计a的长度
	int t = a;
	if (t == 0) len++; //如果a是0,占1位
	while (t > 0) {
		len++;
		t /= 10;
	}
	//累计b的长度
	t = b;
	if (t == 0) len++; //如果b是0,占1位
	while (t > 0) {
		len++;
		t /= 10;
	}
	//累计运算结果的长度
	t = c;
	if (t == 0) len++; //如果c是0,占1位
	if (t < 0) {//如果c小于0,负号占一位
		len++;
		t = -t;
	}
	while (t > 0) {
		len++;
		t /= 10;
	}
	return len + 2; //总长度等于三个数字的长度加上运算符和等号
}
int main() {
	int n;
	cin >> n;
	for (int i = 0; i < n; i++) {
		int a = 0, b = 0; //每次都用新的变量
		cin >> x;
		//是操作符
		if (x[0] == 'a' || x[0] == 'b' || x[0] == 'c') {
			op = x[0];
			cin >> a >> b;
		} else {
			//不是操作符,就把字符串x变成整数
			for (int k = 0; k < x.size(); k++) {
				int t = x[k] - '0'; //取出一个数字
				a = a * 10 + t;
			}
			cin >> b;
		}
		//做运算
		string s = "";
		switch (op) {
			case 'a': //+
				cout << a << "+" << b << "=" << a + b << endl;
				cout << getlen(a, b, a + b) << endl;
				break;

			case 'b': //+
				cout << a << "-" << b << "=" << a - b << endl;
				cout << getlen(a, b, a - b) << endl;
				break;
			case 'c': //+
				cout << a << "*" << b << "=" << a*b << endl;
				cout << getlen(a, b, a * b) << endl;
		}//switch
	}//for
	return 0;
}

头文件cstdlib 中的atoi()函数可以将字符数组存放的整数转换成int类型。比如字符数组s中存储了三个数字字符’1’,‘2’,‘3’,char s[] = {'1','2','3','\0'}; , 那么 atoi(s) 就能得到整数123。
头文件cctype中的isalpha()函数可以判断一个字符是不是字母。比如,isalpha(‘a’)的结果是true,isalpha(‘3’)的结果是false。
学过函数atoi()和isalpha()的同学可以写出下方的代码:

参考代码2

#include<iostream>
#include<cstdlib>//atoi
#include<cctype> //isalpha,isdigit
using namespace std;
char op, x[1005];
int a, b, n;
//计算算式的长度
int getlen(int a, int b, int c) {
	int len = 0;
	//累计a的长度
	int t = a;
	if(t==0) len++; //0占1位
	while (t > 0) {
		len++;
		t /= 10;
	}
	//累计b的长度
	t = b; 
	if(t==0) len++;//0占1位
	while (t > 0) {
		len++;
		t /= 10;
	}
	//累计运算结果的长度
	t = c;
	if(t==0) len++;//0占1位
	if (t < 0) {//加上负号
		len++;
		t = -t;
	}
	while (t > 0) {
		len++;
		t /= 10;
	}
	return len + 2; //总长度等于三个数字的长度加上运算符和等号
}
int main() {
	cin >> n;
	for (int i = 0; i < n; i++) {
		cin >> x;
		//是操作符
		if (isalpha(x[0])) {
			op = x[0];
			cin >> a >> b;
		} else {
			a = atoi(x); //不是操作符,就将s转换成整数
			cin >> b;
		}
		//做运算
		string s = "";
		switch (op) {
			case 'a': //+
				cout << a << "+" << b << "=" << a + b << endl;
				cout << getlen(a, b, a + b) << endl;
				break;

			case 'b': //+
				cout << a << "-" << b << "=" << a - b << endl;
				cout << getlen(a, b, a - b) << endl;
				break;
			case 'c': //+
				cout << a << "*" << b << "=" << a*b << endl;
				cout << getlen(a, b, a * b) << endl;
		}//switch
	}//for
	return 0;
}

头文件cstdio中的sscanf和sprintf 和对字符数组进行输入输出。
sprintf()的返回值就是字符串的长度,直接保存下来就行了。
对这两个函数熟悉的同学可以写出下方的代码。
参考代码3:

#include <iostream> //cin & cout 用iostream
#include <cstring> //memset & strlen 用cstring
#include <cstdio> //sscanf & sprintf 用cstdio
using namespace std;
char s[100000010], x[10005]; //s-最终的等式,b-读入数据
int main() {
	char op;//用于存储运算符
	int n, a, b; //n-输入的算式数,a、b存储两个操作数
	cin >> n;
	for (int i = 0; i < n; i++) {
		cin >> x; //读入,有可能是运算符,也有可能是数字
		if (x[0] >= 'a' && x[0] <= 'z') {
			op = x[0]; //如果是运算符就存入op,然后读入两个操作数
			cin >> a >> b;
		} else {
			//不是运算符,就将字符串格式的整数转换成int
			sscanf(x, "%d", &a);
			cin >> b; //然后读入第二个整数
		}
		memset(s, 0, sizeof(s)); //每次使用前清空数组
		int m; //用于保存算式的长度
		switch (op) {
			case 'a': //+
			m=sprintf(s, "%d+%d=%d", a, b, a + b); //格式化运算式到字符数组
			break;
			case 'b': // -
			m=sprintf(s, "%d-%d=%d", a, b, a - b); //格式化运算式到字符数组
			break;
			case 'c': //*
			m=sprintf(s, "%d*%d=%d", a, b, a * b); //格式化运算式到字符数组
			
		}
		//输出完整的运算式和算式长度
		cout << s << endl << m << endl;
	}
	return 0;
}

三种方法都可以解题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值