1. 程式人生 > >小程式(十六)簡單四則運算

小程式(十六)簡單四則運算

問題描述:
輸入一個只包含個位數字的簡單四則運算表示式字串,計算該表示式的值
注:
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;  
} 


相關推薦

no