C++实现“简单计算器”

最近在看九度上面的题目,其中一道题本以为比较简单,但花了不少时间,题目如下:

题目1019:简单计算器

我的思路是先读入一个字符串,再将字符串里面的数字和运算符号分别提取出来,最后根据运算的先后顺序计算得到最后的结果,程序清单如下:

#include<iostream>
#include<vector>
#include<string>
#include<cmath>
#include<iomanip>

using namespace std;

string  skipblacks(string str) //忽略空格
{
    string return_str="";
    int length=str.length();
    for(int i=0;i<length;i++)
		if(str[i]!=' ')
			 return_str+=str[i];
    return return_str;
}

string str_dele(string s,int m)    //删除字符串str的第m个字符
{
	int len=s.length(); 
	char temp_str[100];

	if(m>len)
		cout<<"删除的位置不对!"<<endl;
	else
	{
		int j = 0;
		for(int i = 0;i<s.size();i++)
		{
			if(i==m-1) 
				continue;
			else 
				temp_str[j++]=s[i];
		}
	}
	for(int i=0,j=0;j<len-1;)
		s[j++]=temp_str[i++];
	string sn = "";
	for(int i = 0;i<s.size()-1;++i)
		sn += s[i];
	return sn;
}

vector<double> renew(vector<double> num,double tmpresult,int i)
{
	vector<double> vnew;
	for(int j = 0;j<i;++j)
		vnew.push_back(num[j]);
	vnew.push_back(tmpresult);
	if(i < num.size()-2)
		for(int j = i + 2;j<num.size();++j)
			vnew.push_back(num[j]);

	return vnew;
}

vector<char> clearchch(vector<char> vch)  //去除乘号除号
{
	vector<char> nvch;
	for(int i = 0;i<vch.size();++i)
		if(vch[i] != '*'&&vch[i] != '/')
			nvch.push_back(vch[i]);

	return nvch;
}

int main()
{
	string str;
	vector<double> result;//保存结果
	while(getline(cin,str))
	{
		if(str == "0")
			break;
		vector<char> vch;
		vector<int> vi;
		string s = skipblacks(str);//忽略字符串中的空格

		for(int i = 0;i<s.size();++i)
		{
			if((s[i]=='+')|(s[i]=='-')|(s[i]=='*')|(s[i]=='/'))
				vch.push_back(s[i]); //保存运算符哈
			else if(s[i]>='0'&&s[i]<='9')
				vi.push_back(s[i]-'0'); //保存数字
		}

		string ns = s;
		vector<double> vpos;//记录运算符号在原字符串中的位置
		vector<double> vnum;//记录每个数的位数
		for(int i = 0;i<vch.size();++i)
		{
			size_t pos = ns.find(vch[i]);
			ns = str_dele(ns,pos+1);
			vpos.push_back(pos+i+1);
		}

		vnum.push_back(vpos[0]-1);
		for(int i = 0;i<vpos.size()-1;++i)
			vnum.push_back(vpos[i+1]-vpos[i]-1);

		double tmpsum = 0;
		for(int i = 0;i<vnum.size();++i)
			tmpsum += vnum[i];
		double tmps = s.size()-vch.size()-tmpsum;
		vnum.push_back(tmps);

		vector<double> num;//将vi转化为数字
		double tmpn = 0;
		for(int i = 0;i<=vch.size();++i)
		{
			double sum = 0;
			tmpn += vnum[i];
			for(int j = 0;j<vnum[i];++j)
				sum += vi[j+tmpn-vnum[i]]*pow(10,vnum[i]-1-j);
			num.push_back(sum);
		}
	
		vector<double> vnew = num;
		int ccnt = 0;
		for(int i = 0;i<vch.size();++i)
		{
			if((vch[i] == '*')|(vch[i] == '/'))
			{
				double tmpresult;
				if(vch[i] == '*')
					tmpresult = num[i]*num[i+1];
				else
					tmpresult = num[i]/num[i+1];
				vnew = renew(vnew,tmpresult,i-ccnt);//更新结果
				++ccnt; //统计已经计算过多少个*和/。
			}
		}

		vector<char> nvch = clearchch(vch);//去除乘号和除号只剩下加减号
		double restmp = vnew[0];
		for(int i = 0;i<nvch.size();++i)
		{
			if(nvch[i] == '+')
				restmp = restmp + vnew[i+1];
			else
				restmp = restmp - vnew[i+1];
		}
		result.push_back(restmp);
	}
	for(int i = 0;i<result.size();++i)
		cout<<fixed<<setprecision(2)<<result[i]<<endl;  //保留两位小数

	system("pause");
	return 0;
}

演示结果如下:


从结果可以看到,实现了题设的要求,但是奇怪的是提交代码之后显示“ Wrong Answer”,暂时还不知道是啥原因。

在编写这个程序的过程中,遇到很多细节问题和一些编程基本知识,在这里总结一下:

(1)保留小数点位数,参见博客C++ 标准输出控制小数点后位数的方法

(2)实现“忽略一个字符串里的空格”和“删除字符串中某个字符或某个位置的字符”这样类似的功能可以编写一个函数进行实现;

(3)在进行除法运算时,要注意整形数据到双精度形数据过程可能会损失掉小数部分,可以先将整形数据转化为双精度形数据再进行计算;

(4)读取整行数据用getline(cin,str)实现。


此外,我在九度论坛里也看到很多特别简洁的答案,深感佩服,其中贴出一个代码如下:

#include "stdio.h"
#include "string.h"
#define MAX 1001

double stack[MAX];
int tail;

int main(){
	int a;
	while(scanf("%d ",&a)&&a!=0){
		tail=0;
		stack[++tail]=1.0*a;//tail始终指向末尾数字位置
		//1.入栈所有数据(如果遇到*/号,只更新栈尾)
		char ch1,ch2;
		while(scanf("%c %d%c",&ch1,&a,&ch2)!=EOF){
			if(ch1=='+'){
				stack[++tail]=1.0*a;//push
			}else if(ch1=='-'){
				stack[++tail]=-1.0*a;//push neg
			}else if(ch1=='*'){
				stack[tail]=stack[tail]*a;//update tail
			}else if(ch1=='/'){
				stack[tail]=stack[tail]/(double)a;//updata tail
			}
			if(ch2!=' ')
				break; 
		}
		//2.把栈里头的东西全部加起来,求和
		double result=0;
		for(int i=1;i<=tail;i++)
			result+=stack[i];
		printf("%.2lf\n",result);
	}
	return 1;
}

代码只有30多行,却实现了题目所要求的功能,感觉C++真是博大精深!

  • 24
    点赞
  • 90
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值