表达式解析计算器源码(完整实现)

大一下时做的大数非图形界面计算器,自己在这个过程中收获较大,希望和大家分享下分三个(面向过程浮点版,面向对象浮点版和面向对象大数版)版本::完整实现如下:Version1:面向过程浮点版(从文件读入并输出)divexcept.h(存储各种错误信息)#include #include using namespace std;string return_except(
摘要由CSDN通过智能技术生成

大一下时做的大数非图形界面计算器,自己在这个过程中收获较大,希望和大家分享下微笑

分三个(面向过程浮点版,面向对象浮点版和面向对象大数版)版本::

完整实现如下:

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;
}


pre_check.h(解析表达式前,对表达式进行预判)

#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;
}


main.cpp

#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
  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值