不智能的计算器
最近公司事情不是很多,就像随便写个东西玩玩,可惜想了半天想不到 。最后只能做个自己大学时没做的很简单的程序。也算了了遗憾,可是做起来的时候才发现原来黑框的计算器也不是好做的,无奈只能google,发现了一种方法比较流行,就生成树比如说(1+2)*3呢,就按权值不同生成的树是:
生成树(图比较粗糙啊)
理解是挺好理解的,但是程序写起来确很费事,需要双向链表及二叉树。可是我就是那种很少用数据结构的人,可能编程的时间太短,很多东西都不是很懂。
但是我自己想了个方法,也不知道算不算方法,总之很乱,我自己看都要看半天才可以理解。
好了废话不说了,上代码(很多的可能出现bug的地方都没有处理,所以可能bug很多)
#include <windows.h>
#include <iostream>
#include <fstream>
#include <string>
#include <cmath>
using namespace std;
#define PI 3.14159265358979
#define EE 2.71828182818281
const string NUM = "0123456789.";
const string OPERATION = "+-*/";
namespace MyCalc
{
class Fun
{
public:
Fun(string o, double lVal, double rVal):op(o), lValue(lVal), rValue(rVal){}
static string FUN[];
double calc();
private:
string op;
double lValue;
double rValue;
};
string Fun::FUN[] = {"!","sin","cos","tan","log","ln","C","A","^","-"};
int factorial(int n) //阶乘函数
{
int i,s=1;
for(i=1;i<=n;i++)
s*=i;
return s;
}
int C(int a,int b)
{
return factorial(a)/(factorial(b)*factorial(a-b));
}
int A(int a,int b)
{
return factorial(a)/factorial(b);
}
double Fun::calc() //计算系统函数的值
{
if(op=="!")
return factorial(lValue);
if(op=="sin")
return sin(rValue/180*PI);
if(op=="cos")
return cos(rValue/180*PI);
if(op=="tan")
return tan(rValue/180*PI);
if(op=="log")
return log10(rValue);
if(op=="ln")
return log10(rValue)/log10(EE);
if(op=="C")
return C(lValue,rValue);
if(op=="A")
return A(lValue,rValue);
if(op=="^")
return pow(lValue,rValue);
if(op=="-")
return -rValue;
else
{
string err="暂时没有函数"+op;
MessageBox(NULL,err.c_str(),"错误",MB_OK);
return 0;
}
}
}
#include "MyCalc.h"
typedef struct _Operation
{
char cOperation;
int iWeight;
}Operation, *POperation;
bool IsNum(char c)
{
if(NUM.find(c) != string::npos)
return true;
return false;
}
bool IsOperation(char c)
{
if(OPERATION.find(c) != string::npos)
return true;
return false;
}
//others are treated as function.
bool IsFun(char c)
{
if(!IsNum(c) && ! IsOperation(c) && c !=
'(' && c != ')' && c != ' ')
return true;
return false;
}
double calc(double lValue, double rValue, char operation)
{
switch(operation)
{
case '+':
return rValue + lValue;
case '-':
return lValue - rValue;
case '*':
return lValue * rValue;
case '/':
return lValue / rValue;
default:
return 0;
}
}
//Getting a number from input string
void getNum(string inputStr, int &i, int &valuesNum, double dValues[])
{
int iPoint = 0;
dValues[valuesNum] = 0.0;
while (i < inputStr.length())
{
if(inputStr[i] == '.')
{
iPoint++;
i++;
continue;
}
if(iPoint == 0)
dValues[valuesNum] *= 10;
dValues[valuesNum] += (inputStr[i] - '0')*pow(10.0, -iPoint);
i++;
if(iPoint != 0)
iPoint++;
if(!IsNum(inputStr[i]))
{
i--;
valuesNum++;
return;
}
}
}
//deal with functions
void HandlingFunction(string inputStr, int &valuesNum, double dValues[], int &i)
{
string op = "";
while(i++)
{
if(i < inputStr.length())
{
if(IsOperation(inputStr[i]))
{
MyCalc::Fun * fun = new MyCalc::Fun(op, dValues[valuesNum - 1], 0.0);
dValues[valuesNum - 1] = fun->calc();
break;
}
else if(IsNum(inputStr[i]))
{
getNum(inputStr, i, valuesNum, dValues);
MyCalc::Fun *fun = new MyCalc::Fun(op, dValues[valuesNum -2], dValues[-1]);
dValues[valuesNum -1] = fun->calc();
valuesNum --;
break;
}
}
else
{
MyCalc::Fun * fun = new MyCalc::Fun(op, dValues[valuesNum - 1], 0.0);
dValues[valuesNum - 1] = fun->calc();
break;
}
op += inputStr[i];
}
}
double GetValue(string inputStr)
{
int iWeigth = 0;
int l_point = 0;
double dValues[] = {0.0, 0.0, 0.0};
int valuesNum = 0;
POperation pOperation = (POperation)malloc(sizeof(Operation) * 4);
string op = "";
for (int i = 0;i < inputStr.length();i++)
{
if(inputStr[i] == '(')
{
iWeigth += 3;
continue;
}
else if(inputStr[i] == ')')
{
iWeigth -= 3;
if(iWeigth < 0)
{
MessageBox(NULL, "Inputting brackets are not matched!", "MyCalc", MB_OK);
return 0;
}
if(valuesNum > 1 && (i + 1) < inputStr.length() && IsFun(inputStr[i + 1]))
{
dValues[0] = calc(dValues[0], dValues[1], pOperation[-1].cOperation);
valuesNum--;
HandlingFunction(inputStr, valuesNum, dValues, i);
}
continue;
}
else if(IsNum(inputStr[i]))
{
getNum(inputStr, i, valuesNum, dValues);
}
else if(IsOperation(inputStr[i]))
{
int add_weight = 0;
if(inputStr[i] == '+' || inputStr[i] == '-')
add_weight = 1;
else if(inputStr[i] == '*' || inputStr[i] == '/')
add_weight = 2;
pOperation->cOperation = inputStr[i];
pOperation->iWeight = add_weight + iWeigth;
pOperation++;
}
//treat as a function
if((i + 1) < inputStr.length() && IsFun(inputStr[i + 1]))
{
HandlingFunction(inputStr, valuesNum, dValues, i);
}
if(valuesNum == 3)
{
if(pOperation[-2].iWeight > pOperation[-1].iWeight)
{
dValues[0] = calc(dValues[0], dValues[1], pOperation[-2].cOperation);
dValues[1] = dValues[2];
pOperation[-2] = pOperation[-1];
}
else
{
dValues[1] = calc(dValues[1], dValues[2], pOperation[-1].cOperation);
}
pOperation--;
valuesNum = 2;
}
}
pOperation--;
double lastValue = 0.0;
if(valuesNum == 2)
lastValue = calc(dValues[0], dValues[1], pOperation->cOperation);
else
lastValue = dValues[0];
free(pOperation);
return lastValue;
}
void main()
{
string exp;
ifstream infile("c:\\test.txt");
while(getline(infile,exp))
{
if(exp=="")
continue;
cout<<exp<<" = "<<GetValue(exp)<<endl;
}
}