问题描述:
输入一个只包含个位数字的简单四则运算表达式字符串,计算该表达式的值
注:
3.1、表达式只含 +, -, *, / 四则运算符,不含括号
3.2、表达式数值只包含个位整数(0-9),且不会出现0作为除数的情况
3.3、要考虑加减乘除按通常四则运算规定的计算优先级
3.4、除法用整数除法,即仅保留除法运算结果的整数部分。比如8/3=2。输入表达式保证无0作为除数情况发生
3.5、输入字符串一定是符合题意合法的表达式,其中只包括数字字符和四则运算符字符,除此之外不含其它任何字符,不会出现计算溢出情况
要求实现函数:
int calculate(int len,char *expStr)
【输入】 int len: 字符串长度;char *expStr: 表达式字符串;
【输出】 无
【返回】 计算结果
示例:
1)输入:char *expStr = “1+4*5-8/3”
函数返回:19
2)输入:char *expStr = “8/3*3”
输入一个只包含个位数字的简单四则运算表达式字符串,计算该表达式的值
注:
3.1、表达式只含 +, -, *, / 四则运算符,不含括号
3.2、表达式数值只包含个位整数(0-9),且不会出现0作为除数的情况
3.3、要考虑加减乘除按通常四则运算规定的计算优先级
3.4、除法用整数除法,即仅保留除法运算结果的整数部分。比如8/3=2。输入表达式保证无0作为除数情况发生
3.5、输入字符串一定是符合题意合法的表达式,其中只包括数字字符和四则运算符字符,除此之外不含其它任何字符,不会出现计算溢出情况
要求实现函数:
int calculate(int len,char *expStr)
【输入】 int len: 字符串长度;char *expStr: 表达式字符串;
【输出】 无
【返回】 计算结果
示例:
1)输入:char *expStr = “1+4*5-8/3”
函数返回:19
2)输入:char *expStr = “8/3*3”
函数返回:6
第一种方法:利用后缀表达式:
#include<stdio.h>
#include<stdlib.h>
#include<stack>
using namespace std;
int calculate(int len,char *expStr)
{
int i;
int j=0;
char * postfix = (char*)malloc(sizeof(char)*len);
stack<char> oper;
for(i=0;i<len;i++)//计算后缀表达式
{
if(expStr[i]>='0' && expStr[i]<='9')
postfix[j++] = expStr[i];
else
switch(expStr[i])
{
case'+':
case'-':if(oper.empty())
{
oper.push(expStr[i]);
break;
}
while(!oper.empty() && oper.top()!='(')
{//如果是'+'或'-',就把栈顶及以以下的元素全部出栈到后缀表达式中,
//(按照当前元素优先级小于或等于栈顶元素,则将栈顶元素出栈的原则,
//如果栈顶元素是'(',则认为 '(' 优先级最小。因此将'+'或'-'压栈。
postfix[j++] = oper.top();
oper.pop();
}
oper.push(expStr[i]);
break;
case'*':
case'/':if(oper.empty())
{
oper.push(expStr[i]);
break;
}
if(oper.top()!='*'&&oper.top()!='/')
oper.push(expStr[i]);
else
{
while(!oper.empty() && (oper.top()=='*' || oper.top()=='/'))
{
postfix[j++] = oper.top();
oper.pop();
}
oper.push(expStr[i]);
}
break;
case'(':oper.push(expStr[i]);break;//左括号在进栈前,认为优先级是最大的
case')':while(oper.top()!='(')
{//当前元素是右括号时,认为右括号的优先级最小,将栈中元素都出栈到
//后缀表达式中,直到遇到左括号,这时直接将左括号弹出(删除),而
//且右括号也不入栈(后缀表达式中是没有括号的)
postfix[j++] = oper.top();
oper.pop();
}
oper.pop();
break;
default:exit(0);
}
}
while(!oper.empty())
{
postfix[j++] = oper.top();
oper.pop();
}
postfix[j]='\0';
//printf("%s\n",postfix);
//利用后缀表达式求值
//每当遇到一个操作符是,就将它的前两个数弹出
//计算相应的值以后,再把结果入栈
int postfix_len = strlen(postfix);
stack<int> pos_str;
int t1,t2,t;
for(i=0;i<postfix_len;i++)
{
if(postfix[i]!='+'&&postfix[i]!='-'&&postfix[i]!='*'&&postfix[i]!='/')
pos_str.push(postfix[i]-'0');
else
{
t1 = pos_str.top(); pos_str.pop();
t2 = pos_str.top(); pos_str.pop();
switch(postfix[i])
{
case'+': t = t1+t2;break;
case'-': t = t2-t1;break;//因为先弹出来的t1是减数,t2是被减数
case'*': t = t1*t2;break;
case'/': t = t2/t1;break;//因为先弹出来的t1是除数,然后t2是被除数
default: exit(0);
}
pos_str.push(t);
}
}
int result = pos_str.top();
return result;
}
int main()
{
char *str="5-(4+5)*2*7/4-5/(3+1)";
int len = strlen(str);
int relVal=calculate(len,str);
printf("%d\n",relVal);
system("pause");
return 0;
}
第二种方法:利用栈和优先级来算,不过这种方法中间计算的结果也不能大于10,并且不能加括号
#include<stdlib.h>
#include<stdio.h>
#include<iostream>
#include<stack>
using namespace std;
stack<char> OPTR;//运算符
stack<int> OPND;//运算数
int In(char c)
{ //判断是否为运算符
switch(c)
{
case '+':
case '-':
case '*':
case '/':
case '#': return 1;
default: return 0;
}
}
char Precede(char t1,char t2) //t1是栈顶元素,t2是原运算式的字符
{
if(t1=='#' && t2=='#')
return '=';
if(t1=='#')
return '<';
if(t2=='#')
return '>';
if(t1=='+' || t1=='-')
{
if(t2=='+' || t2=='-')
return '>';
else
return '<';
}
if(t1=='*' || t1=='/')
return '>';
}
char Operate(char a,char theta,char b)
{
char c;
//a = double(a);
//b = double(b);
a = a-48;
b = b-48;
//int e,f;
//e = a - '0';
//f = b - '0';
switch(theta)
{
case '+': c = a+b+48;
break;
case '-': c = a-b+48;
break;
case '*': c = a*b+48;
break;
case '/': c = a/b+48;
break;
}
//c = char(c);
return c;
}
int calcucate(int len, char *expStr)
{
//char *expStr1 = expStr;
//strcat(expStr1,"#");
int i=0;
char c,theta,a,b;
OPTR.push('#');
c = expStr[i];
char x = OPTR.top();
while(c!='#' || x!='#')
{
c = expStr[i];
if(In(c))//是加减乘除运算符之一
switch(Precede(x,c))
{
case '<':OPTR.push(c);//栈顶元素优先级低
i++;
break;
case '=':i++;
break;
case '>':theta = OPTR.top();
OPTR.pop();
b = OPND.top();
OPND.pop();
a = OPND.top();
OPND.pop();
OPND.push(Operate(a,theta,b));
}
else if(c>='0' && c<='9')
{
OPND.push(c);
i++;
}
else //c是非法字符
{
printf("ERROR\n");
exit(0);
}
x = OPTR.top();
//OPTR.pop();
}
x = OPND.top();
return x;
}
int main()
{
printf("请输入运算式,中间值在0到9之间\n");
//char *expStr = "4+2*1-3+5#";
char *expStr = "1-3+2*1+4*1-1-1#";
int len = strlen(expStr);
int result = calcucate(len , expStr);
printf("%c\n",result);
system("pause");
return 0;
}
第三种方法:用数组模拟栈的实现,不带括号
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int calculate(int len,char *expStr)
{
int* data = (int*)malloc(sizeof(int)*len);
char* oper = (char*)malloc(sizeof(char)*len);
int datatop = -1;
int opertop = -1;
int num=0;
int num1=0;
int num2=0;
memset(data,0,sizeof(int)*len);
memset(oper,0,sizeof(char)*len);
for(int i=0;i<len;i++)
{
if( expStr[i]>='0' && expStr[i]<='9')//如果是数字,就将它压入data栈
data[++datatop] = expStr[i]-'0';
if(expStr[i]=='+' || expStr[i]=='-')//如果是字符,'+','-',就将它压入oper栈
oper[++opertop] = expStr[i];
if(expStr[i]=='*')//如果是乘号,就把乘号左右两边的数字相乘,将得到的结果放入data中。
{
num1 = data[datatop];
num2 = expStr[++i]-'0';
num = num1*num2;
data[datatop] = num;
}
if(expStr[i]=='/')
{
num1 = data[datatop];
num2 = expStr[++i]-'0';
num = num1/num2;
data[datatop] = num;
}
}
char oper_now;//计算只有加减的运算
int flag = datatop;
int data_num = 0,oper_num = 0;
while(data_num<flag)
{
num1 = data[data_num++];
num2 = data[data_num];
oper_now = oper[oper_num++];
if(oper_now=='+')
{
num = num1+num2;
data[data_num] = num;
}
if(oper_now=='-')
{
num = num1-num2;
data[data_num] = num;
}
}
return data[data_num];
}
int main()
{
char * str = "2-3-5+4*3-2";
int len = strlen(str);
int result=calculate(len,str);
printf("%d\n",result);
return 0;
}
以上都是操作数是个位数,如果操作数大于1位,那么我们可以用以下方法来将多个字符转化为数字:
int leftNum = convertToDigit(pInputStr)
<p>int convertToDigit(const char *&str)//将从str开始的数字即其后的数字转换为int,最终str指向下一个运算符或'\0'.</p><p>{</p><p> int result = 0;</p>
while (isdigit(*str))
{
result = result * 10 + (*str - '0');
str++;
}
return result;
}
操作数大于1位的四则运算的代码:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<ctype.h>
int covertodigit(char *s,int &num)
{
int m=0;
while( isdigit(*s) )
{
m = m*10+(*s-'0');
s++;
num++;
}
return m;
}
int calculate(int len,char *expStr)
{
int *data = (int *)malloc(sizeof(int)*len);
char *oper = (char *)malloc(sizeof(char)*len);
int datatop = -1;
int opertop = -1;
int sum = 0;
int m = 0;
int num = 0;
for(int i=0;i<len;i++)
{
if(isdigit(expStr[i]))
{
m = covertodigit(expStr+i,num);
i = i+ num-1 ;
data[++datatop] = m;
num = 0;
}
else
{
if(expStr[i]=='+' || expStr[i] =='-')
oper[++opertop] = expStr[i];
else
{
if(expStr[i]=='*')
data[datatop] = data[datatop] * (expStr[++i]-'0');
if(expStr[i]=='/')
data[datatop] = data[datatop] / (expStr[++i]-'0');
}
}
}
sum = data[0];
int k=0;
for(int j=1;j<=datatop;j++)
{
if(oper[k]=='+')
sum = sum + data[j];
if(oper[k]=='-')
sum = sum - data[j];
k++;
}
return sum;
}
int main()
{
char * str = "20-3-5+4*3-2";
int len = strlen(str);
int result=calculate(len,str);
printf("%d\n",result);
return 0;
}