小程式(十六)簡單四則運算
阿新 • • 發佈:2019-01-20
問題描述:
輸入一個只包含個位數字的簡單四則運算表示式字串,計算該表示式的值
注:
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;
}