问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

c++表达式求值

发布网友 发布时间:2022-04-22 07:59

我来回答

2个回答

热心网友 时间:2022-06-18 05:07

服了你了!就是利用了栈的操作。
肯定是自己写的哦,并且在win-tc和dev-c++或vs2005下运行通过,功能极为强大。
说明:由于幂的运算应该比括号低比乘除要高,所以为避免混淆用幂运算时用括号括起来,比如2+9/3^2-5表示2+(9/3)^2-5,要是想要9除以3^2,这样输入:2+9/(3^2)-5,以免引起歧义。
程序功能强大代码简练。可以对任意数值类型计算,这里全部按double型处理,程序还可以使用大括号{}中括号[]小括号()三种括号,当然优先级是小括号>中括号>大括号>运算符。

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>

char s[201];/*全局变量s[]与i分别表示算术表达式字符串以及其当前位置指针变量*/
int i=0;
double proc1(char ch);
void proc2(double *a,char *c);

void str_read(double *a,char *c) /*读取下一个操作数*/
{ int j=0;
char s1[30];
while ((s[i]!='\0')&&(s[i]!='+')&&(s[i]!='-')&&(s[i]!='(')&&(s[i]!=')')
&&(s[i]!='=')&&(s[i]!='^')&&(s[i]!='*')&&(s[i]!='/')&&(s[i]!='[')&&(s[i]!=']')
&&(s[i]!='{')&&(s[i]!='}')) /*操作数结束标志*/
s1[j++]=s[i++];
s1[j]='\0';
*a=atof(s1);
*c=s[i++];
}

void input_str() /*表达式接收模块*/
{ int j,k,t=0;
char c,s1[80];
printf("\n请输入任一算术表达式:\n");
while (!t)
{ gets(s);
j=k=0; t=1;
while ((s[j]!='=')&&(s[j]!='\0')&&(t)) /*判断括号配对,这就是用了栈的知识,只是程序太完美,一般人体会不深*/
{if ((s[j]=='(')||(s[j]=='[')||(s[j]=='{'))
switch(s[j])
{ case '(':s1[k++]=')';break;
case '[':s1[k++]=']';break;
case '{':s1[k++]='}';
}
else if ((s[j]==')')||(s[j]==']')||(s[j]=='}'))
if (s1[--k]!=s[j])
{ printf("输入出错!请重新输入(直接回车退出):\n");
t=0;
}
j++;
}
if ((k!=0)&&(t))
{printf("输入出错!请重新输入(直接回车退出):\n");
t=0;
}
}
}

void proc2(double *a,char *c)
/*算术运算符之后只有两种情况:要么是各种左括号,要么是操作数*/
{ char ch;
if ((s[i]=='(')||(s[i]=='[')||(s[i]=='{'))
{ switch(s[i])
{ case '(':ch=')';break;
case '[':ch=']';break;
case '{':ch='}';
}
++i;
*a=proc1(ch);
/*计算从当前左括号开始到与其相对应的右括号结束这段表达式的值*/
*c=s[i++]; /*跳过右括号*/
}
else str_read(a,c); /*读取一个操作数*/
}

double proc1(char ch)
/*该过程对算术表达式s从当前位置s[i]开始到表达式结束或s[i]==ch这部分进行求值*/
{ double a1=0,a2,a=0;
char c1='+',c='+',c2='+';
/*给表达式前面加上"0+"(第一操作数与第一操作符)*/
while((c!='=')&&(c!='\0')&&(c!=ch))
{ proc2(&a,&c); /*读取第二操作数与第二操作符.*/
while (c=='^' || c=='*' || c=='/')
{ proc2(&a2,&c2); /*读取第三操作数与第三操作符.*/
switch (c) /*对第二操作符进行运算*/
{ case '*':a=a*a2; break;
case '/':a=a/a2; break;
case '^':a=pow(a,a2);
}
c=c2; /*把第三操作符赋给第二操作符变量*/
}
switch (c1) /*对第一操作符进行运算*/
{ case '+':a1=a1+a;break;
case '-':a1=a1-a;
}
c1=c; /*把第二操作符赋给第一操作符变量*/
}
return(a1); /*返回这部分表达式的值*/
}

int main(void)
{
system("cls");
input_str();
if (s[0]=='\0') return 0;
printf("该表达式的值是: ");
printf("%-8f\n",proc1('\0'));

system("pause");
return 0;
}

--------------------------------------------------------------------
再送一个,显式栈操作,但本程序没有以上程序功能强大:

/* compile under Borland C++ 3.1 or Visual C++ 6.0*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>

#define TRUE 1
#define FALSE 0
#define STACK_INIT_SIZE 100/*存储空间初始分配量*/
#define STACKINCREMENT 20/*存储空间分配增量*/

