这道题分解出来,首先是分离运算符和数字,然后考虑运算顺序求结果。
1.分离运算符和数字
1)由题意,输入是浮点数,用到atof,如下。
头文件:#include <stdlib.h>
定义函数:double atof(const char *nptr);
函数说明:atof()会扫描参数nptr 字符串,跳过前面的空格字符,直到遇上数字或正负符号才开始做转换,而再遇到非数字或字符串结束时('\0')才结束转换,并将结果返回。参数nptr 字符串可包含正负号、小数点或E(e)来表示指数部分,如123. 456 或123e-2。
注意加粗划线字体说明的,atof遇到开头空格跳过,结尾空格结束,并会读入正负。为了统一,我把字符串的运算符读取并改成空格。
2)在处理的时候有一种情况,比如 -1*-1*-1 就是乘除号两边有负数,这时候减号保留,只读出乘除。
2.运算顺序
1)方法:在前面,我把浮点数存数组,并且优先扫乘除,在乘除中是从左到右运算,所以遵循数组中相邻两数做乘除,结果保留在右,左边赋值0.
2)这时候会出现两种符号的存在情况,一种是跟在乘除前面,由于按右边存值,所以直接扫后把右边(i+1)变号就可以:
二是正常的减,把对应位(i)变号。
扫描二维码关注公众号,回复:
1072884 查看本文章
![](/qrcode.jpg)
3)这时你可能会问,+号呢?经过前面的处理,只需求出处理后的数组和就可得到计算结果!
#include<bits/stdc++.h> #define N 200 using namespace std; double DoingCal(char Calcu[],double Num[],int cnt1,int cnt2) { double result=0; for(int i=1;i<=cnt1;i++) { if(Calcu[i]=='*'||Calcu[i]=='/') //依据运算顺序,先处理乘除 { if(Calcu[i]=='*') Num[i+1]=Num[i]*Num[i+1]; else Num[i+1]=Num[i]/Num[i+1]; Num[i]=0; //靠右算,运算结果保留在i+1,i处赋0 if(Calcu[i-1]=='-') Num[i+1]*=-1; //处理乘除符号的前一个减号,是减号对应的计算结果变号 } /*for(int i=1;i<=cnt2;i++) cout<<Num[i]<<" "; cout<<endl;*/ } for(int i=1;i<=cnt1;i++) { if(Calcu[i]=='-'&&Calcu[i+1]!='/'&&Calcu[i+1]!='*') //处理后面没有乘除符号的减号,对应的数变号 Num[i+1]*=-1; /*for(int i=1;i<=cnt2;i++) cout<<Num[i]<<" "; cout<<endl;*/ } for(int i=1;i<=cnt1+1;i++) //处理完的数组相加 result+=Num[i]; return result; //返回计算结果 } int main() { char instructStr[N],Calcu[N]; //instructStr,存最初输入的计算指令(待加工);Calcu,存计算符号 int t,i; double Num[N]; //存分离出来的数 cin>>t; //输入测试次数 while(t--) { int cnt1=0; int cnt2=0; int flag=1; //状态,1表示输入的第一个字符为数字,0为正or负号 cin>>instructStr; if(instructStr[0]>'9'||instructStr[0]<'0') //初加工,保证instructStr[0]是数字 { flag=0; strcpy(instructStr,&instructStr[1]); } for(i=0;instructStr[i]!='\0';i++) //运算符号录入 { int flag1=1; if((instructStr[i]>'9'||instructStr[i]<'0')&&instructStr[i]!='.') //该if防止“.”录入 { if(instructStr[i]=='-'&&instructStr[i-1]==' ') //为便于运算,乘或除号前面的减号忽略不录入,后面运算函数详细说明 flag1=0; if(flag1) { Calcu[++cnt1]=instructStr[i]; instructStr[i]=' '; //把运算符变为空格,因为atof遇符号停止转化。 } } } /*cout<<instructStr<<endl; for(i=1;i<=cnt1;i++) cout<<Calcu[i]<<" "; cout<<endl;*/ for(i=0;instructStr[i]!='\0';i++) //字符转浮点,见对atof使用说明 { if( (instructStr[i-1]==' '||!i) ) //如果读到空格或者开头,对后一位的数字(i=0是对开头)执行转浮点,遇到空格结束。 { Num[++cnt2]=atof(&instructStr[i]); //cout<<Num[cnt2]<<endl; } /*for(j=i;;j++) { if(instructStr[j]==' '&&instructStr[j]=='\0') { i=j-1; break; } }*/ } if(!flag) //开头的符号被清,补上 Num[1]*=-1; /*for(int i=1;i<=cnt2;i++) cout<<Num[i]<<" "; cout<<endl;*/ cout<<fixed<<setprecision(2)<<DoingCal(Calcu,Num,cnt1,cnt2)<<endl; } return 0; } //PS:这是本渣的第一篇博,在打完之后我发现其实代码里面很多处理比较鸡肋,但是好处是思路比较清晰,各位多指教!