添加项目文件。
This commit is contained in:
31
ScientificCalculator.sln
Normal file
31
ScientificCalculator.sln
Normal file
@@ -0,0 +1,31 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.14.36127.28 d17.14
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ScientificCalculator", "ScientificCalculator\ScientificCalculator.vcxproj", "{5C991D9D-797E-4C35-8C97-E6F43099CBD6}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|x64 = Debug|x64
|
||||
Debug|x86 = Debug|x86
|
||||
Release|x64 = Release|x64
|
||||
Release|x86 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{5C991D9D-797E-4C35-8C97-E6F43099CBD6}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{5C991D9D-797E-4C35-8C97-E6F43099CBD6}.Debug|x64.Build.0 = Debug|x64
|
||||
{5C991D9D-797E-4C35-8C97-E6F43099CBD6}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{5C991D9D-797E-4C35-8C97-E6F43099CBD6}.Debug|x86.Build.0 = Debug|Win32
|
||||
{5C991D9D-797E-4C35-8C97-E6F43099CBD6}.Release|x64.ActiveCfg = Release|x64
|
||||
{5C991D9D-797E-4C35-8C97-E6F43099CBD6}.Release|x64.Build.0 = Release|x64
|
||||
{5C991D9D-797E-4C35-8C97-E6F43099CBD6}.Release|x86.ActiveCfg = Release|Win32
|
||||
{5C991D9D-797E-4C35-8C97-E6F43099CBD6}.Release|x86.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {227C30D6-2F25-4EA4-B670-3C930B28DA7B}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
44
ScientificCalculator/Calc.cpp
Normal file
44
ScientificCalculator/Calc.cpp
Normal file
@@ -0,0 +1,44 @@
|
||||
#include "Calc.h"
|
||||
#include <iostream>
|
||||
|
||||
// <20><>̬<EFBFBD><CCAC>Ա<EFBFBD><D4B1>ʼ<EFBFBD><CABC>
|
||||
Tokenizer Calc::tokenizer;
|
||||
InfixToPostfix Calc::converter;
|
||||
PostfixEval Calc::evaluator;
|
||||
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӿڣ<D3BF><DAA3><EFBFBD><EFBFBD><EFBFBD>ʽ<EFBFBD>ַ<EFBFBD><D6B7><EFBFBD> -> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
double Calc::eval(const string& expression) {
|
||||
vector<Token> tokens = tokenizer.run(expression);
|
||||
vector<Token> postfix = converter.run(tokens);
|
||||
return evaluator.run(postfix);
|
||||
}
|
||||
|
||||
// <20><>ȫ<EFBFBD><C8AB><EFBFBD><EFBFBD><EFBFBD>ӿڣ<D3BF><DAA3><EFBFBD> try-catch <20><>װ<EFBFBD><D7B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD> bool <20><>־
|
||||
bool Calc::safeEval(const string& expr, double& res) {
|
||||
try {
|
||||
res = eval(expr);
|
||||
return true;
|
||||
}
|
||||
catch (const exception& e) {
|
||||
cerr << "[Error] " << e.what() << endl;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// <20><><EFBFBD>Խӿڣ<D3BF><DAA3><EFBFBD>ӡ<EFBFBD>м<EFBFBD><D0BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>token <20>б<EFBFBD> <20><> <20><><EFBFBD><D7BA><EFBFBD><EFBFBD>ʽ<EFBFBD><CABD>
|
||||
void Calc::debug(const string& expr) {
|
||||
try {
|
||||
vector<Token> tokens = tokenizer.run(expr);
|
||||
cout << "[Token List]" << endl;
|
||||
for (const auto& t : tokens) cout << t.value << " ";
|
||||
cout << endl;
|
||||
|
||||
vector<Token> postfix = converter.run(tokens);
|
||||
cout << "[Postfix]" << endl;
|
||||
for (const auto& t : postfix) cout << t.value << " ";
|
||||
cout << endl;
|
||||
}
|
||||
catch (const exception& e) {
|
||||
cerr << "[Debug Error] " << e.what() << endl;
|
||||
}
|
||||
}
|
||||
28
ScientificCalculator/Calc.h
Normal file
28
ScientificCalculator/Calc.h
Normal file
@@ -0,0 +1,28 @@
|
||||
#ifndef CALC_H
|
||||
#define CALC_H
|
||||
|
||||
#include"Tokenizer.h"
|
||||
#include"InfixToPostfix.h"
|
||||
#include"PostfixEval.h"
|
||||
#include<optional>
|
||||
#include<unordered_map>
|
||||
|
||||
using namespace std;
|
||||
|
||||
class Calc {
|
||||
public:
|
||||
//<2F><><EFBFBD>ӿں<D3BF><DABA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʽ<EFBFBD>ַ<EFBFBD><D6B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ؼ<EFBFBD><D8BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
static double eval(const string& expresssion);
|
||||
|
||||
//<2F><>ȫ<EFBFBD>ӿڣ<D3BF><DAA3><EFBFBD><EFBFBD>쳣<EFBFBD><ECB3A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>optional
|
||||
static bool safeEval(const string& expr,double& res);
|
||||
|
||||
//<2F><><EFBFBD>Ժ<EFBFBD><D4BA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӡtoken<65>б<EFBFBD><D0B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><D7BA><EFBFBD><EFBFBD>ʽ
|
||||
static void debug(const string& expr);
|
||||
private:
|
||||
static Tokenizer tokenizer;
|
||||
static InfixToPostfix converter;
|
||||
static PostfixEval evaluator;
|
||||
};
|
||||
|
||||
#endif
|
||||
74
ScientificCalculator/InfixToPostfix.cpp
Normal file
74
ScientificCalculator/InfixToPostfix.cpp
Normal file
@@ -0,0 +1,74 @@
|
||||
#include "InfixToPostfix.h"
|
||||
#include <stdexcept>
|
||||
|
||||
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><CAB9><EFBFBD>沨<EFBFBD><E6B2A8><EFBFBD><EFBFBD>ʾ<EFBFBD><CABE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><D7BA><EFBFBD><EFBFBD>ʽת<CABD><D7AA>Ϊ<EFBFBD><CEAA><EFBFBD><D7BA><EFBFBD><EFBFBD>ʽ
|
||||
vector<Token> InfixToPostfix::run(const vector<Token>& infix) {
|
||||
vector<Token> output;// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ջ
|
||||
stack<Token> opStack;//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><D7BA><EFBFBD><EFBFBD>ʽ
|
||||
|
||||
for (const Token& token : infix) {
|
||||
if (token.is_num() || token.is_var())
|
||||
//<2F><><EFBFBD>ֻ<EFBFBD><D6BB><EFBFBD><EFBFBD><EFBFBD>ֱ<EFBFBD>ӷ<EFBFBD><D3B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
output.push_back(token);
|
||||
else if (token.is_fun())
|
||||
//<2F><><EFBFBD><EFBFBD>ѹ<EFBFBD><D1B9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ջ<EFBFBD><D5BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȼ<EFBFBD><C8BC><EFBFBD><EFBFBD>ߣ<EFBFBD>
|
||||
opStack.push(token);
|
||||
else if (token.is_ope()) {
|
||||
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ջ<EFBFBD><D5BB><EFBFBD><EFBFBD><EFBFBD>ȼ<EFBFBD><C8BC><EFBFBD><EFBFBD><EFBFBD><DFBB><EFBFBD>ͬ<EFBFBD>ҽ<EFBFBD><D2BD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD><EFBFBD>ϵ<EFBFBD><CFB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
while (!opStack.empty() && opStack.top().is_ope() &&
|
||||
(precedence(opStack.top()) > precedence(token) ||
|
||||
(precedence(opStack.top()) == precedence(token) && associativity(token) == Associativity::Left))) {
|
||||
output.push_back(opStack.top());
|
||||
opStack.pop();
|
||||
}
|
||||
//<2F><>ǰ<EFBFBD><C7B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ջ
|
||||
opStack.push(token);
|
||||
}
|
||||
else if (token.is_LP())
|
||||
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ţ<EFBFBD>ֱ<EFBFBD><D6B1><EFBFBD><EFBFBD>ջ
|
||||
opStack.push(token);
|
||||
else if (token.is_RP())
|
||||
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ţ<EFBFBD><C5A3><EFBFBD><EFBFBD><EFBFBD>ջ<EFBFBD><D5BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֱ<EFBFBD><D6B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
pop_ULP(opStack, output);
|
||||
}
|
||||
|
||||
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><F3A3ACB5><EFBFBD>ջ<EFBFBD><D5BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
while (!opStack.empty()) {
|
||||
if (opStack.top().is_LP() || opStack.top().is_RP())
|
||||
throw runtime_error("<EFBFBD><EFBFBD><EFBFBD>Ų<EFBFBD>ƥ<EFBFBD><EFBFBD>");//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ų<EFBFBD>ƥ<EFBFBD><C6A5>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
output.push_back(opStack.top());
|
||||
opStack.pop();
|
||||
}
|
||||
|
||||
return output;//<2F><><EFBFBD>غ<EFBFBD><EFBFBD><D7BA><EFBFBD><EFBFBD>ʽ<EFBFBD><CABD><EFBFBD><EFBFBD>
|
||||
}
|
||||
|
||||
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȼ<EFBFBD><C8BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Խ<EFBFBD><D4BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȼ<EFBFBD>Խ<EFBFBD><D4BD>
|
||||
int InfixToPostfix::precedence(const Token& token) const {
|
||||
return token.precedence;
|
||||
}
|
||||
|
||||
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԣ<EFBFBD><D4A3><EFBFBD>/<2F><>
|
||||
Associativity InfixToPostfix::associativity(const Token& token) const {
|
||||
return token.associativity;
|
||||
}
|
||||
|
||||
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ţ<EFBFBD><C5A3><EFBFBD><EFBFBD><EFBFBD>ջ<EFBFBD><D5BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֪<EFBFBD><D6AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
void InfixToPostfix::pop_ULP(stack<Token>& opStack, vector<Token>& output) {
|
||||
//<2F><><EFBFBD><EFBFBD>ֱ<EFBFBD><D6B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
while (!opStack.empty() && !opStack.top().is_LP()) {
|
||||
output.push_back(opStack.top());
|
||||
opStack.pop();
|
||||
}
|
||||
|
||||
//<2F><><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>׳<EFBFBD><D7B3>쳣
|
||||
if (opStack.empty())
|
||||
throw runtime_error("<EFBFBD><EFBFBD><EFBFBD>Ų<EFBFBD>ƥ<EFBFBD>䣺ȱʧ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>");
|
||||
opStack.pop(); // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
|
||||
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֮ǰ<D6AE>Ǻ<EFBFBD><C7BA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҳ<EFBFBD><D2B2>ջ<EFBFBD><D5BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
if (!opStack.empty() && opStack.top().is_fun()) {
|
||||
output.push_back(opStack.top());
|
||||
opStack.pop();
|
||||
}
|
||||
}
|
||||
27
ScientificCalculator/InfixToPostfix.h
Normal file
27
ScientificCalculator/InfixToPostfix.h
Normal file
@@ -0,0 +1,27 @@
|
||||
#ifndef INFIX_TO_POSTFIX_H
|
||||
#define INFIX_TO_POSTFIX_H
|
||||
|
||||
#include"Token.h"
|
||||
#include<vector>
|
||||
#include<stack>
|
||||
|
||||
using namespace std;
|
||||
|
||||
class InfixToPostfix {
|
||||
public:
|
||||
//<2F><>ת<EFBFBD><D7AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><D7BA><EFBFBD><EFBFBD>ʽת<CABD><D7AA>Ϊ<EFBFBD><CEAA><EFBFBD><D7BA><EFBFBD><EFBFBD>ʽ
|
||||
vector<Token> run(const vector<Token>& infix);
|
||||
|
||||
private:
|
||||
//<2F><><EFBFBD><EFBFBD>ָ<EFBFBD><D6B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȼ<EFBFBD>
|
||||
int precedence(const Token& token) const;
|
||||
|
||||
//<2F>ж<EFBFBD><D0B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ľ<EFBFBD><C4BD><EFBFBD><EFBFBD>ԣ<EFBFBD><D4A3><EFBFBD>/<2F>ң<EFBFBD>
|
||||
Associativity associativity(const Token& token) const;
|
||||
|
||||
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD>ջ<EFBFBD>е<EFBFBD><D0B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֱ<EFBFBD><D6B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
void pop_ULP(stack<Token>& opStack, vector<Token>& output);
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
97
ScientificCalculator/PostfixEval.cpp
Normal file
97
ScientificCalculator/PostfixEval.cpp
Normal file
@@ -0,0 +1,97 @@
|
||||
#include"PostfixEval.h"
|
||||
#include<algorithm>
|
||||
#include<cctype>
|
||||
|
||||
double PostfixEval::run(const std::vector<Token>& postfix, const unordered_map<string, double>& vars) {
|
||||
stack<double> stk;
|
||||
|
||||
for (const auto& token : postfix) {
|
||||
if (token.is_num())
|
||||
//<2F><><EFBFBD><EFBFBD>ת<EFBFBD><D7AA>Ϊdouble<6C><65>ջ
|
||||
stk.push(stod(token.value));
|
||||
else if (token.is_var()) {
|
||||
//<2F><><EFBFBD>ұ<EFBFBD><D2B1><EFBFBD>ӳ<EFBFBD><D3B3><EFBFBD><EFBFBD>
|
||||
auto it = vars.find(token.value);
|
||||
// ֧<><D6A7><EFBFBD><EFBFBD><EFBFBD>ó<EFBFBD><C3B3><EFBFBD> PAI <20><> e
|
||||
|
||||
if (it == vars.end()) {
|
||||
if (token.value == "PAI")
|
||||
stk.push(2.0 * std::asin(1.0)); // <20><> = 2 * arcsin(1)
|
||||
else if (token.value == "e")
|
||||
stk.push(std::exp(1.0)); // e = exp(1)
|
||||
else
|
||||
throw runtime_error("<EFBFBD><EFBFBD><EFBFBD><EFBFBD>δ<EFBFBD><EFBFBD><EFBFBD>壺" + token.value);
|
||||
}
|
||||
else stk.push(it->second);
|
||||
}
|
||||
else if (token.is_ope()) {
|
||||
//ȡ<><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ִ<EFBFBD>ж<EFBFBD>Ԫ<EFBFBD><D4AA><EFBFBD><EFBFBD>
|
||||
if (stk.size() < 2) throw runtime_error("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>");
|
||||
double b = stk.top();
|
||||
stk.pop();
|
||||
double a = stk.top();
|
||||
stk.pop();
|
||||
double res = apply_BO(token.value, a, b);
|
||||
stk.push(res);
|
||||
}
|
||||
else if (token.is_fun()) {
|
||||
//ȡ<><C8A1>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ִ<EFBFBD><D6B4>һԪ<D2BB><D4AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ⱥ<EFBFBD><C8BA><EFBFBD><EFBFBD>ļ<EFBFBD><C4BC><EFBFBD>
|
||||
if (stk.empty()) throw runtime_error("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>");
|
||||
double x = stk.top();
|
||||
stk.pop();
|
||||
double res = apply_UF(token.value, x);
|
||||
stk.push(res);
|
||||
}
|
||||
else
|
||||
throw runtime_error("δ֪Token<EFBFBD><EFBFBD><EFBFBD><EFBFBD>");
|
||||
}
|
||||
|
||||
if (stk.size() != 1)
|
||||
throw runtime_error("<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ջ<EFBFBD><EFBFBD>Ψһ");
|
||||
|
||||
return stk.top();
|
||||
}
|
||||
|
||||
//<2F><><EFBFBD>ж<EFBFBD>Ԫ<EFBFBD><D4AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
double PostfixEval::apply_BO(const string& op, double a, double b) {
|
||||
if (op == "+") return a + b;
|
||||
if (op == "-") return a - b;
|
||||
if (op == "*") return a * b;
|
||||
if (op == "/") {
|
||||
if (b == 0) throw runtime_error("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ0");
|
||||
return a / b;
|
||||
}
|
||||
if (op == "^") return pow(a, b);
|
||||
if (op == "%") {
|
||||
if (b == 0) throw runtime_error("ģ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD>");
|
||||
return std::fmod(a, b);
|
||||
}
|
||||
throw runtime_error("δ֪<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>" + op);
|
||||
}
|
||||
|
||||
//<2F><><EFBFBD><EFBFBD>һԪ<D2BB><D4AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ⱥ<EFBFBD><C8BA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
double PostfixEval::apply_UF(const string& func, double x) {
|
||||
string f = func;
|
||||
transform(f.begin(), f.end(), f.begin(), ::tolower);
|
||||
|
||||
if (f == "sin") return sin(x);
|
||||
if (f == "cos") return cos(x);
|
||||
if (f == "tan") return tan(x);
|
||||
if (f == "sqrt") {
|
||||
if (x < 0)
|
||||
throw runtime_error("sqrt<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD>");
|
||||
return sqrt(x);
|
||||
}
|
||||
if (f == "log") {
|
||||
if (x <= 0)
|
||||
throw runtime_error("log<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>0");
|
||||
return log(x);
|
||||
}
|
||||
if (f == "exp") return exp(x);
|
||||
if (f == "abs") return fabs(x);
|
||||
if (f == "asin") return asin(x);
|
||||
if (f == "acos") return acos(x);
|
||||
if (f == "atan") return atan(x);
|
||||
|
||||
throw runtime_error("δ֪<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>" + func);
|
||||
}
|
||||
25
ScientificCalculator/PostfixEval.h
Normal file
25
ScientificCalculator/PostfixEval.h
Normal file
@@ -0,0 +1,25 @@
|
||||
#ifndef POSTFIXEVAL_H
|
||||
#define POSYFIXEVAL_H
|
||||
|
||||
#include "Token.h"
|
||||
#include <vector>
|
||||
#include <stack>
|
||||
#include <cmath>
|
||||
#include <stdexcept>
|
||||
#include<unordered_map>
|
||||
|
||||
using namespace std;
|
||||
class PostfixEval {
|
||||
public:
|
||||
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ժ<EFBFBD><EFBFBD><D7BA><EFBFBD><EFBFBD>ʽ<EFBFBD><CABD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ
|
||||
double run(const std::vector<Token>& postfix, const unordered_map<string, double>& vars = {});
|
||||
|
||||
private:
|
||||
//Ӧ<><D3A6><EFBFBD>ڶ<EFBFBD>Ԫ<EFBFBD><D4AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>+<2B><>-<2D><>*<2A><>/<2F><>^
|
||||
double apply_BO(const string& op, double a, double b);
|
||||
|
||||
//Ӧ<><D3A6><EFBFBD><EFBFBD>ҽԺ<D2BD><D4BA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ⱥ<EFBFBD><C8BA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>sin, cos, log
|
||||
double apply_UF(const string& func, double x);
|
||||
};
|
||||
|
||||
#endif
|
||||
142
ScientificCalculator/ScientificCalculator.vcxproj
Normal file
142
ScientificCalculator/ScientificCalculator.vcxproj
Normal file
@@ -0,0 +1,142 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>17.0</VCProjectVersion>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<ProjectGuid>{5c991d9d-797e-4c35-8c97-e6f43099cbd6}</ProjectGuid>
|
||||
<RootNamespace>ScientificCalculator</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="Calc.h" />
|
||||
<ClInclude Include="InfixToPostfix.h" />
|
||||
<ClInclude Include="PostfixEval.h" />
|
||||
<ClInclude Include="Token.h" />
|
||||
<ClInclude Include="Tokenizer.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="Calc.cpp" />
|
||||
<ClCompile Include="InfixToPostfix.cpp" />
|
||||
<ClCompile Include="main.cpp" />
|
||||
<ClCompile Include="PostfixEval.cpp" />
|
||||
<ClCompile Include="Tokenizer.cpp" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
51
ScientificCalculator/ScientificCalculator.vcxproj.filters
Normal file
51
ScientificCalculator/ScientificCalculator.vcxproj.filters
Normal file
@@ -0,0 +1,51 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="源文件">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="头文件">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="资源文件">
|
||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="Tokenizer.cpp">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="InfixToPostfix.cpp">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="PostfixEval.cpp">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Calc.cpp">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="main.cpp">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="Token.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Tokenizer.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="InfixToPostfix.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="PostfixEval.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Calc.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
52
ScientificCalculator/Token.h
Normal file
52
ScientificCalculator/Token.h
Normal file
@@ -0,0 +1,52 @@
|
||||
#ifndef TOKEN_H
|
||||
#define TOKEN_H
|
||||
|
||||
#include<string>
|
||||
|
||||
using namespace std;
|
||||
//<2F>Ǻ<EFBFBD><C7BA><EFBFBD><EFBFBD><EFBFBD>
|
||||
enum class TokenType {
|
||||
Number,
|
||||
Operator,
|
||||
LeftParen,
|
||||
RightParen,
|
||||
Function,
|
||||
Variable
|
||||
};
|
||||
|
||||
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
enum class Associativity {
|
||||
Left,
|
||||
Right,
|
||||
None
|
||||
};
|
||||
|
||||
//Token<65>ṹ<EFBFBD><E1B9B9>
|
||||
struct Token {
|
||||
TokenType type;//<2F>Ǻ<EFBFBD><C7BA><EFBFBD><EFBFBD><EFBFBD>
|
||||
string value; //ʵ<><CAB5><EFBFBD>ַ<EFBFBD><D6B7><EFBFBD>
|
||||
int precedence = -1; //<2F><><EFBFBD>ȼ<EFBFBD><C8BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͺ<EFBFBD><CDBA><EFBFBD><EFBFBD><EFBFBD>Ч
|
||||
Associativity associativity = Associativity::None; //<2F><><EFBFBD><EFBFBD><EFBFBD>ԣ<EFBFBD><D4A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͺ<EFBFBD><CDBA><EFBFBD><EFBFBD><EFBFBD>Ч
|
||||
|
||||
//<2F><><EFBFBD>캯<EFBFBD><ECBAAF>
|
||||
Token(TokenType t, const string& v,
|
||||
int p = -1, Associativity assoc = Associativity::None)
|
||||
:type(t), value(v), precedence(p), associativity(assoc) {}
|
||||
|
||||
//<2F><><EFBFBD><EFBFBD><EFBFBD>жϷ<D0B6><CFB7><EFBFBD>
|
||||
|
||||
// <20>ж<EFBFBD><D0B6>Ƿ<EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD>֣<EFBFBD><D6A3><EFBFBD><EFBFBD><EFBFBD> "3.14", "42"<22><>
|
||||
bool is_num() const { return type == TokenType::Number; }
|
||||
// <20>ж<EFBFBD><D0B6>Ƿ<EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> "+", "-", "*", "/"<22><>
|
||||
bool is_ope() const { return type == TokenType::Operator; }
|
||||
// <20>ж<EFBFBD><D0B6>Ƿ<EFBFBD>Ϊ<EFBFBD><CEAA>ѧ<EFBFBD><D1A7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> "sin", "cos", "log"<22><>
|
||||
bool is_fun() const { return type == TokenType::Function; }
|
||||
// <20>ж<EFBFBD><D0B6>Ƿ<EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD><EFBFBD><EFBFBD> "("<22><><EFBFBD><EFBFBD><EFBFBD>ڱ<EFBFBD><DAB1><EFBFBD>ʽ<EFBFBD><CABD><EFBFBD><EFBFBD>
|
||||
bool is_LP() const { return type == TokenType::LeftParen; }
|
||||
// <20>ж<EFBFBD><D0B6>Ƿ<EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ")"<22><><EFBFBD><EFBFBD><EFBFBD>ڱ<EFBFBD><DAB1><EFBFBD>ʽ<EFBFBD><CABD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
bool is_RP() const { return type == TokenType::RightParen; }
|
||||
// <20>ж<EFBFBD><D0B6>Ƿ<EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> "x", "y"<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>չ֧<D5B9>ַ<EFBFBD><D6B7>Ŵ<EFBFBD><C5B4><EFBFBD><EFBFBD><EFBFBD>
|
||||
bool is_var()const { return type == TokenType::Variable; }
|
||||
|
||||
};
|
||||
#endif
|
||||
115
ScientificCalculator/Tokenizer.cpp
Normal file
115
ScientificCalculator/Tokenizer.cpp
Normal file
@@ -0,0 +1,115 @@
|
||||
#include"Tokenizer.h"
|
||||
#include<cctype>
|
||||
#include<stdexcept>
|
||||
|
||||
using namespace std;
|
||||
|
||||
vector<Token> Tokenizer::run(const string& expr) {
|
||||
expression = expr;
|
||||
pos = 0;
|
||||
vector<Token> tokens;
|
||||
|
||||
// <20><>ѭ<EFBFBD><D1AD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD><D6B7><EFBFBD>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD>ʽ
|
||||
while (pos < expression.length()) {
|
||||
skipWhitespace();// <20><><EFBFBD><EFBFBD><EFBFBD>հ<EFBFBD><D5B0>ַ<EFBFBD>
|
||||
if (pos >= expression.length()) break;
|
||||
|
||||
char current = expression[pos];
|
||||
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֻ<EFBFBD>һԪ<D2BB><D4AA><EFBFBD>ſ<EFBFBD>ͷ<EFBFBD><CDB7><EFBFBD><EFBFBD>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
if (is_dig(current) || (current == '-' && is_UMC(tokens)))
|
||||
tokens.push_back(readNumber());
|
||||
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĸ<EFBFBD><C4B8><EFBFBD><EFBFBD>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
else if (is_let(current))
|
||||
tokens.push_back(readIdentifier());
|
||||
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
else
|
||||
tokens.push_back(readOperatorOrParen());
|
||||
}
|
||||
|
||||
return tokens;
|
||||
}
|
||||
|
||||
void Tokenizer::skipWhitespace() {
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>пո<D0BF><D5B8><EFBFBD><EFBFBD>Ʊ<EFBFBD><C6B1><EFBFBD><EFBFBD>ȿհ<C8BF><D5B0>ַ<EFBFBD>
|
||||
while (pos < expression.length() && isspace(expression[pos]))
|
||||
++pos;
|
||||
}
|
||||
|
||||
Token Tokenizer::readNumber() {
|
||||
size_t start = pos;
|
||||
bool hasDecimal = false;// <20><><EFBFBD><EFBFBD>С<EFBFBD><D0A1><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD>ֹ<EFBFBD>
|
||||
|
||||
if (expression[pos] == '-')
|
||||
++pos; // <20><><EFBFBD><EFBFBD>һԪ<D2BB><D4AA><EFBFBD>ţ<EFBFBD><C5A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
|
||||
while (pos < expression.length() && (is_dig(expression[pos]) || expression[pos] == '.')) {
|
||||
if (expression[pos] == '.') {
|
||||
if (hasDecimal)
|
||||
throw runtime_error("<EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD>ʽ<EFBFBD><EFBFBD>Ч<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>С<EFBFBD><EFBFBD><EFBFBD><EFBFBD>");// С<><D0A1><EFBFBD><EFBFBD><EFBFBD>ظ<EFBFBD><D8B8><EFBFBD><EFBFBD><EFBFBD>
|
||||
hasDecimal = true;
|
||||
}
|
||||
++pos;
|
||||
}
|
||||
|
||||
string numberStr = expression.substr(start, pos - start);
|
||||
return Token(TokenType::Number, numberStr);// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Token
|
||||
}
|
||||
|
||||
Token Tokenizer::readIdentifier() {
|
||||
size_t start = pos;
|
||||
|
||||
// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĸ<EFBFBD>ַ<EFBFBD><D6B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
while (pos < expression.length() && is_let(expression[pos]))
|
||||
++pos;
|
||||
|
||||
string name = expression.substr(start, pos - start);
|
||||
|
||||
//ʶ<><CAB6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
skipWhitespace();
|
||||
if (pos < expression.length() && expression[pos] == '(')
|
||||
return Token(TokenType::Function, name);
|
||||
else
|
||||
return Token(TokenType::Variable, name);
|
||||
}
|
||||
|
||||
Token Tokenizer::readOperatorOrParen() {
|
||||
char c = expression[pos++]; // <20><>ȡ<EFBFBD><C8A1>ǰ<EFBFBD>ַ<EFBFBD><D6B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD><D6B8>
|
||||
|
||||
// <20>ж<EFBFBD><D0B6>ַ<EFBFBD><D6B7><EFBFBD><EFBFBD>Ͳ<EFBFBD><CDB2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧ Token
|
||||
switch (c) {
|
||||
case '+': return Token(TokenType::Operator, "+", 1, Associativity::Left);
|
||||
case '-': return Token(TokenType::Operator, "-", 1, Associativity::Left);
|
||||
case '*': return Token(TokenType::Operator, "*", 2, Associativity::Left);
|
||||
case '/': return Token(TokenType::Operator, "/", 2, Associativity::Left);
|
||||
case '^': return Token(TokenType::Operator, "^", 3, Associativity::Right);
|
||||
case '(': return Token(TokenType::LeftParen, "(");
|
||||
case ')': return Token(TokenType::RightParen, ")");
|
||||
default:
|
||||
throw runtime_error(string("δ֪<EFBFBD><EFBFBD><EFBFBD><EFBFBD> ") + c); // δ֪<CEB4>ַ<EFBFBD><D6B7><EFBFBD><EFBFBD><EFBFBD>
|
||||
}
|
||||
}
|
||||
|
||||
bool Tokenizer::is_UMC(const vector<Token>& tokens) {
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD>DZ<EFBFBD><C7B1><EFBFBD>ʽ<EFBFBD><CABD>ͷ<EFBFBD><CDB7><EFBFBD><EFBFBD>ǰһ<C7B0><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ţ<EFBFBD><C5A3><EFBFBD><EFBFBD><EFBFBD>ǰ<EFBFBD><C7B0><EFBFBD><EFBFBD>ΪһԪ
|
||||
if (tokens.empty()) return true;
|
||||
Token last = tokens.back();
|
||||
return last.is_ope() || last.is_LP();
|
||||
}
|
||||
|
||||
bool Tokenizer::is_dig(char c) const {
|
||||
// <20>ж<EFBFBD><D0B6>Ƿ<EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD>
|
||||
return std::isdigit(static_cast<unsigned char>(c));
|
||||
}
|
||||
|
||||
bool Tokenizer::is_let(char c) const {
|
||||
// <20>ж<EFBFBD><D0B6>Ƿ<EFBFBD>ΪӢ<CEAA><D3A2><EFBFBD><EFBFBD>ĸ
|
||||
return std::isalpha(static_cast<unsigned char>(c));
|
||||
}
|
||||
|
||||
bool Tokenizer::is_OpeCh(char c) const {
|
||||
// <20>ж<EFBFBD><D0B6>Ƿ<EFBFBD>Ϊ<EFBFBD>Ϸ<EFBFBD><CFB7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD>
|
||||
return c == '+' || c == '-' || c == '*' || c == '/' || c == '^';
|
||||
}
|
||||
40
ScientificCalculator/Tokenizer.h
Normal file
40
ScientificCalculator/Tokenizer.h
Normal file
@@ -0,0 +1,40 @@
|
||||
#ifndef TOKENIZER_H
|
||||
#define TOKENIZER_H
|
||||
|
||||
#include<string>
|
||||
#include<vector>
|
||||
#include"Token.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
class Tokenizer {
|
||||
public:
|
||||
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʽ<EFBFBD>ַ<EFBFBD><D6B7><EFBFBD>ת<EFBFBD><D7AA>ΪToken<65><6E><EFBFBD><EFBFBD>
|
||||
vector<Token> run(const string& expr);
|
||||
|
||||
private:
|
||||
string expression; //<2F><>ǰ<EFBFBD><C7B0><EFBFBD><EFBFBD><EFBFBD>ı<EFBFBD><C4B1><EFBFBD>ʽ
|
||||
size_t pos = 0; //<2F><>ǰָ<C7B0><D6B8>λ<EFBFBD><CEBB>
|
||||
|
||||
//<2F><><EFBFBD>ߺ<EFBFBD><DFBA><EFBFBD>:<3A><><EFBFBD><EFBFBD><EFBFBD>ո<EFBFBD><D5B8>ַ<EFBFBD>
|
||||
void skipWhitespace();
|
||||
|
||||
//<2F><>ȡһ<C8A1><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֣<EFBFBD><D6A3><EFBFBD>С<EFBFBD><D0A1><EFBFBD><EFBFBD>С<EFBFBD><D0A1><EFBFBD>㡢<EFBFBD><E3A1A2><EFBFBD>ܵ<EFBFBD>һԪ<D2BB><D4AA><EFBFBD>ţ<EFBFBD>
|
||||
Token readNumber();
|
||||
|
||||
//<2F><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>(<28><>sin<69><6E>cos<6F><73>log<6F><67>)<29><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>x<EFBFBD><78>y<EFBFBD><79>
|
||||
Token readIdentifier();
|
||||
|
||||
//<2F><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
Token readOperatorOrParen();
|
||||
|
||||
//<2F>жϵ<D0B6>ǰλ<C7B0><CEBB><EFBFBD>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD><EFBFBD>һԪ<D2BB><D4AA><EFBFBD>ŵ<EFBFBD><C5B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
bool is_UMC(const vector<Token>& tokens);
|
||||
|
||||
//<2F>ַ<EFBFBD><D6B7>жϸ<D0B6><CFB8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
bool is_dig(char c)const;
|
||||
bool is_let(char c)const;
|
||||
bool is_OpeCh(char c)const;
|
||||
};
|
||||
|
||||
#endif
|
||||
29
ScientificCalculator/main.cpp
Normal file
29
ScientificCalculator/main.cpp
Normal file
@@ -0,0 +1,29 @@
|
||||
#include <iostream>
|
||||
#include<string>
|
||||
#include "Calc.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
int main() {
|
||||
string input;
|
||||
cout << "<EFBFBD><EFBFBD>ѧ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> (<28><><EFBFBD><EFBFBD> q <20>˳<EFBFBD>)<29><>\n";
|
||||
|
||||
while (true) {
|
||||
cout << "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʽ > ";
|
||||
getline(cin, input);
|
||||
|
||||
if (input == "q" || input == "quit")
|
||||
break;
|
||||
|
||||
double result;
|
||||
if (Calc::safeEval(input, result)) {
|
||||
cout << "= " << result << endl;
|
||||
}
|
||||
else {
|
||||
cout << "[<5B><><EFBFBD><EFBFBD>] <20><><EFBFBD><EFBFBD>ʽ<EFBFBD><EFBFBD><DEB7><EFBFBD><EFBFBD><EFBFBD>\n";
|
||||
}
|
||||
}
|
||||
|
||||
cout << "<EFBFBD><EFBFBD>лʹ<EFBFBD>ã<EFBFBD><EFBFBD>ټ<EFBFBD><EFBFBD><EFBFBD>" << endl;
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user