typedef struct
{
int *pBase;/*在构造之前和销毁之后,base的值为NULL*/
int *pTop;/*栈顶指针*/
int StackSize;/*当前已分配的存储空间,以元素为单位*/
}Stack;

typedef int BOOLEAN;

char Operator[8]="+-*/()#";/*合法的操作符存储在字符串中*/
char Optr;/*操作符*/
int Opnd=-1;/*操作符*/
int Result;/*操作结果*/

/*算符间的优先关系*/
char PriorityTable[7][7]=
{
{'>','>','<','<','<','>','>'},
{'>','>','<','<','<','>','>'},
{'>','>','>','>','<','>','>'},
{'>','>','>','>','<','>','>'},
{'<','<','<','<','<','=','o'},
{'>','>','>','>','o','>','>'},
{'<','<','<','<','<','o','='},
};

//数据对象的操作方法
//构造一个空栈,如果返回值为0,则表示初始化失败
Stack InitStack()/*这是个效率低的方法*/
{
Stack S;
S.pBase=(int*)malloc(STACK_INIT_SIZE*sizeof(int));
if(!S.pBase)
{/*内存分配失败*/
printf("内存分配失败,程序中止运行\n");
exit(-1);
}
else
{
S.pTop=S.pBase;
S.StackSize=STACK_INIT_SIZE;
}
return S;
}
//销毁栈S,S不再存在
void DestoryStack(Stack *S)
{
if(S->pBase)
{
free(S->pBase);
S->pTop=S->pBase=NULL;

}
}
//若栈不空,则用e返回S的栈顶元素
//注:由于应用的特殊,可以不检查栈是否为空
int GetTop(Stack S)
{
return *(S.pTop-1);
}
//插入元素e为新的栈顶元素,如果成功则返回1,否则返回0
int Push(Stack *S,int e)
{
if(S->pTop-S->pBase==S->StackSize)
{//栈满,追加存储空间
S->pBase=(int*)realloc(S->pBase,S->StackSize+STACKINCREMENT*sizeof(int));
if(!S->pBase)
return 0;//存储分配失败
S->pTop=S->pBase+S->StackSize;
S->StackSize+=STACKINCREMENT;
}
*(S->pTop++)=e;
return 1;
}

int Pop(Stack *S,int *e)
{//若栈不空,则删除S的栈顶元素,用e 返回其值,并返回1;否则返回0
if(S->pTop==S->pBase)
return 0;
*e=*--(S->pTop);
return 1;

}
//主函数及其它函数的实现
//比较两个数学符号operator_1,operator_2的计算优先权,在算符优先关系表中查找相应的关系并返回'<','=',或'>'
char CheckPriority(char operator_1,char operator_2)
{
int i,j;//用来查询算符间优先关系表的下标
//char *ptr;
i=strchr(Operator,operator_1)-Operator;//找到传入操作符在字符串Operators中的相对位置
j=strchr(Operator,operator_2)-Operator;
//返回算符优先关系表中相应值
return PriorityTable[i][j];
}

BOOLEAN IsOperator(char ch)
{//判断一个字符是否为打操作符
if(strchr(Operator,ch))
return TRUE;
else
return FALSE;

}
//从键盘获得输入
void GetInput(void)
{
char Buffer[20];//键盘输入缓冲区,用来处理输入多位数的情况
char ch;//存放键盘输入
int index;//存放Buffer的下标
index=0;
ch=getch();//从键盘读入一个字符
while(ch!=13&&!IsOperator(ch))
{//如果输入的字符是回车符或是操作符,循环结束
if(ch>='0'&&ch<='9')
{//将字符回显到屏幕
printf("%c",ch);
Buffer[index]=ch;
index++;

}
ch=getch();
}
if(ch==13)
Optr='#';//输入的表达式以回车符结束
else
{
Optr=ch;
printf("%c",ch);

}
if(index>0)
{
Buffer[index]='\0';
Opnd=atoi((Buffer));
}
else
Opnd=-1;//程序不支持输入负数,当Opnd为负数时,表示输入的字符为操作符
}
//计算形如a+b之类的表达式,theta为操作符,a,b为操作数
int Calc(int a,char theta,int b)
{
switch(theta)
{
case '+':
return a+b;
case '-':
return a-b;
case '*':
return a*b;
default:
if(b==0)//除数为零的情况
{
printf("除数不能为");
return 0;//返回0用以显示
}
else
return a/b;
}
}
/*表达式求值*/
BOOLEAN EvaluateExpression()
{
int temp;//临时变量
char theta;//存放操作符的变量
int itheta;//存放出栈的操作符的变量add by me
int a,b;//存放表达式运算时的中间值
int topOpnd;//栈顶操作数
char topOptr;//栈顶操作符

Stack OPTR=InitStack();//操作符栈
Stack OPND=InitStack();//操作数栈

if(!Push(&OPTR,'#'))//操作符栈中的第一个为#字符
return FALSE;

GetInput();//从键盘获得输入

while(Optr!='#'||GetTop(OPTR)!='#')
{//如果Optr>=0,表示有操作数输入
if(Opnd>=0)Push(&OPND,Opnd);
switch(CheckPriority(GetTop(OPTR),Optr))
{
case '<'://栈顶元素优先权低
if(!Push(&OPTR,Optr))return FALSE;
GetInput();
break;
case '='://脱括号并接收键盘输入
Pop(&OPTR,&temp);GetInput();
break;
case '>'://退栈并将运算结果入栈
//先用itheta得到操作符在赋给theta
Pop(&OPTR,&itheta);
Pop(&OPND,&b);
Pop(&OPND,&a);
theta = (char)( itheta );
Push(&OPND,Calc(a,itheta,b));
Opnd=-1;
break;

}
}
//本算法中,当输入只有一个操作数然后就输入回车符时,
//OPND.pTop==OPND.pBase
//如果OPND.pTop==OPND.pBase并且Opnd<0,则说明用户
//未输入任何操作和操作符而直接输入[回车],程序直接
//退出运行
if(OPND.pTop==OPND.pBase&&Opnd<0)
{
printf("\n\n感谢使用!\n");
exit(1);

}
else if(OPND.pTop==OPND.pBase)
Result=Opnd;
else
{
Result=GetTop(OPND);
DestoryStack(&OPND);
DestoryStack(&OPTR);
}
return TRUE;

}

