//算术表达式求值
//作者:金航
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <conio.h>
#include "SqStack.h"
using namespace std;
char input[1024];
SqStack<double> OPND;
SqStack<char> OPTR;
int count = 0;
Status InitProcess();
bool CheckExpress();
int JudgeOptr(char ch);
#define UNACCEPTED 0
#define NUMBER 1
#define POINT 2
#define OPERATOR 3
#define BRAC 4
#define SHARP 5
void Message(int pos, int type, const char *words);
#define INFO 0
#define ERROR 1
#define WORNING 2
#define YES 1
#define NO 0
Status ParseToFloat(char* &p, double &ret);
#define EXTRAPOINT 1
#define POINTATNUMHEAD 2
char Precede(char theta1, char theta2);
double Operate(double num1, char theta, double num2);
void Print(char *p);
int main()
{
char *p = NULL;
char numtmp[16];
int state = OK, rtn;
cout << "算术表达式求值\n"
<< "表达式条件限制:\n"
<< "最大长度1024,以'#'结束,每个数字不超过15位(小数点算1位)\n"
<< "请输入表达式(输入首字符为'#'时退出程序):";
MAINLOOP:
while (true)
{
state = OK;
count = 0;
if (ERROR == InitProcess()) //初始化
{
Message(0, ERROR, "初始化失败。");
}
p = &input[0];
count++;
if (input[0] == '#') //首个字符为#时退出程序
{
break;
}
if (!CheckExpress()) //检查表达式
{
continue;
}
while ('#' != *p || '#' != OPTR.GetTop()) //表达式处理过程
{
if (NUMBER == JudgeOptr(*p) || POINT == JudgeOptr(*p))
{
double num;
if (*(p - 1) == ')')
{
Message(count, ERROR, "语法错误,计算中止");
goto ENDDING;
}
rtn = ParseToFloat(p, num);
if (EXTRAPOINT == rtn)
{
Message(count, ERROR, "同个数中小数点超过1个");
goto ENDDING;
}
else if (POINTATNUMHEAD == rtn)
{
Message(count, ERROR, "小数点位于数字开头");
goto ENDDING;
}
else
{
OPND.Push(num);
Print(p);
}
}
else
{
if ('(' == *p && NUMBER == JudgeOptr(*(p - 1)))
{
OPTR.Push('*');
Print(p);
}
switch (Precede(OPTR.GetTop(), *p))
{
case '<':
if (ERROR == OPTR.Push(*p))
{
Message(count, ERROR, "语法错误,数字和括号关系有误,计算中止");
goto ENDDING;
}
p++;
count++;
Print(p);
break;
case '=':
if (ERROR == OPTR.Pop())
{
Message(count, ERROR, "语法错误,计算中止");
goto ENDDING;
}
p++;
count++;
Print(p);
break;
case '>':
char opr;
double topa, topb, rst;
state = OK;
state += OPTR.Pop(opr);
state += OPND.Pop(topb);
state += OPND.Pop(topa);
Print(p);
if (state > OK)
{
Message(count, ERROR, "语法错误,运算数不足,计算中止");
goto ENDDING;
}
rst = Operate(topa, opr, topb);
OPND.Push(rst);
Print(p);
break;
case '*':
Message(count, ERROR, "语法错误,计算中止");
goto ENDDING;
break;
default:
break;
}
}
}
cout << "Input:#" << input << endl
<< "表达式已接受。\n"
<< "计算值:" << OPND.GetTop();
ENDDING:
cin.clear();
cin.sync();
}//MainLoop
return 0;
}
void Print(char *p)
{
cout << "String: " << p << endl;
cout << "OPTR: ";
OPTR.ShowAllStack();
cout << "OPND: ";
OPND.ShowAllStack();
cout << "----------------\n";
}
Status InitProcess()
{
count = 0;
cout << "\n\n#";
cin.getline(input, 1024, '\n');
OPTR.DestoryStack();
OPND.DestoryStack();
if (OK == OPTR.InitStack()
&& OK == OPND.InitStack())
{
OPTR.Push('#');
return OK;
}
return ERROR;
}
bool CheckExpress()
{
char *p;
int pos = 0, replace = 0;
//检查以'#'结束
if (input[strlen(input) - 1] != '#')
{
Message(strlen(input) + 1, ERROR, "没有以'#'结束。");
return false;
}
//替换中大括号为小括号
cout << ' ';
for (p = &input[0]; *p != '#'; p++)
{
switch (*p)
{
case '{':
case '[':
cout << '^';
*p = '(';
replace++;
break;
case '}':
case ']':
cout << '^';
*p = ')';
replace++;
break;
default:
cout << ' ';
break;
}
}
cout << endl;
if (replace > 0)
{
cout << "提示:有" << replace << "处括号将被替换为圆括号。\n";
}
//检查非法字符
for (p=&input[0]; *p!='#'; p++)
{
if (UNACCEPTED == JudgeOptr(*p))
{
Message(pos + 1, ERROR, "含有非法字符。");
return false;
}
pos++;
}
return true;
}
int JudgeOptr(char ch)
{
int chnum;
char accept[] = {'1', '2', '3', '4', '5', '6', '7', '8', '9', '0',
'.', '+', '-', '*', '/', '(', ')', '#'};
for (chnum = 0; chnum < 18; chnum++)
{
if (ch == accept[chnum])
{
break;
}
}
if (chnum < 10)
{
return NUMBER;
}
else
{
switch (chnum)
{
case 10:
return POINT;
break;
case 11: case 12: case 13: case 14:
return OPERATOR;
break;
case 15: case 16:
return BRAC;
break;
case 17:
return SHARP;
break;
default:
return UNACCEPTED;
break;
}
}
}
void Message(int pos, int type, const char *words)
{
cout << "Input: \n#" << input << endl;
for (int i=0; i<pos; i++)
{
cout << ' ';
}
cout << '^' << "\n位置" << pos << ":";
switch (type)
{
case INFO:
cout << "提示:" << words << endl;
break;
case ERROR:
cout << "错误:" << words << endl;
cin.clear();
cin.sync();
break;
case WORNING:
cout << "警告:" << words << endl;
break;
default:
break;
}
return;
}
Status ParseToFloat(char* &p, double &ret)
{
char numstr[12];
int i;
bool point = false;
memset(numstr, 0, sizeof(numstr));
if (*p == '.')
{
ret = 0.0f;
return POINTATNUMHEAD;
}
for (i = 0; JudgeOptr(*p) < 3; i++)
{
numstr[i] = *p;
if (*p == '.')
{
if (point)
{
ret = 0.0f;
return EXTRAPOINT;
}
else
{
point = true;
}
}
p++;
count++;
}
numstr[i] = '\0';
ret = atof(numstr);
return OK;
}
char Precede(char theta1, char theta2)
{ // +-*/()#
char table[7][8] = {">><<<>>", //+
">><<<>>", //-
">>>><>>", //*
">>>><>>", ///
"<<<<<=*", //(
">>>>*>>", //)
"<<<<<*="}; //#
char order[] = "+-*/()#";
int x, y;
for (int i=0; i<7; i++)
{
if (order[i] == theta1)
{
y = i;
}
if (order[i] == theta2)
{
x = i;
}
}
return table[y][x];
}
double Operate(double num1, char theta, double num2)
{
double ret = 0.0f;
switch (theta)
{
case '+':
ret = num1 + num2;
break;
case '-':
ret = num1 - num2;
break;
case '*':
ret = num1 * num2;
break;
case '/':
ret = num1 / num2;
break;
default:
break;
}
return ret;
}

