我能不能从一个字符串读取成一个一个算术表达式啊

yaoha2003 2003-10-09 10:56:17
例如“ax+by+c+125",还是要一个一个来读?
...全文
37 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
bluebohe 2003-10-10
  • 打赏
  • 举报
回复
// Expression.h: interface for the CExpression class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_EXPRESSION_H__2578E33F_FF86_4384_A7CE_A401BAC5A010__INCLUDED_)
#define AFX_EXPRESSION_H__2578E33F_FF86_4384_A7CE_A401BAC5A010__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include <list>
#include <string>

using namespace std;
#define DELIMITER 1 //分隔符
#define VARIABLE 2 //变量
#define NUMBER 3 //数值
#define FUNCTION 4 //函数
#define PI 3.1415926535898
class CVar //用来存放变量及变量值的表结构
{
public:
char m_cFlag; // 等于0为临时变量,否则等于1
string m_strName; //变量名 如变量a
string m_strSlave; //约束表达式,如a=b+2
double m_dValue; //变量值 如10,表a=10
public:
CVar();
virtual ~CVar();
void InitVar();

};
class CVarList
{
public:
list<CVar*> m_VarList;
CVarList();
virtual ~CVarList();

bool AddVar(CVar* pVar);

};
class CExpression
{
public:
double m_dResult;
char* m_strExp;
CVarList m_VarList;
bool m_bDegUnit; // 缺省采用角度单位
protected:
int m_iErrFlag; //标记表达式计算是否出错0:正常,1:表达式空2:非法变量或函数3:括号不匹配
int m_iFunFlag; //标记当前正在进行函数参数计算.
int m_iMatchFlag; //标记括号是否匹配

char m_cTokenType; //标记符号的类型,如分格符,变量等
char m_strToken[80];

public:
void Message(const char * strMsg);
CExpression();
virtual ~CExpression();

bool CalExp();
bool UpdateSlaveVar();

protected:
bool GetToken();
void Error();
bool IsDelim(char c);
bool IsFunc(const char *fname);
bool IsWhite(char c);
bool IsInStr(char ch,char *s);
bool Level1(double *result);
bool Level2(double *result);
bool Level3(double *result);
bool Level4(double *result);
bool Level5(double *result);
bool Level6(double *result);
bool Level7(double *result);
bool GetFunIndex(const char *name,int *index);
void PutBack();
void Unary(char o,double *r);
bool Arith(char o, double *r, double *h);
bool Primitive(double *result);
bool GetVarValue( const char * n, double * result );
bool GetVarIndex( const char * name, int * index );
};




#endif // !defined(AFX_EXPRESSION_H__2578E33F_FF86_4384_A7CE_A401BAC5A010__INCLUDED_)


bluebohe 2003-10-10
  • 打赏
  • 举报
回复

//括号及函数处理
bool CExpression::Level7(double *result)
{
//若取得的单元为括号
if((*m_strToken == '(') && (m_cTokenType == DELIMITER))
{
//跳过括号,取得括号内第一单元
if(GetToken() == true)
{
//递归调用,完成括号内的表达式运算
if(Level2(result) != true)
return false;

//当前符号应为')',否则出错
if(*m_strToken != ')')
{
m_iErrFlag = 3;
return false;
}

//跳过符号')'
if(GetToken() != true)
{
m_iErrFlag = 3;
return false;
}
}
else
{
m_iErrFlag = 2; //m_iErrFlag = 1;
return false;
}
}
//否则必为变量或常数
else
{
//取得变量数值或常数
if(Primitive(result) != true)
{
m_iErrFlag = 2;
return false;
}
else
return true;
}
return true;
}
bool CExpression::GetFunIndex(const char *name,int *index)
{
int i;
for(i=0 ;i< funTableLen ;i++)
{
if(strcmp(funNameTable[i],name) == 0)
{
*index = i;
return true;
}
}
return false;
}
//回读表达式一token,在level1中调用.
void CExpression::PutBack()
{
char *t;

//将token回送到表达式
t = m_strToken;
for( ; *t; t ++ )
m_strExp--;
}
//取反
void CExpression::Unary(char o,double *r)
{
if(o == '-')
*r = -(*r);
}