void Message(void)
{
printf("\n四则运算表达式求值演示\n");
printf("-------------------------------\n");
printf("使用方法:请从键盘上直接输入表达式,以回车键结束.如45*(12-2)[回车]\n");
printf("注0:不输入任何数而直接按[回车]键,将退出程序.\n");
printf("注1:本程序暂时不接受除数字键及四则运算符之外的任何其它键盘输入.\n");
printf("注2:本程序暂时只能处理正确的表达式,不支持输入负数.\n");
printf("-------------------------------\n\n");
}

int main(void)
{
int i;//用来一些说明性信息
Message();
for(i=1;;i++)
{
printf("表达式%d:",i);
if(EvaluateExpression())
printf("=%d\n",Result);
else
printf("计算中遇到错误\n");

}

return 0;
}

热心网友 时间:2022-06-18 05:07

我前几天才编的科学计算器
http://tieba.baidu.com/f?kz=604999195
除了你要的功能外 还添加^运算 !运算 与数学函数乘号简写(可以输5(3+2))等功能 还有结果记忆功能
不过有些和【实现提示】中的实现方法不太一样 虽然也是利用栈的操作 需要你自己修改一下 或者删除一些不要求的功能
声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
八月中国最凉快的地方 八月份哪里最凉快,去哪旅游好?美丽的地方 乱字同韵字是什么意思 华硕笔记本电脑触摸板怎么开笔记本电脑触摸板怎么开启和关闭_百度知 ... 陕西职务侵占案立案准则 结婚后我的恋情维系了十年,怎么做到的? 玉米仁子饭产自哪里 中国期货交易所的交易品种有哪些? 历史要怎么读,有啥诀窍 高中历史诀窍 图形与位置.在图中描出下面各点,并依次连起来.A... 国旗的英文翻译? 做保险理赔员有什么发展前景 用IDl编写光谱重采样的代码 Word 中如何微调图形及图像的位置 ? 国庆节准备干什么,英语造句 保险公司招聘是不是骗人的? C语言 任意表达式求值。(栈的应用 小学数学中“图形与位置”的教学包含哪些 人寿保险招聘的理赔定损专员是不是骗人的 图形与位置 什么方向偏什么方向 怎么确定的 给以下英语词组造句,最好短一点,要加翻译 数据结构表达式求值程序 最近新华保险招团队主管,可靠么? national 造英语句子 cs3000怎么用calcu语句 小学数学中“图形与位置”的教学有哪两条基本线索?... 平安保险招聘 小学数学图形与位置 保险公司招聘 苏教版小学图形与位置整理方案 英语翻译,造句 在java中,定义一个接口,声明计算长方形面积和周... 图形与位置的意义 calculate 这个单词如何更好记 图形与图形之间的位置关系一般怎么表达 关于保险公司招聘和用人情况? 图形与位置。 指南针一端指着正北面,另一端指向(... 车险理赔主管的职责 解释形式否定句,语法,举例,造句 图形与位置教学设计及说课稿 高分啊!!! 所有关于空间与图形的知识(小学) vb 做计算器 界面如图所示 图形与位置思维导图 champion 造句 4个 翻译 如何通过学习&quot;确定图形位置&quot;的方法,发展学生的空... 怎样学好英文? 今天接到了阳光保险财险的面试通知,由于心里对这... 图形与位置是属于趣课数学乐园哪个模块的? 用“for”造句,15句,内容不限,要不同的!