表达式的计算
Posted cjj2503
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了表达式的计算相关的知识,希望对你有一定的参考价值。
数据结构----表达式的计算
说明:
本程序为表达式的计算算法实现
(1)表达式支持整数的+ - * / ( )运算,可以有空格
(2)算法从文件input.txt 中读取表达式,表达式以#结束算法说明: (1)计算算术表达式的值时,可用两个栈作辅助工具。
(2)对于给出的一个表达式,从左向右扫描它的字符,并将操作数放入栈S1中,运算符放入栈S2中,
但每次扫描到运算符时,要把它同S2的栈顶运算符进行优先级比较,当扫描到的运算符的优先级不高于栈顶运算符的优先级时,
取出栈S1的栈顶和次栈顶的两个元素,以及栈S2的栈顶运算符进行运算将结果放入栈S1中(得到的结果依次用T1、T2等表示)。
(3)为方便比较,假设栈S2的初始栈顶为#(#运算符的优先级低于加、减、乘、除中任何一种运算)。输入举例: 34 + ((5*8)- 20+6)#
输出: 34 + ((5*8)- 20+6) = 60
测试案例
输入案例
34 + ((5*8)- 20+6)#
输出案例
34 + ((5*8)- 20+6) = 60
代码部分
SeqStack.h
#ifndef SEQSTACK_H
#define SEQSTACK_H
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MaxStackSize 100
typedef int DataType;
typedef struct
DataType stack[MaxStackSize];
int top;
SeqStack;
void StackInitiate(SeqStack *S);
int StackNotEmpty(SeqStack S);
int StackPush(SeqStack *S, DataType x);
int StackPop(SeqStack *S, DataType *d);
int StackTop(SeqStack S, DataType *d);
int StackLength(SeqStack S);
#endif
exp.h
#ifndef EXP_H
#define EXP_H
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef enum
PLUS, MINUS, TIMES, OVER, LPAREN, RPAREN, JINHAO
OpType; //頓炬륜잚謹
typedef enum
NUM, OP, ERROR
Type; //데늦잚謹 꾸鱗鑒 꾸鱗륜 俚륜눔써監륜 페儉댄轎데늦
int scan(int* d);
int compareOp(OpType op1,OpType op2);
int compute(int op1,int op2, OpType ot,int* result);
int expCalculation(int *result);
#endif
SeqStack.c
#include "SeqStack.h"
//初始化
void StackInitiate(SeqStack *S)
S->top = 0;
//非空否
int StackNotEmpty(SeqStack S)
if(S.top <= 0) return 0;
else return 1;
//把数据元素值x存入顺序堆栈S中,入栈成功则返回0,否则返-1
int StackPush(SeqStack *S, DataType x)
if(S->top >= MaxStackSize-1)
printf("堆栈已满无法插入!");
return -1;
else
S->top ++;
S->stack[S->top] = x;
return 0;
//出栈 出栈成功则返回0,否则返-1
int StackPop(SeqStack *S, DataType *d)
if(S->top <= 0)
printf("堆栈已空无数据元素出栈!");
return -1;
else
*d = S->stack[S->top];
S->top --;
return 0;
//取栈顶数据元素 ,成功返回0,失败返回-1
int StackTop(SeqStack S, DataType *d)
if(S.top <= 0)
printf("堆栈已空无数据元素!");
return -1;
else
*d = S.stack[S.top];
return 0;
//栈中元素的个数
int StackLength(SeqStack S)
return S.top;
exp.c
```c
#include "exp.h"
#include "SeqStack.h"
extern char str[100];
extern int index;
int scan(int* d)
char temp[100];
int i=0;
while(str[index]==' ') //过滤空格
index++;
if(str[index]=='+')
*d=PLUS;
index++;
return OP;
if(str[index]=='-')
*d=MINUS;
index++;
return OP;
if(str[index]=='*')
*d=TIMES;
index++;
return OP;
if(str[index]=='/')
*d=OVER;
index++;
return OP;
if(str[index]=='(')
*d=LPAREN;
index++;
return OP;
if(str[index]==')')
*d=RPAREN;
index++;
return OP;
while(str[index]>='0'&&str[index]<='9')
temp[i]=str[index];
index++;
i++;
temp[i]='\\0';
if(i>0)
*d=atoi(temp);
return NUM;
if(str[index]=='#')
*d=JINHAO;
return OP;
return ERROR;
//运算符优先表,用函数来表示,比较运算符 op1 和 op2 , op1>op2 返回1; < 返回-1 ; == 返回0; 非法运算符返回-2
int compareOp(OpType op1,OpType op2)
switch(op1)
case PLUS: if(op2==PLUS||op2==MINUS) return 1; if(op2==TIMES||op2==OVER) return -1; if(op2== LPAREN) return -1;if(op2== RPAREN) return 1;if(op2== JINHAO) return 1;
case MINUS: if(op2==PLUS||op2==MINUS) return 1; if(op2==TIMES||op2==OVER) return -1; if(op2== LPAREN) return -1;if(op2== RPAREN) return 1;if(op2== JINHAO) return 1;
case TIMES: if(op2==PLUS||op2==MINUS) return 1; if(op2==TIMES||op2==OVER) return 1; if(op2== LPAREN) return -1;if(op2== RPAREN) return 1;if(op2== JINHAO) return 1;
case OVER: if(op2==PLUS||op2==MINUS) return 1; if(op2==TIMES||op2==OVER) return 1; if(op2== LPAREN) return -1;if(op2== RPAREN) return 1;if(op2== JINHAO) return 1;
case LPAREN: if(op2==PLUS||op2==MINUS) return -1; if(op2==TIMES||op2==OVER) return -1; if(op2== LPAREN) return -1;if(op2== RPAREN) return 0;if(op2== JINHAO) printf("illegal expression:%s",str);return -2;
case RPAREN: if(op2==PLUS||op2==MINUS) return 1; if(op2==TIMES||op2==OVER) return 1; if(op2== LPAREN) printf("illegal expression:%s\\n",str);exit(0); if(op2== RPAREN) return 1;if(op2== JINHAO) return 1;
case JINHAO: if(op2==PLUS||op2==MINUS) return -1; if(op2==TIMES||op2==OVER) return -1; if(op2== LPAREN) return -1;if(op2== RPAREN)printf("illegal expression:%s",str);return -2; if(op2== JINHAO) return 0;
default: printf("illegal expression!");return -2;
//根据不同的运算符类型计算结果,成功返回0,失败返回-1
int compute(int op1,int op2, OpType ot,int* result)
switch(ot)
case PLUS: *result = op1+op2; return 0;
case MINUS: *result = op1-op2; return 0;
case TIMES: *result = op1*op2; return 0;
case OVER: *result = op1/op2; return 0;
default:printf("illegal expression!");return -1;
/*表达式求值算法描述:
(1)计算算术表达式的值时,可用两个栈作辅助工具。
(2)对于给出的一个表达式,从左向右扫描它的字符,并将操作数放入栈S1中,运算符放入栈S2中,
但每次扫描到运算符时,要把它同S2的栈顶运算符进行优先级比较,当扫描到的运算符的优先级不高于栈顶运算符的优先级时,取出栈S1的栈顶和次栈顶的两个元素,
以及栈S2的栈顶运算符进行运算将结果放入栈S1中(得到的结果依次用T1、T2等表示)。
(3)为方便比较,假设栈S2的初始栈顶为#(#运算符的优先级低于加、减、乘、除中任何一种运算)。
*/
int expCalculation(int *result)
SeqStack s1; //装操作数的堆栈
SeqStack s2; //装运算符的堆栈
StackInitiate(&s1);
StackInitiate(&s2);
StackPush(&s2, JINHAO);
int value=0;
Type type=-1;
int isSuccessFinish=0;
type=scan(&value); //扫描到到第一个单词类型
while(1)
if(type==NUM) //如果当前扫描到的单词类型是操作数类型时,操作数进操作数栈
StackPush(&s1,value);
type=scan(&value); //读取下一个单词
else if(type==OP) //如果当前扫描到的单词类型是操作符类型时,与栈顶操作符比较
OpType o;
if(StackNotEmpty(s2)==0) //如果堆栈为空,表达式错误
isSuccessFinish=0;
break;
StackTop(s2,&o);
if(value==JINHAO&&o==JINHAO) // 如果当前扫描到的单词和栈顶操作符都是#,表达式计算正确完成,设置成功标志,退出循环
isSuccessFinish=1;
break;
int result=compareOp(o,value); //如果当前操作符号不是#,栈顶符号和当前扫描到的运算符进行优先级比较
if(result==1) //栈顶符号 > 当前符号, 运算符出栈并计算
//补充代码
OpType o;
DataType a,b;
int T1;
StackPop(&s2,&o);
if(StackNotEmpty(s1)==0)continue;
else StackPop(&s1,&b);
if(StackNotEmpty(s1)==0)continue;
else StackPop(&s1,&a);
compute(a,b,o,&T1);
StackPush(&s1,T1);
else if(result ==-1) //栈顶符号 < 当前符号, 当前符号进栈
//补充代码
StackPush(&s2,value);
type=scan(&value);
else //栈顶符号 == 当前符号,匹配
//补充代码
OpType o;
StackPop(&s2,&o);
type=scan(&value);
else if(type==ERROR)
printf("illegal expression:%s");
return -1;
if(isSuccessFinish&&StackLength(s1)==1)
StackTop(s1,result);
return 0;
else
printf("illegal expression:%s",str);
return -1;
main.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "exp.h"
/*
功能:
主函数
参数:
argc - argv 数组的长度,大小至少为 1,argc - 1 为命令行参数的数量。
argv - 字符串指针数组,数组长度为命令行参数个数 + 1。其中 argv[0] 固定指向当前
所执行的可执行文件的路径字符串,argv[1] 及其后面的指针指向各个命令行参数。
例如通过命令行输入 "C:\\hello.exe -a -b" 后,main 函数的 argc 的值为 3,
argv[0] 指向字符串 "C:\\hello.exe",argv[1] 指向字符串 "-a",argv[2] 指向字符串 "-b"。
返回值:
成功返回 0, 失败返回 1
*/
char str[100];
int index=0;
int main(int argc, char* argv[])
// 使用第一个参数输入待处理文件的名称,若没有输入此参数就报告错误
if(argc < 2)
printf("Usage: app.exe filename\\n");
return 1;
// 打开待处理的文件。读取文件中的内容。
FILE* file= fopen(argv[1], "rt");
if(NULL == file)
printf("Can not open file \\"%s\\".\\n", argv[1]);
return 1;
char temp[100];
if(fgets(temp,100,file)!=NULL)
index=0;
int i=0;
int flag=0;
while(temp[i]!='\\0')
str[i]=temp[i];
if(temp[i]=='#')
flag=1;
break;
i++;
if(flag!=1)
printf("表达式要以#结尾!\\n");
exit(0)Linux shell 编程:运算
求一个匹配 以指定字符开头,指定字符结尾,中间内容任意的正则表达式
求一个匹配 以指定字符开头,指定字符结尾,中间内容任意的正则表达式