造轮使者
- 粉丝: 30
- 资源: 6
最新资源
- GitHub新手使用教程(Windows Git从安装到使用).docx
- Matlab Simulink下的双馈风机控制策略比较研究:超速减载变桨调频与下垂控制及虚拟惯性控制的应用分析于三机九节点系统中,Matlab Simulink下的双馈风机全套控制策略解析:超速减载变
- 基于深度强化学习的无人机自主避障与目标追踪:MP-DQN算法Python实现(论文复现含可运行代码及解释共18页)
- Linux下Nginx+Tomcat负载均衡和动静分离配置要点.docx
- Deepseek免费无卡顿五大访问全攻略:多平台实现AI快速响应
- 电脑装机必备软件清单/windows装机必备软件库
- 图书管理系统BOOKMS winform+sqlite
- C++实现单目相机与投影仪标定算法,yml格式输出结果,重投影误差小于0.1像素,单目相机与投影仪标定算法研究:C++实现,yml格式输出,重投影误差低于0.1像素,单目相机+投影仪标定算法,C++语
- 非线性七自由度模型搭建与CarSim联合仿真验证:车速50km/h路面附着力0.8时的模型精度与误差分析,非线性七自由度模型搭建与CarSim联合仿真验证:车速50km/h路面附着力0.8下的模型精度
- 永磁同步电机转速滑模控制与电流矢量双闭环控制Matlab仿真模型:原理说明与文献参考,永磁同步电机转速滑模控制与电流矢量双闭环控制Matlab仿真模型:原理说明与文献参考,永磁同步电机转速滑模控制Ma
- 软件面试题宝典.docx
- 基于MATLAB的菲涅尔公式计算:P波、S波振幅透射与反射系数及其比值分析,自然光透射反射比的算法实现 ,基于MATLAB的菲涅尔公式计算:P波、S波振幅透射反射系数及比值分析,以及自然光透反特性研究
- 基于Next.js和Deepseek API开发的智能闪卡学习工具
- java调用科大讯飞在线语音合成API
- STM32C8T6库函数实现SG90和SH04扫描测距完整代码工程
- C# LitJson 案例
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈


