📚博客主页:Zhui_Yi_
🔍:上期回顾:图
❤️感谢大家点赞👍🏻收藏⭐评论✍🏻,您的三连就是我持续更新的动力❤️
🎇追当今朝天骄,忆顾往昔豪杰。
文章目录
前言
本期呢,给大家带来的课程设计,简单给大家说一哈要求:
问题描述
基 本 要 求
实 现 提 示
一、摘要以及引言
摘要
引言
二、系统设计
- 本系统主要由以下几个部分组成:
- 链栈结构:定义了两个链栈,OPTD用于存储操作数,OPTR用于存储运算符。
表达式解析与计算:程序首先读取用户输入的中缀表达式,然后根据运算符优先级和括号规则,将表达式转换为便于计算的形式,并最终求得结果。
用户交互:提供友好界面,用户输入表达式,以等号结束,程序显示计算结果,并询问是否继续进行新的计算。
三、关键算法与实现
1.运算符处理
- 运算符入栈规则:程序通过Precede函数判断新读入的运算符与栈顶运算符的优先级,优先级较低的运算符先出栈计算。
括号处理:遇到左括号入栈,遇到右括号则弹出栈顶运算符直到遇到左括号,处理括号内表达式。
等号处理:等号既是输入结束标志,也作为特殊运算符处理,确保表达式正确结束。
2.表达式求值流程
- 初始化:初始化两个链栈。
- 读取输入:逐字符读取用户输入的表达式。
- 字符处理:对每个字符判断是否为运算符、数字或结束符号,进行相应处理。
- 运算符优先级判定与操作数计算:使用栈结构辅助计算,遵循运算符优先级规则。
- 输出结果:计算完成后,输出表达式的计算结果。
四、程序实现
本程序使用C++语言实现,主要采用了结构体定义链栈,通过自定义的链栈操作函数实现了数据的入栈、出栈等操作。calculate函数为核心,负责解析和计算表达式。通过一系列条件判断和循环结构,实现了对中缀表达式的有效处理。此外,程序还包含用户交互环节,提高了用户体验。
五、具体代码
1.定义结构以及初始化
// 链栈节点结构
struct Node {
double data;
Node* next;
};
// 链栈结构
struct LinkStack {
Node* top;
int size;
};
// 初始化链栈
LinkStack* InitLinkStack() {
LinkStack* stack = new LinkStack;
stack->top = nullptr;
stack->size = 0;
return stack;
}
2.简单的链栈操作
判空
bool IsEmpty(LinkStack* stack) {
return stack->top == nullptr;
}
入栈
// 入栈操作
void Push(LinkStack* stack, double value) {
Node* node = new Node;
node->data = value;
node->next = stack->top;
stack->top = node;
stack->size++;
}
出栈
double Pop(LinkStack* stack) {
if (IsEmpty(stack)) {
throw runtime_error("栈是空的!");
}
double value = stack->top->data;
Node* temp = stack->top;
stack->top = stack->top->next;
delete temp;
stack->size--;
return value;
}
取栈顶元素
// 获取栈顶元素
double GetTop(LinkStack* stack) {
if (IsEmpty(stack)) {
throw runtime_error("栈是空的!");
}
return stack->top->data;
}
判断运算符是否有效
运算符分为+、-、*、/、=,即:
bool In(char c) {
if (c == '(' || c == ')' || c == '+' || c == '-' || c == '*' || c == '/' || c == '=')
return true;
return false;
}
将运算符转换
int intdata(char c) {
switch (c) {
case '+': return 0;
case '-': return 1;
case '*': return 2;
case '/': return 3;
case '(': return 4;
case ')': return 5;
case '=': return 6;
default: break;
}
}
判断运算符优先级
根据这张图片进行建立二维数组。
char Precede(char c1, char c2) {
int a, b;
char table[7][7] = {
'>','>','<','<','<','>','>',
'>','>','<','<','<','>','>',
'>','>','>','>','<','>','>',
'>','>','>','>','<','>','>',
'<','<','<','<','<','=','0',
'>','>','>','>','0','>','>',
'<','<','<','<','<','0','=',
};
a = intdata(c1); b = intdata(c2);
return table[a][b];
}
进行运算
double operate(double a, char c, double b) {
if (c == '+') return (a + b);
else if (c == '-') return (a - b);
else if (c == '*') return (a * b);
else if (c == '/') {
if (b == 0) return (flag = 1);
else return (a / b);
}
}
进行运算
double calculate() {
char ch, tempc;
double x, y, temp, count = 0;
Push(OPTR, '=');
cin >> ch;
while (ch != '=' || GetTop(OPTR) != '=') {
if (!In(ch)) {
if (count != 0) {
temp = GetTop(OPTD); Pop(OPTD);
temp = (double)(temp * 10 + ch - '0');
Push(OPTD, temp);
cin >> ch;
}
else {
temp = (double)(ch - '0');
Push(OPTD, temp);
count++;
cin >> ch;
}
}
else {
count = 0;
switch (Precede(GetTop(OPTR), ch)) {
case '<':
Push(OPTR, ch);
cin >> ch;
break;
case '>':
tempc = GetTop(OPTR); Pop(OPTR);
y = GetTop(OPTD); Pop(OPTD);
x = GetTop(OPTD); Pop(OPTD);
Push(OPTD, operate(x, tempc, y));
break;
case '=':
tempc = GetTop(OPTR); Pop(OPTR);
cin >> ch;
break;
default:
break;
}
}
}
return GetTop(OPTD);
}
完整代码
#include <iostream>
#include <string>
using namespace std;
// 链栈节点结构
struct Node {
double data;
Node* next;
};
// 链栈结构
struct LinkStack {
Node* top;
int size;
};
// 初始化链栈
LinkStack* InitLinkStack() {
LinkStack* stack = new LinkStack;
stack->top = nullptr;
stack->size = 0;
return stack;
}
// 判断栈是否为空
bool IsEmpty(LinkStack* stack) {
return stack->top == nullptr;
}
// 入栈操作
void Push(LinkStack* stack, double value) {
Node* node = new Node;
node->data = value;
node->next = stack->top;
stack->top = node;
stack->size++;
}
// 出栈操作
double Pop(LinkStack* stack) {
if (IsEmpty(stack)) {
throw runtime_error("栈是空的!");
}
double value = stack->top->data;
Node* temp = stack->top;
stack->top = stack->top->next;
delete temp;
stack->size--;
return value;
}
// 获取栈顶元素
double GetTop(LinkStack* stack) {
if (IsEmpty(stack)) {
throw runtime_error("栈是空的!");
}
return stack->top->data;
}
// 全局链栈
LinkStack* OPTD = InitLinkStack();
LinkStack* OPTR = InitLinkStack();
int flag = 0;
// 判断字符是否为运算符
bool In(char c) {
if (c == '(' || c == ')' || c == '+' || c == '-' || c == '*' || c == '/' || c == '=')
return true;
return false;
}
// 将运算符转换为序号
int intdata(char c) {
switch (c) {
case '+': return 0;
case '-': return 1;
case '*': return 2;
case '/': return 3;
case '(': return 4;
case ')': return 5;
case '=': return 6; // 修改这里,添加'='的序号
default: break;
}
}
// 判定运算符优先级
char Precede(char c1, char c2) {
int a, b;
char table[7][7] = {
'>','>','<','<','<','>','>',
'>','>','<','<','<','>','>',
'>','>','>','>','<','>','>',
'>','>','>','>','<','>','>',
'<','<','<','<','<','=','0',
'>','>','>','>','0','>','>',
'<','<','<','<','<','0','=',
};
a = intdata(c1); b = intdata(c2);
return table[a][b];
}
// 执行运算
double operate(double a, char c, double b) {
if (c == '+') return (a + b);
else if (c == '-') return (a - b);
else if (c == '*') return (a * b);
else if (c == '/') {
if (b == 0) return (flag = 1);
else return (a / b);
}
}
// 表达式求值
double calculate() {
char ch, tempc;
double x, y, temp, count = 0;
Push(OPTR, '=');
cin >> ch;
while (ch != '=' || GetTop(OPTR) != '=') {
if (!In(ch)) {
if (count != 0) {
temp = GetTop(OPTD); Pop(OPTD);
temp = (double)(temp * 10 + ch - '0');
Push(OPTD, temp);
cin >> ch;
}
else {
temp = (double)(ch - '0');
Push(OPTD, temp);
count++;
cin >> ch;
}
}
else {
count = 0;
switch (Precede(GetTop(OPTR), ch)) {
case '<':
Push(OPTR, ch);
cin >> ch;
break;
case '>':
tempc = GetTop(OPTR); Pop(OPTR);
y = GetTop(OPTD); Pop(OPTD);
x = GetTop(OPTD); Pop(OPTD);
Push(OPTD, operate(x, tempc, y));
break;
case '=':
tempc = GetTop(OPTR); Pop(OPTR);
cin >> ch;
break;
default:
break;
}
}
}
return GetTop(OPTD);
}
// 菜单函数
void menu() {
puts("\n=========================\n");
puts(" 表达式求值");
puts("\n=========================\n");
}
// 主函数
int main() {
menu();
double answer, trueValue = 1;
while (trueValue) {
cout << "\n请输入表达式,以等号(=)结束:";
answer = calculate();
if (flag == 1) {
cout << "分母不能为0哦!" << endl;
flag = 0;
}
else
cout << "表达式的值为:" << answer << endl;
cout << "按0可结束程序,继续请按1:";
cin >> trueValue;
}
return 0;
}
总结
本文通过设计链栈数据结构和实现相应的算法,成功开发了一个能够处理中缀表达式的程序。该程序不仅能够正确计算表达式的值,还具备良好的用户交互体验,适合教学和初步编程实践。未来的工作可以考虑扩展程序功能,支持更多类型的运算符和更复杂的表达式结构。