bool CExpression::Arith(char o, double *r, double *h)
{
int t;
double ex;

switch(o)
{
case '-':
*r=*r - *h;
break;
case '+':
*r=*r + *h;
break;
case '*':
*r=*r * *h;
break;
case '/':
if(fabs(*h)<0.00000001)
{
Message("除数为零!" ); //
return false;
}
*r=(*r) / (*h);
break;
case '%':
t=(int)( (*r) / (*h) );
*r=*r- t*(*h);
break;
case '^': // 原有处理如果指数为小数则结果误差很大
ex=*r;
if( fabs( *h ) < 1e-9 )
{
*r=1.0;
break;
}
if( fabs( *h - floor( *h ) ) < 0.01 || fabs( *h - ceil( *h ) ) < 0.01 )
{
for( t = (int)(*h) - 1; t > 0; t -- )
*r = (*r) * ex;
}
else
*r = pow( *r, *h );
break;
}
return true;
}


//取变量或常数值
bool CExpression::Primitive(double *result)
{
if(strcmp(m_strToken,"") == 0)
return true;

//常数
if(m_cTokenType == NUMBER)
{
//串转化为实数
*result = atof(m_strToken);

//取得下一单元
if(GetToken() != true)
return false;

return true;
}
//变量
else if(m_cTokenType == VARIABLE)
{
if(GetVarValue(m_strToken,result) != true)
return false;

//取得下一单元
if(GetToken() != true)
return false;
return true;
}
return false;
}

bool CExpression::GetVarValue( const char * n, double * result )
{
list<CVar*>::iterator iter;
for(iter=m_VarList.m_VarList.begin();iter!=m_VarList.m_VarList.end();iter++)
{
if((*iter)->m_strName==n)
{
*result=(*iter)->m_dValue;
return true;
}
}
return false;
}
//取得变量在变量表中的索引值
bool CExpression::GetVarIndex( const char * name, int * index )
{
int i=0;
list<CVar*>::iterator iter;
for(iter=m_VarList.m_VarList.begin();iter!=m_VarList.m_VarList.end();iter++)
{
if((*iter)->m_strName==name)
{
*index=i;
return true;
}
i++;
}
return false;
}
bool CExpression::UpdateSlaveVar()
{
bool bRet = true;
list<CVar*>::iterator iter;
for(iter=m_VarList.m_VarList.begin();iter!=m_VarList.m_VarList.end();iter++)
{
if((*iter)->m_strSlave!="")
{
double dResult=m_dResult;
char* strExp=m_strExp;
string str=(*iter)->m_strSlave;
m_strExp=(char*)str.c_str();
(*iter)->m_strSlave="";
bRet=CalExp();
if(bRet==false)
{
string prompt=(*iter)->m_strName;
prompt+="定义错误!";
Message(prompt.c_str());
return false;
}else
{
(*iter)->m_dValue=m_dResult;
}
m_dResult=dResult;
m_strExp=strExp;
}
}

return true;
}
bluebohe 2003-10-10
  • 打赏
  • 举报
回复

//加减运算
bool CExpression::Level2(double *result)
{
register char op; //运算符
double hold=0; //保留运算中间结果

//直接进入高优先级的*/%运算,没有高级运算才进入下面运算
if(Level3(result) != true)
return false;

//若下一单元为+-号
while((op = *m_strToken) == '+' || op == '-')
{
//取得+-号后的单元
if(GetToken() == true)
{
//运算+-号后面的表达式值,有可能又取得+-号
if(Level3(&hold) == true)
{
//数学运算,结果直接放在*result中
bool bRet = Arith(op,result,&hold);
if( bRet == false )
return false;
}
else
return false;
}
else
{
m_iErrFlag = 2; //m_iErrFlag = 1;
return false;
}
}
return true;
}

//乘除及求余数运算
bool CExpression::Level3(double *result)
{
register char op; //运算符
double hold=0; //保留中间运算结果

//直接进入高优先级运算,没有高级运算才进入下面运算
if(Level4(result) != true)
return false;

//若下一单元为*/%
while((op=*m_strToken) == '*' || op == '/' || op == '%')
{
//取得运算符后的单元
if(GetToken() == true)
{
//运算*/%后的表达式值,有可能又获得*/%
if(Level4(&hold) == true)
{
//数学运算,结果放在*result中
bool nRet = Arith(op,result,&hold);
if( nRet == false )
return false;
}
else
return false;
}
else
{
m_iErrFlag = 2; //m_iErrFlag = 1;
return false;
}
}
return true;
}

