要求
- 采用多个头文件、多个实现文件的方式实现完整程序(使得源代码的物理结构和逻辑结构保持一致);
- 输入中每遇到一个分号或回车(‘\n’)就认为一个完整表达式结束,并将该完整表达式记作一行。在处理过程中累计行数(和行号);
- 对于输入中存在的错误,除了提示错误现象外,还需提示相应的出错行号(即表达式的序号)。
- 必须支持命令行参数,以指明从何处读取所有表达式。
- 命令行参数中的第2项开始,指定0~多个输入文件之路径。输入文件就是普通的文本文件,其中预先输入了若干表达式,内容及格式 均与来自标准输入的完全相同。
- 若命令行参数未指明输入文件,则程序从标准输入设备(cin)读取表达式。
- 若命令行指明了1~N个输入文件,则程序依次从这些文件读入表达式,并按照读到的顺序依次处理他们。
代码文件说明
每一个类都由头文件和源文件组成。
calch.h文件
#pragma once
#include <iostream>
#include <string>
#include <sstream>
#include <fstream>
#include <vector>
#include <stack>
#include <queue>
#include <map>
#include <set>
#include <cmath>
#include "calc.h"
#include "datahandler.h"
#include "eval.h"
#include "lexer.h"
#include "sym.h"
#include "filenotfound.h"
#include "illegalname.h"
#include "evalerror.h"
我把所有的头文件在这个文件中一次引用,之后后面的代码每一个头文件都要引用这个头文件。
主函数文件
#include "calch.h"
using namespace std;
using namespace calculator;
int main(int argc, char* argv[])
{
calc mycalc(argc, argv);
system("pause");
return 0;
}
calc
头文件
#pragma once
#include "calch.h"
namespace calculator
{
class calc
{
public:
calc(int argc, char * argv[]);
};
}
源文件
#include "calc.h"
using namespace calculator;
using namespace std;
datahandler dh;
sym symbol_table;
calc::calc(int argc, char* argv[])
{
try
{
dh.init(argc, argv);
}
catch (filenotfound e)
{
cout << e.what() << endl;
}
vector<string> lines = dh.getLines();
int pos = 1;
for (vector<string>::iterator it = lines.begin(); it < lines.end(); ++it)
{
laxer mylaxer(*it, pos);
try
{
mylaxer.getcalc();
}
catch (evalerror e)
{
cout << e.what() << endl;
}
catch (illegalname e)
{
cout << e.what() << endl;
}
++pos;
}
}
datahandler
头文件
#pragma once
#include "calch.h"
namespace calculator
{
class datahandler
{
public:
~datahandler();
void init(int argc, char * argv[]);
void handlekeybordinput();
void handlefileinput();
void handlechar(char c);
void output2keybord();
std::vector<std::string> getLines();
private:
std::vector<std::string> lines;
std::ifstream infile;
std::string tempstr;
};
}
源文件
#include "datahandler.h"
using namespace std;
using namespace calculator;
datahandler::~datahandler()
{
std::vector<std::string>().swap(lines);
tempstr.clear();
infile.close();
}
void datahandler::init(int argc, char * argv[])
{
if (argc == 1)
handlekeybordinput();
else
{
string filename;
for (int i = 1; i < argc; i++)
{
filename = argv[i];
infile.open(filename);
if (!infile.is_open())
throw filenotfound(filename);
else
handlefileinput();
}
}
}
void datahandler::handlekeybordinput()
{
cin >> noskipws;
char c;
while (cin >> c)
handlechar(c);
}
void datahandler::handlefileinput()
{
char c;
infile >> noskipws;
int pos = 0;
while (!infile.eof())
{
infile >> c;
handlechar(c);
}
}
void datahandler::handlechar(char c)
{
switch (c)
{
case ' ':
break;
case ';':
if (tempstr.empty())
break;
tempstr.append(1, c);
lines.push_back(this->tempstr);
tempstr.clear();
break;
case '\n':
if (tempstr.empty())
break;
lines.push_back(this->tempstr);
tempstr.clear();
break;
default:
tempstr.append(1, c);
break;
}
}
void datahandler::output2keybord()
{
int pos = 1;
for (vector<string>::iterator it = lines.begin(); it < lines.end(); ++it)
{
cout << pos << "\t" << (*it) << endl;
++pos;
}
}
vector<std::string> datahandler::getLines()
{
return lines;
}
eval
头文件
#pragma once
#include "calch.h"
namespace calculator
{
class eval
{
typedef struct Reverse_Polish_Expression
{
Reverse_Polish_Expression(double num)
{
data.num = num;
this->symbol = true;
}
Reverse_Polish_Expression(char ch)
{
data.op = ch;
this->symbol = false;
}
union data
{
double num = 0.0;
char op;
}data;
bool symbol;
}RPE;
public:
eval();
~eval();
double calc(std::string line);
double itercalc(std::string::iterator & begin, std::string::iterator & end);
void parenthesis_matching(std::string str);
void ophandler(char op, std::stack<char>& opStack, std::stack<RPE>& num);
bool isNumber(char ch);
bool ispartofNumber(char ch);
bool isOperator(char ch);
bool isLetter(char ch);
void symbolhandler(std::string::iterator & it, std::stack<RPE> & num);
void tranNum(std::string::iterator & it, std::stack<RPE>& num);
void residueOphandler(std::stack<char>& opStack, std::stack<RPE>& number);
void reverseStack(std::stack<RPE>& number);
double RPEhandler(std::stack<RPE>& number);
private:
std::string line;
std::map<char, int> priority;
std::set<char> op;
};
}
源文件
#include "eval.h"
using namespace std;
using namespace calculator;
extern sym symbol_table;
eval::eval()
{
priority['+'] = 1;
priority['-'] = 1;
priority['*'] = 2;
priority['/'] = 2;
priority['^'] = 3;
op.insert('+');
op.insert('-');
op.insert('*');
op.insert('/');
op.insert('^');
}
eval::~eval()
{
line.clear();
priority.clear();
op.clear();
}
double eval::calc(string line)
{
if (*(line.end() - 1) == ';')
this->line = line.substr(0, line.length() - 1);
else
this->line = line;
parenthesis_matching(this->line);
string::iterator itbegin = this->line.begin();
string::iterator itend = this->line.end();
return itercalc(itbegin, itend);
}
double eval::itercalc(string::iterator &begin, string::iterator &end)
{
stack<RPE> num;
stack<char> opStack;
bool lasttoken = true;
for (; begin < end; ++begin)
{
if (*begin == '(')
{
int n = 1;
++begin;
string::iterator nextbegin = begin;
for (; begin < end; ++begin)
if (*begin == ')')
{
--n;
if (n == 0)
{
num.push(RPE(itercalc(nextbegin, begin)));
break;
}
}
else if (*begin == '(')
{
++n;
}
lasttoken = false;
if (begin >= end)
break;
}
if (lasttoken && ispartofNumber(*begin))
{
tranNum(begin, num);
lasttoken = false;
}
else
{
if (isOperator(*begin))
{
if (lasttoken)
throw "Operator error.";
ophandler(*begin, opStack, num);
lasttoken = true;
}
else if (isLetter(*begin))
{
symbolhandler(begin, num);
lasttoken = false;
}
else if (*begin == ')')
continue;
else
throw "Unknown operation.";
}
}
if (lasttoken)
throw "Operator error.";
residueOphandler(opStack, num);
reverseStack(num);
return RPEhandler(num);
}
void eval::parenthesis_matching(string str)
{
int n = 0;
for (string::iterator it = str.begin(); it < str.end(); ++it)
{
if (*it == '(')
++n;
if (*it == ')')
{
if (n > 0)
--n;
else
throw "Parenthesis unmatching.";
}
}
if (n != 0)
throw "Parenthesis unmatching.";
}
void eval::ophandler(char op, stack<char> &opStack, stack<RPE> &num)
{
while (!opStack.empty() && priority[op] <= priority[opStack.top()])
{
num.push(RPE(opStack.top()));
opStack.pop();
}
opStack.push(op);
}
void eval::symbolhandler(string::iterator &it, stack<RPE> &num)
{
string tempstr;
tempstr.append(1, *it);
for (++it; it < line.end(); ++it)
if (isLetter(*it) || isNumber(*it))
tempstr.append(1, *it);
else
break;
try
{
num.push(RPE(symbol_table.find(tempstr)));
}
catch (const char* str)
{
throw str;
}
--it;
}
void eval::tranNum(string::iterator &it, stack<RPE> &num)
{
string tempstr;
double n;
if (ispartofNumber(*it))
tempstr.append(1, *it);
++it;
for (; it < line.end(); ++it)
if (isNumber(*it) || *it == '.')
tempstr.append(1, *it);
else
break;
if (!isNumber(tempstr[0]) && tempstr[0] != '-')
throw "Operator error.";
stringstream ss(tempstr);
ss >> n;
num.push(RPE(n));
--it;
}
void eval::residueOphandler(stack<char> &opStack, stack<RPE> &number)
{
while (!opStack.empty())
{
number.push(RPE(opStack.top()));
opStack.pop();
}
}
void eval::reverseStack(stack<RPE> &number)
{
queue<RPE> queue;
while (!number.empty())
{
queue.push(number.top());
number.pop();
}
while (!queue.empty())
{
number.push(queue.front());
queue.pop();
}
}
double eval::RPEhandler(stack<RPE> &number)
{
stack<double> result;
char tempOp;
double tempnum1, tempnum2;
while (!number.empty())
{
if (number.top().symbol)
{
result.push(number.top().data.num);
number.pop();
}
else
{
tempOp = number.top().data.op;
number.pop();
if (result.size() < 2)
throw "Operator error.";
tempnum2 = result.top();
result.pop();
tempnum1 = result.top();
result.pop();
switch (tempOp)
{
case '+':
result.push(tempnum1 + tempnum2);
break;
case '-':
result.push(tempnum1 - tempnum2);
break;
case '*':
result.push(tempnum1 * tempnum2);
break;
case '/':
result.push(tempnum1 / tempnum2);
break;
case '^':
result.push(pow(tempnum1, tempnum2));
break;
default:
throw "Operator error.";
}
}
}
if (!number.empty())
throw "Operator error.";
if (isinf(result.top()) || isnan(result.top()))
throw "Divide 0 is not allow.";
if (result.size() != 1)
throw "Number error.";
return result.top();
}
bool eval::isNumber(char ch)
{
return ch >= '0' && ch <= '9';
}
bool eval::ispartofNumber(char ch)
{
return isNumber(ch) || ch == '.' || ch == '-' || ch == '+';
}
bool eval::isOperator(char ch)
{
return op.count(ch) != 0;
}
bool eval::isLetter(char ch)
{
return ((ch >= 'a'&&ch <= 'z') || (ch >= 'A'&&ch <= 'Z'));
}
evalerror
头文件
#pragma once
#include "calch.h"
namespace calculator
{
class evalerror
{
public:
evalerror(std::string except, int Line);
~evalerror();
std::string what();
private:
std::string except;
};
}
源文件
#include "evalerror.h"
using namespace std;
using namespace calculator;
evalerror::evalerror(string except, int Line)
{
this->except = "EVALERROR ERROR: " + except + " Line " + to_string(Line);
}
evalerror::~evalerror()
{
except.clear();
}
string evalerror::what()
{
return except;
}
filenotfound
头文件
#pragma once
#include "calch.h"
namespace calculator
{
class filenotfound
{
public:
filenotfound(std::string except);
~filenotfound();
std::string what();
private:
std::string except;
};
}
源文件
#include "filenotfound.h"
using namespace calculator;
using namespace std;
filenotfound::filenotfound(string except)
{
this->except = "FILENOTFOUND ERROR: " + except;
}
filenotfound::~filenotfound()
{
except.clear();
}
string filenotfound::what()
{
return except;
}
illegalname
头文件
namespace calculator
{
class illegalname
{
public:
illegalname(std::string except, int Line);
~illegalname();
std::string what();
private:
std::string except;
};
}
源文件
#include "illegalname.h"
using namespace std;
using namespace calculator;
illegalname::illegalname(string except, int Line)
{
this->except = "ILLEGALNAME ERROR: " + except + " Line " + to_string(Line);
}
illegalname::~illegalname()
{
except.clear();
}
string illegalname::what()
{
return except;
}
lexer
头文件
namespace calculator
{
class lexer
{
enum ChooseSymbol
{
num, symbol, token
};
public:
lexer(std::string line, int Lnum);
~lexer();
void getcalc();
void symbolhandle(std::string str);
bool isLetter(const char ch);
bool isNumber(const char ch);
private:
int Lnum;
double ans;
std::vector<std::string> s;
std::string line;
enum ChooseSymbol cs;
};
}
源文件
#include "lexer.h"
using namespace calculator;
using namespace std;
extern sym symbol_table;
eval myeval;
lexer::lexer(string line, int Lnum)
{
this->line = line;
this->Lnum = Lnum;
}
lexer::~lexer()
{
s.clear();
line.clear();
}
void lexer::getcalc()
{
int equalpos = line.find("=");
bool flag = *(line.end() - 1) == ';';
if (equalpos > -1)
{
try
{
ans = myeval.calc(line.substr(equalpos + 1));
}
catch (const char* str)
{
throw evalerror(str, Lnum);
}
try
{
symbolhandle(line.substr(0, equalpos));
}
catch (const char* str)
{
throw illegalname(str, Lnum);
}
if (!flag)
cout << line.substr(0, equalpos) << " = " << ans << endl;
}
else
{
try
{
if (flag)
ans = myeval.calc(line.substr(0, line.length() - 1));
else
ans = myeval.calc(line);
}
catch (const char* str)
{
throw evalerror(str, Lnum);
}
symbol_table.add("ans", ans);
if (!flag)
cout << "ans = " << ans << endl;
}
}
void lexer::symbolhandle(string str)
{
string tempsym;
string::iterator it = str.begin();
if (!isLetter(*it))
throw "Not conform to the standard.";
for (; it < str.end(); ++it)
if (!(isLetter(*it) || isNumber(*it)))
throw "Not conform to the standard.";
else
tempsym.append(1, *it);
symbol_table.add(tempsym, ans);
}
bool lexer::isLetter(const char ch)
{
return (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z');
}
bool lexer::isNumber(const char ch)
{
return (ch >= '0' && ch <= '9');
}
sym
头文件
#pragma once
#include "calch.h"
namespace calculator
{
class sym
{
public:
sym();
~sym();
void add(std::string symbol, double num);
double find(std::string symbol);
private:
std::map<std::string, double>table;
};
}
源文件
#include "sym.h"
using namespace calculator;
sym::sym()
{
table["e"] = 2.71828182845904523536;
table["pi"] = 3.14159265358979323846;
}
sym::~sym()
{
table.clear();
}
void sym::add(std::string symbol, double num)
{
table[symbol] = num;
}
double sym::find(std::string symbol)
{
if (table.count(symbol) == 0)
throw "No such symbol.";
return table[symbol];
}
代码说明
数据结构:eval.h中定义了逆波兰表达式所需的节点,其中包含一个联合体data与symbol,data为了表示数据,symbol用于区分数字与符号。
typedef struct Reverse_Polish_Expression
{
Reverse_Polish_Expression(double num)
{
data.num = num;
this->symbol = true;
}
Reverse_Polish_Expression(char ch)
{
data.op = ch;
this->symbol = false;
}
union data
{
double num = 0.0;
char op;
}data;
bool symbol;
}RPE;
算法1 int main()
作 用:主控函数,也实现对题目所需其他内容的测试。
参 数:int argc, char* argv[]:命令行参数
返回值:总是返回0。
计算过程:
创建calc类,名为mycalc。
类1 calc类
算法1.1 构造器calc::calc()
作 用:构造计算器,处理各类跑出的异常。
参 数:int argc, char* argv[]:命令行参数
返回值:无
计算过程:
(1) try/catch语句,调用数据处理类,该类调用算法2.1,处理filenotfound错误。
(2) 调用数据处理类,该类调用算法2.2,返回值赋值给lines。
(3) 循环遍历lines,读取lines中每一元素。
(4) try/catch语句,将lines中元素给语法分析类,该类调用算法3.2,处理evalerror与illegalname错误。
类2 datahandler类
算法2.1 void datahandler::init(int argc, char * argv[])
作 用:初始化状态,判断数据来源。
参 数:int argc, char * argv[]:命令行参数
返回值:无
计算过程:
(1) 判断argc为1,调用算法2.3。
(2) 判断argc不为1,循环遍历argv,将其当做文件名处理,如果文件找不到,抛出异常filenotfound;否则调用算法2.4。
算法2.2 vectorstd::string datahandler::getLines()
作 用:返回私有成员lines
参 数:无
返回值:lines
计算过程:
返回私有成员lines。
算法2.3 void datahandler::handlekeybordinput()
作 用:处理键盘输入
参 数:无
返回值:无
计算过程:
(1) 将cin模式调为不跳过结束符。
(2) 每次读入一个字符,并调用算法2.5。
算法2.4 void datahandler::handlefileinput()
作 用:处理文件输入
参 数:无
返回值:无
计算过程:
(1) 将文件内容按字符输入,不调过结束符。
(2) 每次读入一个字符,并调用算法2.5。
算法2.5 void datahandler::handlechar(char c)
作 用:处理一个字符
参 数:char c:传入字符
返回值:无
计算过程:
(1) 如果c是空格就退出。
(2) 如果c是‘;’,如果tempstr为空,则退出;否则,就将其接在tempstr后面,之后在lines中加入tempstr。
(3) 如果c是‘\n’,如果tempstr为空,则退出;否则,在lines中加入tempstr。
(4) 如果c都不满足上述条件,就将其接在tempstr后面。
类3 laxer类
算法3.1 构造器laxer::laxer(string line, int Lnum)
作 用:为成员变量赋值
参 数:
string line:一行
int Lnum:行号
返回值:无
计算过程:
为成员变量赋值
算法3.2 void laxer::getcalc()
作 用:进行语法分析
参 数:无
返回值:无
计算过程:
(1) 找到成员变量line中的‘=’,以此作为分隔,前面为新增符号,后面为表达式。
(2) 判断语句结尾是否有‘;’,有则为真,将结果赋值给flag。
(3) 判断‘=’位置,如果有,则调用算法4.2计算表达式的值并赋值给ans,并处理异常,之后调用算法3.3,处理赋值;如果没有,则调用算法4.2计算表达式的值并赋值给ans,并处理异常,之后将值放入符号表中ans项。
(4) 判断flag,如果为真,输出结果,符号为自定义符号,如果为假,则输出符号ans的值。
算法3.3 void laxer::symbolhandle(string str)
作 用:处理符号,检查是否为不符合规定的符号。
参 数:string str:符号
返回值:无
计算过程:
(1) 先检查符号的第一位,不为字母,则抛出异常。
(2) 后面如果出现不为字母或数字的字符,则抛出异常。
(3) 如果符合标准,则将该符号加入符号表,并将赋值为ans的值。
算法3.4 bool laxer::isLetter(const char ch)
作 用:判断是否为字母
参 数:const char ch:传入字符
返回值:(ch >= ‘a’ && ch <= ‘z’) || (ch >= ‘A’ && ch <= ‘Z’)
计算过程:
判断传入字符是否为字母。
算法3.5 bool laxer::isNumber(const char ch)
作 用:判断是否为数字
参 数:const char ch:传入字符
返回值:(ch >= ‘0’ && ch <= ‘9’)
计算过程:
判断传入字符是否为数字。
类4 eval类
算法4.1 构造器eval::eval()
作 用:初始化成员变量
参 数:无
返回值:无
计算过程:
初始化成员变量,为各个运算符分配优先级。
算法4.2 double eval::calc(string line)
作 用:计算表达式值,将表达式看做由很多括号括起来的子式,之后迭代计算。
参 数:string line:表达式
返回值:表达式的值
计算过程:
(1) 判断表达式后是否有‘;’,有就去掉。
(2) 调用算法4.3,检查括号是否匹配。
(3) 调用算法4.4。
算法4.3 void eval::parenthesis_matching(string str)
作 用:判断括号是否匹配
参 数:string str:表达式
返回值:无
计算过程:
(1) 使用一个整数n。
(2) 每次遇到‘(’,n就累加1,每次遇到‘)’,判断是否小于0,是就抛出异常,不是n就减1。
(3) 结束循环后,检查n是否为0,不是就抛出异常。
算法4.4 double eval::itercalc(string::iterator &begin, string::iterator &end)
作 用:计算一个算术子式,即计算一个无括号算式。
参 数:string::iterator &begin:算术子式的开头
string::iterator &end:算术子式的结尾
返回值:算术子式的值
计算过程:
使用逆波兰表达式计算算术子式。
(1) 使用栈,第一个栈为运算符栈,其中使用结构为结构体RPE,第二个栈为操作符栈。
(2) 扫描整个字符串,读入为数字或者符号,则压入运算符栈,读入为操作符,则按照逆波兰表达式的规则压入运算符栈或者操作符栈,这里运算符栈结构为结构体RPE,使用symbol来区分是操作符还是数字。
(3) 在扫描过程中,发现‘(’,则把这个括号当做起始位置,向后找到与之对应的‘)’,之后将其中的式子当做子式,调用算法4.4,进行下一轮循环,将迭代结果压入运算符栈中。
(4) 最外层的迭代返回整个式子的结果。
算法4.5 void eval::ophandler(char op, stack &opStack, stack &num)
作 用:处理操作符
参 数:
char op:操作符
stack &opStack:操作符栈
stack &num:运算符栈
返回值:无
计算过程:
解决逆波兰表达式中运算符优先级问题。
算法4.6 void eval::symbolhandler(string::iterator &it, stack &num)
作 用:处理符号
参 数:
string::iterator &it:符号在字符串中出现的开始位置
stack &num:运算符栈
返回值:无
计算过程:
检测符号,将符号转换为数字并压入运算符栈,没有该运算符则抛出异常。
算法4.7 void eval::tranNum(string::iterator &it, stack &num)
作 用:处理数字
参 数:
string::iterator &it:数字在字符串中出现位置
stack &num:运算符栈
返回值:无
计算过程:
检测数字,将字符串转换为数字并压入运算符栈。
算法4.8 void eval::residueOphandler(stack &opStack, stack &number)
作 用:将操作符栈剩余的操作符压入运算符栈
参 数:
stack &opStack:操作符栈
stack &number:运算符栈
返回值:无
计算过程:
将操作符栈剩余的操作符压入运算符栈
算法4.9 void eval::reverseStack(stack &number)
作 用:翻转运算符栈
参 数:
stack &number:运算符栈
返回值:无
计算过程:
用队列将运算符栈翻转
算法4.10 double eval::RPEhandler(stack &number)
作 用:处理逆波兰表达式
参 数:
stack &number:运算符栈
返回值:逆波兰表达式计算结果
计算过程:
(1) 建立一个结果栈,从运算符栈中弹出项,如果为数字,则直接压入结果栈,如果是符号,则从结果栈中弹出两个数字,进行运算后压入结果栈中。
(2) 判断操作数栈是否为空,不为空抛出异常。
(3) 判断结果栈栈顶是否为inf,是则抛出异常。
(4) 判断结果栈大小是否为1,不是则抛出异常。
(5) 返回结果栈顶。
算法4.11 bool eval::isNumber(char ch)
作 用:判断是否为数字,
参 数:
char ch:输入字符,
返回值:true则为是,false则为否,
计算过程:
判断是否为数字,
算法4.12 bool eval::ispartofNumber(char ch)
作 用:判断是否为一个数字的一部分,
参 数:
char ch:输入字符,
返回值:true则为是,false则为否,
计算过程:
判断是否为一个数字的一部分,
算法4.13 bool eval::isOperator(char ch)
作 用:判断是否为操作符,
参 数:
char ch:输入字符,
返回值:true则为是,false则为否,
计算过程:
判断是否为操作符,
算法4.14 bool eval::isLetter(char ch)
作 用:判断是否为字母。
参 数:
char ch:输入字符。
返回值:true则为是,false则为否。
计算过程:
判断是否为字母。
类5 sym类
算法5.1 构造器sym::sym()
作 用:初始化符号表。
参 数:无
返回值:无
计算过程:
初始化符号表。
算法5.2 void sym::add(std::string symbol, double num)
作 用:向符号表中添加元素。
参 数:
std::string symbol:符号。
double num:符号的值。
返回值:无
计算过程:
在符号表中插入键为symbol,值为num的项。
算法5.3 double sym::find(std::string symbol)
作 用:在符号表里查找一个元素。
参 数:
std::string symbol:需要查找的元素的键值。
返回值:键的值
计算过程:
先查找是否有该元素,如果没有就抛出异常,有就返回键的值。
类6 evalerror类
算法6.1 构造器evalerror::evalerror(string except, int Line)
作 用:初始化类
参 数:
string except:抛出异常的内容。
int Line:行号。
返回值:无
计算过程:
初始化成员
算法6.2 string evalerror::what()
作 用:返回错误内容。
参 数:无
返回值:错误内容
计算过程:
返回错误内容。
类7 filenotfound类
算法7.1 构造器filenotfound::filenotfound(string except)
作 用:初始化类
参 数:
string except:抛出异常的内容。
int Line:行号。
返回值:无
计算过程:
初始化成员
算法7.2 string filenotfound::what()
作 用:返回错误内容。
参 数:无
返回值:错误内容
计算过程:
返回错误内容。
类8 illegalname类
算法8.1 构造器illegalname::illegalname(string except, int Line)
作 用:初始化类
参 数:
string except:抛出异常的内容。
int Line:行号。
返回值:无
计算过程:
初始化成员
算法8.2 string illegalname::what()
作 用:返回错误内容。
参 数:无
返回值:错误内容
计算过程:
返回错误内容。
测试结果
输入1
b=7
c=21
a=3
a^2
A^2
9abc=5+6;
9/0
1/0-1/0
a*(2+3)
^1+1
1**2
1&+2
1(2+3*)
^Z
输出1
b = 7
c = 21
a = 3
ans = 9
EVALERROR ERROR: No such symbol. Line 5
ILLEGALNAME ERROR: Not conform to the standard. Line 6
EVALERROR ERROR: Divide 0 is not allow. Line 7
EVALERROR ERROR: Divide 0 is not allow. Line 8
ans = 15
EVALERROR ERROR: Operator error. Line 10
EVALERROR ERROR: Operator error. Line 11
EVALERROR ERROR: Unknown operation. Line 12
EVALERROR ERROR: Operator error. Line 13
输入2
a=4;b=3;c=a+b;d=haha
a
b
c
^Z
输出2
EVALERROR ERROR: No such symbol. Line 4
ans = 4
ans = 3
ans = 7