大一下时做的大数非图形界面计算器,自己在这个过程中收获较大,希望和大家分享下
分三个(面向过程浮点版,面向对象浮点版和面向对象大数版)版本::
完整实现如下:
Version1:
面向过程浮点版
(从文件读入并输出)
divexcept.h(存储各种错误信息)
#include <iostream>
#include <string>
using namespace std;
string return_except(int sign)
{
string errortype;
if(sign==1)errortype="运算符错位/(Primary Expected)";
else if(sign==2)errortype="多余运算符/(Unexpected Token)";
else if(sign==3)errortype="出现非法字符/(Invalid Characters)";
else if(sign==4)errortype="右括号多于左括号/(Too Many Right Parentheses)";
else if(sign==5)errortype="变量名命名错误/(Unexpected Token)";
else if(sign==6)errortype="除零错误/(Divide By Zero)";
else if(sign==7)errortype="变量名过长/(Too Long Name Of Variables)";
else if(sign==8)errortype="未定义变量/(Undefined Variables)";
else if(sign==9)errortype="乘号缺失/(Multiple Sign Expected)";
else if(sign==10)errortype="左右括号不匹配/(Parentheses Matching failed)";
return errortype;
}
#include <iostream>
#include <string>
#include <map>
using namespace std;
string validchars="0123456789*/+-=()_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ ";
string tmp="";
int precheck(string s)
{
int count=0;
tmp="";
int sign=0;//因错误类型繁多,故设定sign值为0时,判断无错误。
int leftp=0,rightp=0;//分别表示左右括号数。
s=' '+s;//便于后续过程处理
int len=s.length();
//报错类型1,运算符错位,(Primary Expected),括号内的独立表达式会在下述循环中处理 。
if(s[1]=='*'||s[1]=='/'||s[1]=='=')
{
sign=1;
return sign;
}
//报错类型2,多余运算符,(Unexpected Token),式子中的将在循环中处理。
if(s[len-1]=='+'||s[len-1]=='*'||s[len-1]=='/'||s[len-1]=='-'||s[len-1]=='=')
{
sign=2;
return sign;
}
for(int i=1;i<s.length();i++)
{
//报错类型3,合法字符中找不到该字符,(Bad Token)。
if(validchars.find(s[i])==-1)
{
sign=3;
return sign;
}
if(s[i]=='(')leftp++;
else if(s[i]==')')rightp++;
//报错类型4,右括号多于左括号,(Too Many Right Parentheses)。
if(rightp>leftp)
{
sign=4;
return sign;
}
//报错类型5,变量名命名错误,数字后不能再跟字母,(Unexpected Token)。
if(isalpha(s[i])&&isdigit(s[i-1]))
{
sign=5;
return sign;
}
//报错类型6,除零错误,此处只能初判直接除以0的错误,运算中将继续检查(Divide By Zero)。
if(s[i-1]=='/'&&s[i]=='0')
{
sign=6;
return sign;
}
//报错类型1,运算符错位,(Priamry Expected)。
if((s[i-1]=='+'||s[i-1]=='-'||s[i-1]=='*'||s[i-1]=='/'||s[i-1]=='=')
&&(s[i]=='+'||s[i]=='-'||s[i]=='*'||s[i]=='/'||s[i]=='='))
{
sign=1;
return sign;
}
if((s[i-1]=='(')&&(s[i]=='='||s[i]=='*'||s[i]=='/'))
{
sign=1;
return sign;
}
//报错类型2,多余运算符,(Unexpected Token)。
if((s[i]==')')&&(s[i-1]=='='||s[i-1]=='+'||s[i-1]=='-'||s[i-1]=='*'||s[i-1]=='/'))
{
sign=2;
return sign;
}
//报错类型9,不能省略乘号,(Multiple Sign Can't Be Ignored)。
if((s[i]=='('&&isalnum(s[i-1]))||(s[i-1]==')'&&isalnum(s[i])))
{
sign=9;
return sign;
}
//统计=号个数
if(s[i]=='=')count++;
}
//左右括号不匹配,报错类型10(Parentheses Matching failed)。
if(leftp!=rightp)
{
sign=10;
return sign;
}
if(count)//代表是赋值表达式,处理全是数字的变量错误
{
int count1=0;
s[0]='='; //将表达式变成 =123=234从而方便判断
for(int i=1;i<s.length();i++)
{
if(s[i]=='=')count1++;
if(s[i]<='9'&&s[i]>='0'&&s[i-1]=='='&&count1!=count)
{
sign=5;
return sign;
}
}
}
return sign;
}
#include <fstream>
#include <iostream>
#include <map>
#include <string>
#include <iomanip>
#include "divexcept.h"
#include "pre_check.h"
using namespace std;
double term(),factor(),expr(),number();
void assignment();
string var(),original,store;//original为预处理后的表达式
int pos;//pos计算过程中的光标位置
map <string,double> vars;//储存变量
int presign=0;//预判过程中的错误标记,0默认无错误
int tmpsign=0;//文法解析过程中的错误标记,0默认无错误
ifstream in("in.txt");
ofstream out("out.txt");
void assignment()
{
//如若已出错,直接返回
if(tmpsign) return;
string varName[20]; //最多支持20个变量的连等
double val;
int n=0;
while(1)
{
int var_begin=pos;
if(isalpha(original[pos])||original[pos]=='_') //表示读入变量名
{
string temp=var();
if(temp!="") varName[n++]=temp;//""代表出现过长变量名,已处理
else break;
if(pos!=original.length()-1&&original[pos]=='=') ++pos;
else
{
pos=var_begin; //变量名后面不再是等号,把变量名回吐
n--;
break;
}
}
else break;//已读不到变量名
}
val=expr();
if(!tmpsign)//代表没有出现任何异常
{
for(int i=0;i<n;i++) vars[varName[i]]=val;//把变量及值放入map
out<<"Assignment Succeed!/赋值成功\n";
for(int i=0;i<n;i++)out<<varName[i]<<": "<<vars[varName[i]]<<" ";
out<<endl;
return ;
}
else return;
}
double expr(void)
{
//如若已出错,直接返回
if(tmpsign) return 0;
double result_expr;
//若出现其它运算符,已在预判中报错
if(original[pos]=='-'){ ++pos;result_expr=-term();}
else result_expr=term();
while(1)
{
if(original[pos]=='+')
{
++pos;
result_expr+=term();
}
else if(original[pos]=='-')
{
++pos;
result_expr-=term