//乘方运算
bool CExpression::Level4(double *result)
{
register char op; //运算符
double hold=0; //保留中间运算结果

//直接进入高优先级运算,没有高级运算才进入下面运算
if(Level5(result) != true)
return false;

//若下一单元为^(乘方)
while((op=*m_strToken) == '^')
{
if(GetToken() == true)
{
//取得运算符后的单元
if(Level5(&hold) == true)
{
//运算^后的表达式值,有可能又获得^
bool nRet = Arith(op,result,&hold);
if( nRet == false )
return false;
}
else
return false;
}
else
{
m_iErrFlag = 2; //m_iErrFlag = 1;
return false;
}
}
return true;
}



//单目求反运算
bool CExpression::Level5(double *result)
{
register char op = 0;

if((m_cTokenType == DELIMITER) && *m_strToken == '+' || *m_strToken == '-' )
{
//若表达式第一单元为+号或-号,记录该运算符
op = *m_strToken;

//取得下一单元
if(GetToken() != true)
{
m_iErrFlag = 2; //m_iErrFlag = 1;
return false;
}
}

//进入高优先级运算
if(Level6(result) != true)
return false;

//进入高优先级运算
if(op)
Unary(op,result);

return true;
}

//函数处理
bool CExpression::Level6(double *result)
{
int num; char funcname[8];
char op = 0;
int paranum=1;
double para[6];

if( IsFunc( m_strToken ) ) // 如果是函数名
//if(expGetFunIndex(m_strToken,&num) == true)
{
op = 1;
strcpy( funcname, m_strToken );
//取得下一单元
if(GetToken() != true)
{
m_iErrFlag = 2; //m_iErrFlag = 1;
return false;
}
}

if(op)
{
if((*m_strToken == '(') && (m_cTokenType == DELIMITER))
{
//取得括号内第一单元
if(GetToken() == true)
{
//递归调用,完成括号内的表达式运算
if(Level2(result) != true)
return false;
while(m_cTokenType == DELIMITER && *m_strToken == ',')
{
paranum++;
if(GetToken() != true)
{
m_iErrFlag = 2; //m_iErrFlag = 1;
return false;
}

//递归调用,完成括号内的表达式运算
if(Level2(¶[paranum-1]) != true)
return false;
}
para[0] = *result;

//当前符号应为')'
if(*m_strToken != ')')
{
//括号不匹配
m_iErrFlag = 3;
return false;
}

if(GetToken() != true)
{
m_iErrFlag = 2; //m_iErrFlag = 1;
return false;
}
}
else
{
m_iErrFlag = 2; //m_iErrFlag = 1;
return false;
}
}
else
{
//括号不匹配
m_iErrFlag = 3;
return false;
}

//单参数
if(paranum == 1)
{
*result = para[0];
//若函数为三角函数,进行角度到弧度的转换
if(stricmp(funcname,"sin") == 0 ||
stricmp(funcname,"cos") == 0 ||
stricmp(funcname,"tan") == 0 )
{
if( stricmp( funcname, "tan" ) == 0 )
{
if( fabs( *result - 90.0 ) < 0.0005 ||
fabs( *result - 270.0 ) < 0.0005 ||
fabs( *result + 90.0 ) < 0.0005 ||
fabs( *result + 270.0 ) < 0.0005 )
{
Message( "正切函数值溢出!" );//
return false;
}
}
if( m_bDegUnit == true )
*result = *result /180 * PI;
}
else if( stricmp(funcname,"asin") == 0 ||
stricmp(funcname,"acos") == 0 )
{
if( fabs( *result ) > 1.0 )
{
//
Message( "反正弦函数和反余弦函数的参数绝对值必须小于1!" );
return false;
}
}
else if( stricmp( funcname, "sqrt" ) == 0 )
{
if( *result < 0.0 )
{
Message( "不能对负数开平方!" );//
return false;
}
}
else if( stricmp( funcname, "log" ) == 0 ||
stricmp( funcname, "log10" ) == 0 )
{
if( *result <= 0.0 )
{
Message( "负数和零没有对数!" );//
return false;
}
}
if( GetFunIndex( funcname, &num ) )
*result = ( *funTable[num])(*result);
else
{
m_iErrFlag = 2;
return false;
}
}
else
return false;

if(paranum == 1)
{
//若为反三角函数,将弧度转化为度
if(stricmp(funcname,"asin") == 0 ||
stricmp(funcname,"acos") == 0 ||
stricmp(funcname,"atan") == 0 )
{
if( m_bDegUnit == true )
*result = *result *180 / PI;
}
return true;
}
}

if(Level7(result) != true)
return false;

return true;
}
zj510 2003-10-10
  • 打赏
  • 举报
