2442: 【普及-】【P1957】口算练习题

内存限制:128 MB 时间限制:1.000 S
评测方式:文本比较 命题人:
提交:16 解决:8

题目描述

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

输入

第一行为数值 lns="http://www.w3.org/1998/Math/MathML">

接着的 lns="http://www.w3.org/1998/Math/MathML"> 行为需要输入的算式,每行可能有三个数据或两个数据。

若该行为三个数据则第一个数据表示运算类型,lns="http://www.w3.org/1998/Math/MathML">a 表示加法运算,lns="http://www.w3.org/1998/Math/MathML">b 表示减法运算,lns="http://www.w3.org/1998/Math/MathML">c 表示乘法运算,接着的两个数据表示参加运算的运算数。

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

输出

输出 lns="http://www.w3.org/1998/Math/MathML">2× 行。对于每个输入的算式,输出完整的运算式及结果,第二行输出该运算式的总长度

样例输入 复制

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

提示

数据规模与约定

对于 lns="http://www.w3.org/1998/Math/MathML">50% 的数据,输入的算式都有三个数据,第一个算式一定有三个数据。

对于所有数据,lns="http://www.w3.org/1998/Math/MathML">0<50,运算数为非负整数且小于 lns="http://www.w3.org/1998/Math/MathML">10000

分析:

如果每次输入固定是三个数据,那就比较简单了,直接依次读入处理就可以得到这三个数据。但是这里给出的数据,可能是两个数字,也有可能是三个数字,所以就不能直接读入了。因此,可以将整条语句读进字符数组中,然后再根据字符串进行判断,根据不同情况分离出需要的数据,代码如下:

#include<bits/stdc++.h>
using namespace std;

int main(){
    int n,a,b,c;
    char last,s[20],ans[20];
    scanf("%d\n",&n);
    while (n--) {
    	fgets(s,sizeof(s),stdin);  //读入一行
		if (s[0]=='a'||s[0]=='b'||s[0]=='c')
		    last=s[0],s[0]=' ';  //获取计算符号,并替换为空格
		sscanf(s,"%d %d",&a,&b);  //从这个字符串里面读入两个数a和b
		switch (last) {
			case 'a':
				c=a+b;
				sprintf(ans,"%d+%d=%d",a,b,c);
				break;  //+
			case 'b':
				c=a-b;
				sprintf(ans,"%d-%d=%d",a,b,c);
				break;  //-
			case 'c':
				c=a*b;
				sprintf(ans,"%d*%d=%d",a,b,c);
				break;  //*								
		}
		printf("%s\n%d\n",ans,strlen(ans)); //输出 
	}
	return 0;
}

本题使用了fgels()函数来进行读入一行字符串,并存人字符数组中,空格也一起存下了之前常使用的 gets()函数因为存在可能溢出的风险所以不使用。fgets(s,sizeof(s),stdin);这条语句中指定了字符数组的最大读入数量,因此是安全的。

接下来使用了sscanf()函数,可以从已经存储下来的字符串中读入信息。sprintf()可以将信息输出到字符串中。回顾一下scanf()的用法,就会发现 sscanf()和 scanf()是很接近的。比如,sscanf(s,"%d",&a);就可以从s字符串中读入一个整数a。它们的区别是,scanf()是从标准输人中读人,而 sscanf()是从给定的一个字符串中读人,所以要求提供字符数组的名称,表示从哪个字符串里面读入信息。

本题中的指令字符串第一个字符是'a',b','c',这会影响从这个字符串里面读人后面的信息,所以把这个字符赋值为空格,由于scanf()会自动忽视掉空格,所以这样可以规避这个问题。

同理,sprint(s,"%d",a);就可以将一个 int 类型的数a输出到字符串s中而不是标准输出。请读者将这个函数和printf()进行比较。

#include<bits/stdc++.h>
using namespace std;

int main(){
    int n,a,b,c;
    string s,ans,opt;
    char last;
    cin>>n;
    while (n--) {
    	cin>>s;
    	if (s[0]=='a'||s[0]=='b'||s[0]=='c') {
    		last=s[0];
    		cin>>a>>b;
		}    
    	else {
    		a=0;
    		for (int i=0;i<s.length();i++) {
    			a=a*10+s[i]-'0';
			}
    		cin>>b;
		}
		ans="";
    	switch(last) {
    		case 'a':
    			c=a+b;
    			ans+=to_string(a);
    			ans+="+";
    			ans+=to_string(b);
    			ans+="=";
    			ans+=to_string(a+b);
    			break;
    		case 'b':
    			c=a-b;
    			ans+=to_string(a);
    			ans+="-";
    			ans+=to_string(b);
    			ans+="=";
    			ans+=to_string(a-b);
    			break;   
    		case 'c':
    			c=a-b;
    			ans+=to_string(a);
    			ans+="*";
    			ans+=to_string(b);
    			ans+="=";
    			ans+=to_string(a*b);
    			break; 				 			
		}
		cout<<ans<<endl;
		cout<<ans.length()<<endl;    
    	
	}
	return 0;
}