您的位置:首页 > 编程语言 > C语言/C++

C++实现算术四则运算

2013-11-11 20:11 246 查看
四则运算是指仅包含数字及‘+’ ‘-’ ‘*’ ‘/‘和括号’(‘ ’)‘的算式;

此题在2014小米笔试2014美团笔试中均曾出现。

编程考虑:

首要的问题在于四则运算顺序的考虑,首先计算括号内的结果,而后计算乘法,最后计算加法。

数据结构:

这种四则运算的题目,最好的实现方法,是利用两个栈或者两个链表等类似结构,其中一个存储当前结果,一个存储当前优先级较高的结果运算后的结果。以此来获得整体的运算结果。

编程实现:

(1) 如利用双栈进行操作,首先将现有字符串依次压入栈A,当遇到括号时,将括号内的算式单独提出,递归调用,并将返回结果压入栈A;

(2) 此时栈A中即去除了括号,而后将栈A中的值依次弹出,如果为数字和加法均压入栈B,若出现乘号或出号,则由B中弹出第一个操作数,由A中弹出第二个操作数,两个相乘或相除后压入栈B,此时栈B中仅有加减法;

(3) 而后类似结果(2)将栈依次操作压入栈A;最后弹出A的栈顶元素即可。

需要处理的异常情况:

(1)  多重括号问题。比如  ((1+2)*3+4)/2

(2)  括号不匹配问题。比如  ((1+2)*3   或  1+2)*3等等

(3)  输入为空问题。

(4)  除数为0的问题。

(5)  异常输入问题,输入非数字及运算符号的其他符号的问题。

1.包含括号的代码如下:

struct Nnode
{
float num;
char c;
};
float computestr(char *str)
{
int left=0,right=0;
int len=strlen(str);
int bracketNUM(0);
stack<Nnode> s1;
stack<Nnode> s2;
int number=0;
Nnode temp;
for (int i=0;i<len;)
{
int original=i;
while(i<len&&str[i]>='0'&&str[i]<='9')
{
number=number*10+str[i]-'0';
i++;
}
if (i!=original)//有数字且可能为0,将数字压入堆栈
{
temp.num=number;
temp.c=NULL;
s1.push(temp);
number=0;
}
if (i<len&&(str[i]=='+' || str[i]=='-'|| str[i]=='*'|| str[i]=='/'))//压入符号
{
temp.c=str[i];
temp.num=NULL;
s1.push(temp);
i++;
}
if (i<len&&str[i]=='(')//if includes brackets
{
bracketNUM=1;//multi brackets
left=i;
int j=i+1;
for (;j<=len;j++)
{
if (bracketNUM==0)
//bracket matches
{
right=j-1;
char *bracket=(char *)malloc((right-left)*sizeof(char));
int bracketLen=0;
for (int k=left+1;k<right;k++)
{
bracket[bracketLen++]=str[k];
}
bracket[bracketLen]='\0';
float ret = computestr(bracket);//将括号重新处理
temp.num = ret;
temp.c = NULL;
s1.push(temp);
free(bracket);
break;
}
if (str[j]==')')
{
bracketNUM--;
}
if (j==len&&bracketNUM!=0)
{
cout<<"bracket not matches";
return -1;
break;
}
if (str[j]=='(')//多重括号
{
bracketNUM++;
}
}
i=j;
}
}
while(!s1.empty())//首先计算乘除法
{
Nnode ch=s1.top();
s1.pop();
if (ch.c!='*'&&ch.c!='/')
{
s2.push(ch);
}
else if(ch.c!='*'||ch.c!='/')
{
float v1=s1.top().num;
float v2=s2.top().num;
s1.pop();
s2.pop();
if (ch.c=='*')
{
temp.num=v1*v2;
temp.c=NULL;
s2.push(temp);
}
else if (ch.c=='/')
{
if (v2==0)
{
cout<<"除数为0"<<endl;
return -1;
break;
}
else
{
temp.num=v1/v2;
temp.c=NULL;
s2.push(temp);
}
}

}
}
while (!s2.empty())
{
Nnode ch=s2.top();
s2.pop();
if (ch.c!='+'&&ch.c!='-')
{
s1.push(ch);
}
else if(ch.c=='+'||ch.c=='-')
{
float v1=s2.top().num;
float v2=s1.top().num;
s1.pop();
s2.pop();
if (ch.c=='+')
{
temp.num=v1+v2;
temp.c=NULL;
s2.push(temp);
}
else if (ch.c=='-')
{
//-has changed twice
temp.num=v2-v1;
temp.c=NULL;
s2.push(temp);
}
}
}
return s1.top().num;
}


2.后缀表达式下的四则运算结果

    后缀表达式是指不包含括号,运算符放在两个运算对象的后面,所有的计算按运算符出现的顺序,严格从左向右进行(不再考虑运算符的优先规则,如:(2 + 1) * 3 , 即2 1 + 3 *;因而可以通过两个连续的操作数与位于其后的操作数相结合从而首先获得结合结果;类似上面的计算结果,可以有如下代码实现:类似的,也可以编写前缀表达式的输出结果。

float computestrmid(char *str)
{
int len=strlen(str);
stack<Nnode> s1;
stack<Nnode> s2;
int number=0;
for (int i=0;i<len;)
{
if (str[i]==' ')//ignore the space
{
i++;
continue;
}
int original=i;
while(i<len&&str[i]>='0'&&str[i]<='9')
{
number=number*10+str[i]-'0';
i++;
}
if (i!=original)//有数字且可能为0,将数字压入堆栈
{
Nnode numb;
numb.num=number;
numb.c=NULL;
s1.push(numb);
number=0;
}
if (i<len&&(str[i]=='+' || str[i]=='-'|| str[i]=='*'|| str[i]=='/'))//压入符号
{
Nnode ch;
ch.c=str[i];
ch.num=0;
s1.push(ch);
i++;
}
}
int flagnum(0);
while(!s1.empty())
{
Nnode elem=s1.top();
s1.pop();
if (elem.c==NULL)//当前是数字
{
s2.push(elem);
flagnum++;
}
else//当前是符号
{
if (flagnum>=2)//有两个操作数出现
{
float num1=s2.top().num;
s2.pop();
float num2=s2.top().num;
s2.pop();
Nnode temp;
if (elem.c=='+')
{
float result=num1+num2;
temp.num=result;
}
else if (elem.c=='-')
{
float result=num1-num2;
temp.num=result;
}
else if (elem.c=='*')
{
float result=num1*num2;
temp.num=result;
}
else if (elem.c=='/')
{
float result=num1/num2;
if (num2==0)
{
cout<<"除数为0"<<endl;
return -1;
break;
}
temp.num=result;
}
temp.c=NULL;
s2.push(temp);
flagnum--;
}
else
{
s2.push(elem);
}
}
}
return s2.top().num;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息