回复
数据结构里面已经讲过很多了,回去翻一下书,我以前做过一个的,主要是利用了STACK数据结构,如果你需要的话,我可以给你一个参考一下。
bluebohe 2003-10-10
  • 打赏
  • 举报
回复
回复一个帖子,不然我接不下去了
bluebohe 2003-10-10
  • 打赏
  • 举报
回复


bool CExpression::GetToken()
{
register char *temp;

m_cTokenType = 0;

//指针指向token的首地址
temp = m_strToken;

//跳过空格及TAB符
while(IsWhite(*m_strExp) == true)
m_strExp++;

//首字符是为运算符
if(IsInStr(*m_strExp,"+-*/%^=(),") == true)
{
m_cTokenType = DELIMITER;
*temp++ = *m_strExp++;
*temp = 0;
return true;
}

//首字符为ASSCI字符或汉字
else if( isalpha(*m_strExp) || (*m_strExp > 127) || (*m_strExp < 0) )
{
//找到字符串结尾
while(IsDelim(*m_strExp) != true)
*temp ++ = *m_strExp++;

*temp = 0;

if(IsFunc( m_strToken ) )
{
m_cTokenType = FUNCTION;
return true;
}

//搜索变量表,判断取得的符号是否为变量
string sToken = m_strToken;
list<CVar*>::iterator iter;

for(iter=m_VarList.m_VarList.begin();iter!=m_VarList.m_VarList.end();iter++)
{
if((*iter)->m_strName == sToken )
{
m_cTokenType = VARIABLE;
return true;
}
}
return false;
}

//首字符为数字
else if(isdigit(*m_strExp) || *m_strExp == '.')
{
//.5按0.5处理
if(*m_strExp == '.')
*temp++ = '0';

while(IsDelim(*m_strExp) != true)
*temp ++ = *m_strExp++;

*temp = 0;
m_cTokenType = NUMBER;
return true;
}

//首字符为NULL
if(*m_strExp == 0)
{
strcpy(m_strToken,"");

//到达结尾
return true;
}
return false;

}


//判断是否为空格或TAB
bool CExpression::IsWhite(char c)
{
if(c == ' ' || c == 9)
return true;
return false;
}

//判断是否为分隔符
bool CExpression::IsDelim(char c)
{
if(IsInStr(c,"+-*/%^=() ,") == true || c == 9 || c == '\r' || c == 0)
return true;
return false;
}

//判断是否为函数
bool CExpression::IsFunc(const char *fname)
{
int i;
for(i=0;i<funTableLen;i++)
{
if(strcmp(fname,funNameTable[i]) == 0)
return true;
}
return false;
}

//判断C是否在串S中
bool CExpression::IsInStr(char ch,char *s)
{
while(*s)
{
if(*s++ == ch)
return true;
}
return false;
}


