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

这是一篇关于大一下学期完成的非图形界面大数计算器的分享,包含面向过程浮点版、面向对象浮点版及面向对象大数版的完整源码实现。文章详细介绍了不同版本的实现细节,如divexcept.h、programm.h等关键文件在各版本中的作用。
摘要由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
表达式计算说明 很久就想编一个这样的计算器,只可惜一直没什么思路,最近突然灵感来了,所以就写下 这个程序。现在还在测试阶段,所以功能不是很完善。 程序功能:基本的表达式运算,可以自定义函数跟常量,分别保存在 “常数.txt” 和 “函数.txt”,方便自己添加。双击相应的函数名或常数名就可以将函数或常量添加到表达式中。 计算过程只能当表达式只有一行时有效。 实例1:计算sqr(19+tan(98)*tan(91)-sin(122)*(5*5-(19-11)))/2 计算过程sqr(19+tan(98)*tan(91)-sin(122)*(5*5-(19-11)))/2 =sqr(19+-7.11536972238419*tan(91)-sin(122)*(5*5-(19-11)))/2 =sqr(19+-7.11536972238419*-57.2899616307588-sin(122)*(5*5-(19-11)))/2 =sqr(19+-7.11536972238419*-57.2899616307588-.848048096156426*(5*5-(19-11)))/2 =sqr(19+-7.11536972238419*-57.2899616307588-.848048096156426*(5*5-8))/2 =sqr(19+-7.11536972238419*-57.2899616307588-.848048096156426*17)/2 =20.3032618253667/2 =10.1516309126834 实例2:计算 a=34 b=55 c=a+1 圆的面积(c) a*b c=a+b 圆的面积(c) 以下是计算结果: 圆的面积(c)=3848.4510006475 a*b=1870 圆的面积(c)=24884.5554090847 内置函数: !(x) - x 的阶乘 lg(x),log(x) 以10为底的对数 ln(x) 以 e为底x的对数 pow(x,y) x的y方次幂 prime(x) 判定x是否是素数,如果是直接将s2返回,否则将其各因子用连乘返回 sqr(x),sqrt(x) - x 的二次方根 arcsin(x) - x 的反正弦 arccos(x) - x 的反余弦 arcsec(x) - x 的反正割 arccsc(x) - x 的反余割 atn(x),arctg(x) - x 的反正切 arcctg(x) - x 的反余切 sin(x) - x 的正弦 cos(x) - x 的余弦 sec(x) - x 的正割 csc(x) - x 的余割 tg(x),tan(x) - x 的正切 ctg(x) - x 的余切 harcsin(x) - x 的反双曲正弦 harccos(x) - x 的反双曲余弦 harcsec(x) - x 的反双曲正割 harccsc(x) - x 的反双曲余割 harctg(x),harctan(x) - x 的反双曲正切 harcctg(x) - x 的反双曲余切 hsin(x) - x 的双曲正弦 hcos(x) - x 的双曲余弦 hsec(x) - x 的双曲正割 hcsc(x) - x 的双曲余割 htg(x),htan(x) - x 的双曲正切 hctg(x) - x 的双曲余切 有什么意见或建议可以跟我联系Email: ldm.menglv@gmail.com
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值