Калькулятор

Калькулятор.
Произвести синтаксический анализ строки, задающей математическое выражение, содержащее скобки, операции умножения, деления, вычитания, суммирования, тригонометрические функции и условный оператор. Вычислить результат.

Программа способна вычислять сложные математические выражения следующего вида:
3 + 2 * ( 4 + cos( Pi ) )/( 3 + 4 > 2 ? 1 : 0 ) + 3 % 2;
Это математическое выражение полностью исчерпывает все возможности калькулятора.

Функция GetToken определяет функции, операции и числа, последовательно считывая строку из входного потока.
Функция Expr определяет самые низкоуровневые операции "+", "-", ">" между выражениями.
Функция Term определяет операции "*", "/", "%".
Функция Prim анализирует самые глубокие выражения ,а так же числа.

По аналогии с представленными возможностями данного калькулятора, можно построить достаточно большое количество функций и операций над числами. Например, операции возведения встепень, бинарное сложение и умножение( по аналогии с "*", "/" );
sin(), tg(), ctg(), abs() ( по аналогии с cos() ); ">= ? :", "< ? :", "<= ? :", "== ? :", "!= ? :" ( по аналогии с "> ? :" )

#include <iostream.h>
#include <ctype.h>
#include <conio.h>
#include <math.h>
 
enum TToken { NUMBER, END, COS };
 
TToken CurrTok;
double NumberValue;
 
double Expr();
double Term();
double Prim();
double Error(const char * Msg);
TToken GetToken();
 
void main()
{
 
  CurrTok = GetToken();
  cout << Expr() << endl;
  getch();
}
 
double Expr()
{
  double Left = Term();
 
  for (;;)
    switch (CurrTok) {
      case '+': GetToken();
		  Left += Term();
		  break;
      case '-': GetToken();
		  Left -= Term();
		  break;
      case '>': GetToken();
		 double Right = Expr();
		 if( (char)CurrTok != '?' ) return Error("Error Expr > Expr _?_ Expr : Expr");
		 GetToken();
		 double E1 = Expr();
		 if( (char)CurrTok !=  ':' ) return Error("Error Expr > Expr ? Expr _:_ Expr");
		 GetToken();
		 double E2 = Expr();
		 Left =  Left > Right ? E1 : E2;
		 break;
      default:  return Left;
    }
}
 
double Term()
{
  double Left = Prim();
  double D;
  long _D;
  for (;;)
    switch (CurrTok) {
      case '*': GetToken(); Left *= Prim(); break;
      case '/': GetToken();
		D = Prim();
		if (D == 0) return Error("division by zero");
		Left /= D;
		break;
	  case '%': GetToken();
		  D = Prim();
		  _D = (long)D;
		  if( _D - D  != 0) return Error(" '%' : right hand double");
		  if( (float)Left - (long)Left != 0 ) return Error(" '%' : left hand double");
		  Left = (long)(Left)%_D;
		break;
 
      default:  return Left;
    }
}
 
double Prim()
{
	double E;
  switch (CurrTok) {
    case NUMBER: GetToken(); return NumberValue;
    case    '+': GetToken(); return +Prim();
    case    '-': GetToken(); return -Prim();
    case    '(': GetToken();
		 E = Expr();
		 if (CurrTok != ')') return Error("Expected \")\"");
		 GetToken();
		 return E;
    case     COS: GetToken();
		 E = cos( Expr() );
		 if( CurrTok != ')') return Error("Expected \")\"");
		 GetToken();
		 return E;
      case    END: return 1;
    default: return Error("Expected Prim");
  }
}
 
double Error(const char * ErrorMsg)
{
  cerr << "Error: " << ErrorMsg << "\n";
  return 1;
}
 
TToken GetToken()
{
  char ch = cin.get();
 
  while (isspace(ch) && ch != '\n') ch = cin.get();
 
  switch (ch) {
    case '\n':
      return CurrTok = END;
 
    case '*': case '/': case '+': case '-': case '(': case ')': case '%':
    case '>': case '?': case ':':
      return CurrTok = TToken(ch);
	  /*cos*/
    case 'c':
		ch = cin.get();
		if( ch != 'o' ) { Error(" in 'cos': undefine functin"); return CurrTok = END; }
		ch = cin.get();
		if( ch != 's' ) { Error(" in 'cos': undefine functin"); return CurrTok = END; }
		ch = cin.get();
		if( ch != '(' ) { Error(" in 'cos': Expected - )"); return CurrTok = END; }
		return CurrTok = COS;
		/*Pi*/
	case 'P':
		ch = cin.get();
		if( ch != 'i' ) { Error(" in 'cos': undefine functin"); return CurrTok = END; }
		NumberValue = 3.14;
		return CurrTok = NUMBER;
 
    case '0': case '1': case '2': case '3': case '4':
    case '5': case '6': case '7': case '8': case '9':
      cin.putback(ch);
      cin >> NumberValue;
      return CurrTok = NUMBER;
 
    default:
      Error("Error: lexical scope");
      return CurrTok = END;
  }
}

Ключевые слова: 
калькулятор, математическое выражение, функция, синтаксический анализ
ВложениеРазмер
Калькулятор21.95 кб