double sign(double x)
{
if(x > 0)
return x;
else
return 0;
}
//赋值运算
bool CExpression::Level1(double *result)
{
int index,ttok_type;
char temp_token[80];

//变量单元,有可能是赋值的表达式运算
if(m_cTokenType == VARIABLE)
{
//保留该单元及单元类型
strcpy(temp_token,m_strToken);
ttok_type = m_cTokenType;

//若取不到变量在变量表中的索引值
if(GetVarIndex(m_strToken,&index) != true)
{
m_iErrFlag = 2;
return false;
}

if(GetToken() != true)
{
m_iErrFlag = 2; //m_iErrFlag = 1;
return false;
}

//若变量后紧跟'='号,则为赋值运算,否则为一般运算
if(*m_strToken != '=')
{
//将刚取得的单元回送到表达式中
PutBack();

//恢复当前单元变量及变量类型
strcpy(m_strToken,temp_token);
m_cTokenType = ttok_type;
}

//若为赋值运算进入下面运算
else
{
//取'='号后面的单元
if(GetToken() != true)
{
m_iErrFlag = 2; //m_iErrFlag = 1;
return false;
}

//进入高级的+-运算
if(Level2(result) == true)
{
list<CVar*>::iterator iter;
int i=0;
for(iter=m_VarList.m_VarList.begin();iter!=m_VarList.m_VarList.end();iter++)
{
if(i==index)
{
(*iter)->m_dValue=*result;
return true;
}
i++;
}
}
else
return false;
}
}

//第一单元不是变量,直接进入高优先级+-运算
if(Level2(result) == true)
return true;
else
return false;
}
bluebohe 2003-10-10
  • 打赏
  • 举报
回复
// Expression.cpp: implementation of the CExpression class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "Expression.h"
#include "math.h"

const int funTableLen = 17; //函数表长度
double sign(double x);
static double ( * funTable[ ] )( double ) = {
acos, asin, atan,
ceil, cos, cosh, exp,
fabs, floor, log, log10,
sin, sinh, sqrt,
tan, tanh, sign
}; //单参数函数入口地址表

static char funNameTable[ ][6] = {
"acos", "asin", "atan", "ceil", "cos", "cosh", "exp", "fabs",
"floor", "log", "log10", "sin", "sinh", "sqrt", "tan", "tanh", "sign"
}; //函数名表

//////////////////////////////////////////////////////////////////////
// CVar Class
//////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CVar::CVar()
{
InitVar();
}

CVar::~CVar()
{

}
void CVar::InitVar()
{
m_cFlag=1;
m_strName="";
m_strSlave="";
m_dValue=0;
}
//////////////////////////////////////////////////////////////////////
// CVarList Class
//////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CVarList::CVarList()
{

}

CVarList::~CVarList()
{
list<CVar*>::iterator iter;
for(iter=m_VarList.begin();iter!=m_VarList.end();iter++)
{
delete (*iter);
}
m_VarList.clear();
}
bool CVarList::AddVar(CVar *pVar)
{
m_VarList.insert(m_VarList.end(),pVar);
return true;
}



//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CExpression::CExpression()
{
m_iErrFlag=0;
m_iFunFlag=0;
m_iMatchFlag=0;
m_dResult = 0;
m_bDegUnit=true;
m_strExp=NULL;
strcpy(m_strToken,"");
}

CExpression::~CExpression()
{

}

bool CExpression::CalExp()
{
bool ret;

m_iErrFlag=0;
m_iFunFlag=0;
m_iMatchFlag=0;
m_dResult = 0;

if( strlen(m_strExp)==0)
{
m_iErrFlag = 1;
Error();
return false;
}
UpdateSlaveVar();

//取表达式第一单元(利用m_strExp)
if(GetToken() == true)
{
//进入高优先级运算
ret = Level1(&m_dResult);

//若高级运算出现错误(m_iErrFlag被设置)
if(ret == false)
{
//打印错误信息
Error();
return false;
}
else
return true;
}

//从表达式中取符号错误
m_iErrFlag = 2;
Error();
return false;
}
void CExpression::Error()
{
switch(m_iErrFlag)
{
case 1:
Message( "表达式为空!" );
break;
case 2:
Message( "变量或函数非法或语法错误!\n表达式无法计算!" );
break;
case 3:
Message("括号不匹配!"); //"括号不匹配!"
break;
}

}

void CExpression::Message(const char *strMsg)
{
// printf("\n%s\n",strMsg);
}
会思考的草 2003-10-10
  • 打赏
  • 举报
回复
数据结构和编译原理里面已经讲得够多了,回去自己翻翻。
differ1 2003-10-09
  • 打赏
  • 举报
回复
解析一下字符串就可以啦
遇到号调用相应得函数,可用指针函数实现。

16,471

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Web++
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