首先申明头文件
#include "stdafx.h"
#include "iostream"
#include <stdio.h>
#include <string.h> // 用于获取字符串长度
#include <stdlib.h>
using namespace std;
定义栈相关的变量及函数操作
// 定义栈结构
typedef struct
{
double *data; // 数据域数组名
int top; // 栈顶
int stackSize; // 栈最大可用容量
} Stack;
// 初始化栈,输入栈名和容量
void initStack(Stack *stack, int stackSize)
{
stack->data = new double[stackSize]; // 申请一段连续的double类型空间,首地址赋值给data
stack->top = -1; // 栈顶初始化为-1,代表栈空
stack->stackSize = stackSize; // 赋值栈的容量
}
// 判断栈是否为空,为空返回1,非空返回0
int isEmpty(Stack *stack)
{
return stack->top == -1; // 判断栈顶是否为-1,是则代表栈空,输出1
}
// 将值入栈
void push(Stack *stack, double value)
{
if (stack->top < stack->stackSize - 1) // 栈顶未到最大容量
{
stack->data[++stack->top] = value; // 栈顶先自增,再存放元素
}
else
{
cout << "栈满!" << endl;
}
}
// 出栈,返回出栈的元素值,栈空返回0
double pop(Stack *stack)
{
if (!isEmpty(stack)) // 栈非空
{
return stack->data[stack->top--]; // 先取栈顶元素,栈顶再自减
}
else
{
cout << "栈空!" << endl;
return 0; // 栈为空时返回一个默认值
}
}
// 获取栈顶元素
double getTop(Stack *stack)
{
if (!isEmpty(stack)) // 栈非空
{
return stack->data[stack->top]; // 返回栈顶元素值
}
else // 栈空
{
return 0; // 栈为空时返回一个默认值
}
}
// 释放栈空间
void destroy(Stack *stack)
{
delete[] stack->data;
stack->top = -1;
stack->stackSize = 0;
}
定义数与表达式相关的函数操作
// 判断是否为操作符(+ - * /和左右小括号),是则返回1,不是返回0
int isOperator(char ch)
{
return (ch == '+' || ch == '-' || ch == '*' || ch == '/' || ch == '(' || ch == ')');
}
// 判断是否为数字,是则返回1,不是返回0
int isNumber(char ch)
{
return (ch >= '0' && ch <= '9');
}
// 判断是否为合法表达式
int isCorrectExpression(char *expression)
{
int i = 0; // 用于遍历表达式数组
for (i = 0; expression[i] != '\0'; i++)
{
if ((isOperator(expression[i]) == 0) && (isNumber(expression[i]) == 0) && (expression[i] != '.'))
{
cout << "请输入正确的表达式!" << endl;
exit(1); // 表达式中有非操作符或非数字,程序异常结束
}
}
return 1;
}
// 判断是否存在括号不匹配
int checkParen(char *expression)
{
Stack checkStack; // 创建用于括号检查的栈
initStack(&checkStack, strlen(expression)); // 初始化检查栈
int i = 0; // 用于遍历表达式数组
for (i = 0; expression[i] != '\0'; i++) // 遍历表达式数组
{
if (expression[i] == '(') // 遇到左括号就入栈
push(&checkStack, 1); // 用1代表括号入栈
if (expression[i] == ')') //遇到右括号就出栈
{
int tmp = (int) pop(&checkStack); // 定义临时变量存放出栈的数
if (tmp == 0) // pop函数在栈空时不会输出1,而是输出默认值0
{
cout << "括号不匹配!(右括号多)" << endl; // 栈空代表出栈函数比入栈函数调用多,即右括号多
exit(1); // 程序异常结束
}
}
} // 遍历完成
if (isEmpty(&checkStack) == 0) // 括号栈非空
{
cout << "括号不匹配!(左括号多)" << endl; // 栈非空,代表入栈函数比出栈函数调用多,即左括号多
exit(1); // 程序异常结束
}
destroy(&checkStack); // 申请完的内存在用完释放
return 0;
}
// 判断是否为正确的计算式(最后一个除括号外的字符不能是加减乘除;两个运算符间除了括号外必须是一个数字;两个小数点不能出现在同一个数里,如1.1.1)
int checkCalculation(char *expression)
{
int i = 0; // 用于遍历表达式数组
// 先判断符号的正确性(最后一个除括号外的字符不能是加减乘除,且两个运算符间除了括号外必须是一个数字)
for (i = 0; expression[i] != '\0'; i++) // 遍历表达式数组
{
if ((expression[i] == '+' || expression[i] == '-' || expression[i] == '*' || expression[i] == '/')) // 遇到加减乘除
{
i++; // 开始判断表达式下一个字符
while (isNumber(expression[i]) == 0) // 表达式当前字符不是数字
{
if (expression[i] == '+' || expression[i] == '-' || expression[i] == '*' || expression[i] == '/') // 遇到加减乘除
{
cout << "错误的计算式!(两个加减乘除间无数字)" << endl;
exit(1);
}
if (expression[i] == '\0') // 遍历到表达式尾,但仍然不是数字
{
cout << "错误的计算式!(除括号外最后一个字符为加减乘除)" << endl;
exit(1);
}
i++; // 继续往下遍历
}
}
}
// 再判断数字的正确性,一个数内不能有两个小数点
for (i = 0; expression[i] != '\0'; i++) // 遍历表达式数组
{
if ((expression[i] == '.')) // 遇到小数点
{
i++; // 开始往后遍历
while (isNumber(expression[i])) // 移动到非数字的位置
{
i++;
}
if (expression[i] == '.') // 如果是小数点则代表一个数中有至少两个小数点
{
cout << "错误的数据形式!(一个数内有至少两个小数点)" << endl;
exit(1); // 程序异常停止
}
}
}
return 1;
}
// 获取操作符的优先度,返回值越大越优先,0为非法操作符
int getPriority(char Operator)
{
if (Operator == '(') // 括号最先计算
return 3;
else if (Operator == '*' || Operator == '/') // 先乘除
return 2;
else if (Operator == '+' || Operator == '-') // 后加减
return 1;
else
return 0; // 非法操作符
}
// 执行操作符计算,numberStack为数栈引用,operand1和operand2分别为第1、2个数,Operator为操作符
double performOperation(Stack &numberStack, double operand1, double operand2, char Operator)
{
switch (Operator)
{
case '+': // 操作符为'+'
{
cout << operand1 << "+" << operand2 << "=" << operand1 + operand2 << endl; // 运算过程可视化
push(&numberStack, operand1 + operand2); // 将运算结果入栈
return operand1 + operand2;
}
case '-': // 操作符为'-'
{
cout << operand1 << "-" << operand2 << "=" << operand1 - operand2 << endl; // 运算过程可视化
push(&numberStack, operand1 - operand2); // 将运算结果入栈
return operand1 - operand2;
}
case '*': // 操作符为'*'
{
cout << operand1 << "*" << operand2 << "=" << operand1 * operand2 << endl; // 运算过程可视化
push(&numberStack, operand1 * operand2); // 将运算结果入栈
return operand1 * operand2;
}
case '/': // 操作符为'/'
{
if (operand2 != 0) // 判断除数是否为0,不为0就正常运算
{
cout << operand1 << "/" << operand2 << "=" << operand1 / operand2 << endl; // 运算过程可视化
push(&numberStack, operand1 / operand2); // 将运算结果入栈
return operand1 / operand2;
}
else // 除数为0
{
cout << "除数不能为0!" << endl;
exit(1); // 程序异常结束
}
}
default: // 操作符不为'+''-''*''/'
{
cout << "非法操作符!" << endl;
exit(1); // 程序异常结束
}
}
}
// 输入表达式的字符串数组名,计算表达式的结果
double calculateExpression(char *expression)
{
isCorrectExpression(expression); // 检查输入表达式是否合法
checkParen(expression); // 检查输入表达式是否存在括号不匹配
checkCalculation(expression); // 检查输入表达式是否正确
Stack numberStack; // 定义操作数栈
Stack operatorStack; // 定义操作符栈
initStack(&numberStack, strlen(expression)); // 初始化操作数栈
initStack(&operatorStack, strlen(expression)); // 初始化操作符栈
int i = 0; // 用i访问表达式中每个字符
double operand = 0; // 用于临时存放 要放入数栈的浮点数
double num1, num2; // 分别存两个要进行运算的数,num1在运算时靠前
while (expression[i] != '\0' || !isEmpty(&operatorStack)) //遍历表达式数组,并处理完所有操作符栈内的元素
{
if (expression[i] >= '0' && expression[i] <= '9') // 表达式当前字符为数字
{
// 处理数字
operand = strtod(&expression[i], NULL); // 将字符串中 从字符expression[i]开始的浮点数赋值给operand
push(&numberStack, operand); // 将operand入到操作数栈
while ((expression[i] >= '0' && expression[i] <= '9') || expression[i] == '.') // 将i移动到非浮点数所对应的字符位置处
{
i++;
}
}
else // 表达式当前字符为操作符
{
// 左括号出栈,不进行计算
if (getTop(&operatorStack) == '(' && expression[i] == ')') // 栈顶为'(' ,表达式当前字符为')',直接将'('出栈,不计算
{
pop(&operatorStack); //左括号直接出栈
i++; // 移到表达式下一字符位置
continue; // 继续下一次循环
}
// 操作符进栈
if ((isEmpty(&operatorStack) == 1) //操作符栈为空
|| (getPriority(expression[i]) > getPriority( (char) getTop(&operatorStack))) //表达式操作符优先级 大于 栈顶操作符优先级
|| (getTop(&operatorStack) == '(' && expression[i] != ')')) //栈顶为'(' 且 表达式当前字符不为 ')'
{
push(&operatorStack, expression[i]); //操作符进栈
i++; // 移到表达式下一字符位置
continue; // 继续下一次循环
}
// 操作符出栈,进行计算
if (getPriority(expression[i]) <= getPriority( (char) getTop(&operatorStack)) // 表达式当前字符优先级 小于等于 栈顶操作符优先级
|| (expression[i] == '\0' && isEmpty(&operatorStack) == 0) // 表达式为空 且 操作符栈非空
|| expression[i] == ')') // 表达式当前字符为')'
{
num2 = pop(&numberStack); // 数字栈顶出栈,后入先出
num1 = pop(&numberStack); // 数字栈新栈顶(原第二个数字)出栈,先入后出
char op = (char) pop(&operatorStack); // 定义字符op用来临时存放从操作符栈出栈的字符
performOperation(numberStack, num1, num2, op); // 对num1和num2进行op这种类型的运算,num1在前,num2在后,运算完的结果入栈到数栈numberStack中
continue; // 继续下一次循环
}
}
} // 此时已完成表达式的遍历,并处理完所有操作符栈内的元素,运算完成
double result = getTop(&numberStack); // 运算完的结果会存放在数栈的栈顶位置,通过定义result变量,取数栈栈顶,存放在result中,来获得运算结果
destroy(&numberStack); // 申请完的内存在用完释放
destroy(&operatorStack); // 申请完的内存在用完释放
return result; // 运算完的结果会存放在数栈的栈顶位置,通过取数栈栈顶,来获得运算结果,并返回值。
}
main函数
int main()
{
char expression_example[] = "(2*(2*2.5+3/2)-1.2)*2"; // 定义字符数组并初始化
char expression[100] = {0}; // 定义字符数组并初始化
cout << "样例输入:" << "(2*(2*2.5+3/2)-1.2)*2" << endl << "计算过程:" << endl << endl; // 提供样例
cout << endl << "计算结果为:" << calculateExpression(expression_example) << endl << endl; // 输出结果
cout << "请输入您的表达式:";
cin >> expression; // 输入字符串
cout << endl << "计算过程:" << endl;
cout << endl << "计算结果为:" << calculateExpression(expression) << endl; // 输出结果
return 0;
}