数据结构课程设计之简单计算器的实现

2023-05-16

一、问题陈述

从键盘上输入一算术表达式(中缀白大师),包括圆括号,计算出表达式的值。
要求:

  1. 程序对所输入的表达式作简单判断,如有错给出提示;
  2. 实现算术四则运算(+、-、*、/)和平方(^)运算,能处理双目运算符:+-
  3. 能将中缀算术表达式转换成后缀表达式并输出,并输出运算结果。

二、概要设计

2.1 概要简述

中缀表达式转为后缀表达式,从左到右遍历中缀表达式的每个数字和符号,若是数字就输出,即成为后缀表达式的一部分;若是符号,则判断其与栈顶符号的优先级,是右括号或优先级低于找顶符号(乘除优先加减)则栈顶元素依次出找并输出,并将当前符号进栈,一直到最终输出后缀表达式为止。
后缀表达式也称为逆波兰表达式,计算方法为:新建一个表达式,如果当前字符为变量或者为数字,则压栈,如果是运算符,则将栈顶两个元素弹出作相应运算,结果再入栈,最后当表达式扫描完后,栈里的就是结果。

2.2 存储结构表示

typedef struct {//数字栈结构体
	double data[MAXSIZE];
	int top;
} opstack;

typedef struct {//符号栈结构体
	char data[MAXSIZE];
	int top;
} stack;

2.3 详细设计

2.3.1 判断中缀表达式是否合理
//判断中缀表达式是否合理
bool judge_infix(char str[]){
	int temp=0;
 	if(str[0]=='/'||str[0]=='*')
		return false;
	if(str[strlen(str)-1]<'0'&&str[strlen(str)-1]>'9')
		return false;
	for(int i=0; i<strlen(str); i++) {
		if(str[i]=='(') {
			if(i==0&&(str[i+1]=='*'||str[i+1]=='/'))
				return false;
			else if(str[i-1]>='0'&&str[i-1]<='9')
				return false;
			temp++;
		} else if(str[i]==')') {
			if(i==0)
				return false;
			else if(str[i-1]=='+'||str[i-1]=='*'||str[i-1]=='-'||str[i-1]=='/')
				return false;
			else if(str[i+1]>='0'&&str[i+1]<='9')
				return false;
			temp--;
		}
	}
	if(temp==0)
		return true;
	return false;
}
2.3.2 中缀表达式转换为后缀表达式
  1. 创建栈

  2. 从左向右顺序遍历中缀表达式:

    • 数字直接输出
    • 运算符:
      遇到‘(’直接入栈,遇到‘)’将栈中‘(’之后入栈的全部输出,同时‘(’出栈但是不输出。其他符号将符号栈中的元素依次出栈并输出,直到遇到比当前符号优先级更低的符号或者‘(’,将当前符号入栈。
  3. 将栈中剩余的符号依次输出。

//中缀表达式转后缀表达式
void TranslateExpress(char str[], char exp[]) {
	stack s;
	char ch, e;
	int i=0, j=0;
	InitStack(&s);
	ch=str[i++];
	while(ch!='\0') {
		switch(ch) {
			case '(':
				Push(&s,ch);
				break;
			case ')':
				while (GetTop(s,&e)&&e!='(') {
					Pop(&s,&e);
					exp[j++]=e;
				}
				Pop(&s,&e);
				break;
			case '+':
			case '-':
				while (!StackEmpty(s)&&GetTop(s,&e)&&e!='(') {
					Pop(&s,&e);
					exp[j++]=e;
				}
				Push(&s,ch);
				break;
			case '*':
			case '/':
				while(!StackEmpty(s)&&GetTop(s,&e)&&e=='/'||e=='*'||e=='^') {
					Pop(&s,&e);
					exp[j++]=e;
				}
				Push(&s,ch);
				break;
			case '^':
				while(!StackEmpty(s)&&GetTop(s,&e)&&e=='^') {
					Pop(&s,&e);
					exp[j++]=e;
				}
				Push(&s,ch);
				break;
			case ' ':
				break;
			default:
				while(ch>='0'&&ch<='9') {
					exp[j++]=ch;
					ch=str[i++];
				}
				i--;
				exp[j++]=' ';
		}
		ch=str[i++];
	}
	while(!StackEmpty(s)) {
		Pop(&s,&e);
		exp[j++]=e;
	}
	exp[j]='\0';
}

2.3.3 计算后缀表达式值

  1. 依次遍历栈
  2. 检测是否是数字,是数字就压栈,是操作符从栈中依次取出当前操作数的右操作数和左操作数与当前操作符进行运算,结果压栈。
  3. 遍历结束,运行结果就是栈顶元素。
//计算表达式值
double ComputeExpress(char a[]) {
	opstack s;
	int i=0, value;
	float x1, x2, result;
	s.top=-1;
	while (a[i]!='\0') {
		if(a[i]!=' '&&a[i]>='0'&&a[i]<='9') {
			value=0;
			while (a[i]!=' ') {
				value=10*value+a[i]-'0';
				i++;
			}
			s.top++;
			s.data[s.top]=value;
		} else {
			switch(a[i]) {
				case '+':
					x1=s.data[s.top--];
					x2=s.data[s.top--];
					result=x1+x2;
					s.data[++s.top]=result;
					break;
				case '-':
					x1=s.data[s.top--];
					x2=s.data[s.top--];
					result=x2-x1;
					s.data[++s.top]=result;
					break;
				case '*':
					x1=s.data[s.top--];
					x2=s.data[s.top--];
					result=x1*x2;
					s.data[++s.top]=result;
					break;
				case '/':
					x1=s.data[s.top--];
					x2=s.data[s.top--];
					result=x2/x1;
					s.data[++s.top]=result;
					break;
				case '^':
					x1=s.data[s.top--];
					x2=s.data[s.top--];
					result=pow(x2,x1);
					s.data[++s.top]=result;
					break;
			}
			i++;
		}
	}
	if(!s.top!=-1) {
		result=s.data[s.top];
		s.top--;
		if(s.top==-1)
			return result;
		else {
			printf("表达式错误!");
			//exit(-1);
		}
	}
}

三、测试与运行

3.1 判断表达式是否正确

在这里插入图片描述

3.2 简单四则运算

在这里插入图片描述

3.3 含平方运算

在这里插入图片描述

四、代码实现

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#define MAXSIZE 50

typedef struct {//数字栈结构体
	double data[MAXSIZE];
	int top;
} opstack;

typedef struct {//符号栈结构体
	char data[MAXSIZE];
	int top;
} stack;

//初始化栈
void InitStack(stack *s) {
	s->top=0;
}

//取栈头
int GetTop(stack s, char *e) {
	if(s.top<=0)
		return 0;
	else {
		*e=s.data[s.top-1];
		return 1;
	}
}

//出栈操作
void Pop(stack *s, char *e) {
	if(s->top<=0)
		printf("栈空!");
	else
		*e=s->data[--s->top];
}

//入栈操作
void Push(stack *s, char e) {
	if(s->top>=MAXSIZE)
		printf("栈满!");
	else
		s->data[s->top++]=e;
}

//判断栈空
int StackEmpty(stack s) {
	if(s.top==0)
		return 1;
	else return 0;
}

//计算表达式值
double ComputeExpress(char a[]) {
	opstack s;
	int i=0, value;
	float x1, x2, result;
	s.top=-1;
	while (a[i]!='\0') {
		if(a[i]!=' '&&a[i]>='0'&&a[i]<='9') {
			value=0;
			while (a[i]!=' ') {
				value=10*value+a[i]-'0';
				i++;
			}
			s.top++;
			s.data[s.top]=value;
		} else {
			switch(a[i]) {
				case '+':
					x1=s.data[s.top--];
					x2=s.data[s.top--];
					result=x1+x2;
					s.data[++s.top]=result;
					break;
				case '-':
					x1=s.data[s.top--];
					x2=s.data[s.top--];
					result=x2-x1;
					s.data[++s.top]=result;
					break;
				case '*':
					x1=s.data[s.top--];
					x2=s.data[s.top--];
					result=x1*x2;
					s.data[++s.top]=result;
					break;
				case '/':
					x1=s.data[s.top--];
					x2=s.data[s.top--];
					result=x2/x1;
					s.data[++s.top]=result;
					break;
				case '^':
					x1=s.data[s.top--];
					x2=s.data[s.top--];
					result=pow(x2,x1);
					s.data[++s.top]=result;
					break;
			}
			i++;
		}
	}
	if(!s.top!=-1) {
		result=s.data[s.top];
		s.top--;
		if(s.top==-1)
			return result;
		else {
			printf("表达式错误!");
			//exit(-1);
		}
	}
}

//中缀表达式转后缀表达式
void TranslateExpress(char str[], char exp[]) {
	stack s;
	char ch, e;
	int i=0, j=0;
	InitStack(&s);
	ch=str[i++];
	while(ch!='\0') {
		switch(ch) {
			case '(':
				Push(&s,ch);
				break;
			case ')':
				while (GetTop(s,&e)&&e!='(') {
					Pop(&s,&e);
					exp[j++]=e;
				}
				Pop(&s,&e);
				break;
			case '+':
			case '-':
				while (!StackEmpty(s)&&GetTop(s,&e)&&e!='(') {
					Pop(&s,&e);
					exp[j++]=e;
				}
				Push(&s,ch);
				break;
			case '*':
			case '/':
				while(!StackEmpty(s)&&GetTop(s,&e)&&e=='/'||e=='*'||e=='^') {
					Pop(&s,&e);
					exp[j++]=e;
				}
				Push(&s,ch);
				break;
			case '^':
				while(!StackEmpty(s)&&GetTop(s,&e)&&e=='^') {
					Pop(&s,&e);
					exp[j++]=e;
				}
				Push(&s,ch);
				break;
			case ' ':
				break;
			default:
				while(ch>='0'&&ch<='9') {
					exp[j++]=ch;
					ch=str[i++];
				}
				i--;
				exp[j++]=' ';
		}
		ch=str[i++];
	}
	while(!StackEmpty(s)) {
		Pop(&s,&e);
		exp[j++]=e;
	}
	exp[j]='\0';
}

//判断中缀表达式是否合理
bool judge_infix(char str[]){
	int temp=0;
 	if(str[0]=='/'||str[0]=='*')
		return false;
	if(str[strlen(str)-1]<'0'&&str[strlen(str)-1]>'9')
		return false;
	for(int i=0; i<strlen(str); i++) {
		if(str[i]=='(') {
			if(i==0&&(str[i+1]=='*'||str[i+1]=='/'))
				return false;
			else if(str[i-1]>='0'&&str[i-1]<='9')
				return false;
			temp++;
		} else if(str[i]==')') {
			if(i==0)
				return false;
			else if(str[i-1]=='+'||str[i-1]=='*'||str[i-1]=='-'||str[i-1]=='/')
				return false;
			else if(str[i+1]>='0'&&str[i+1]<='9')
				return false;
			temp--;
		}
	}
	if(temp==0)
		return true;
	return false;
}

int main() {
	char a[MAXSIZE],b[MAXSIZE];
	double f;
	int flag=0;
	printf("请输入一个算术表达式:");
	gets(a);
	printf("中缀表达式为: %s\n",a);
	bool judge = judge_infix(a);
	if(judge == false){
        printf("表达式有误!\n");
        system("pause");
		exit(-1);
	}else
		TranslateExpress(a,b);
		printf("后缀表达式为: %s\n",b);
		f=ComputeExpress(b);
		printf("计算结果为: %f\n",f);
	system("pause");
	return 0;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

数据结构课程设计之简单计算器的实现 的相关文章

  • Python图像(字母数字)识别

    本文只针对数字或字母验证码识别 准备工具 tesseract ocr w64 setup v4 1 0 20190314 exepip install pytesseractpip install pillow中文包 tesseract o
  • Python习题

    1 题目 xff1a 编写一个程序 xff0c 使用for循环输出0 10之间的整数 xff1b 代码 xff1a span class token keyword for span i span class token keyword i
  • 面向对象模块和包

    文章目录 1 1 模块1 2 模块的使用2 包 1 1 模块 参考链接 xff1a Python 面向对象 模块和包 来源 xff1a CSDN Python面向对象 模块和包 来源 xff1a CSDN 概念 xff1a 每一个以py为拓
  • SUNDIALS库的编译和使用

    SUNDIALS库的编译和使用 1 简介 SUNDIALS SUite of Nonlinear and DIfferential ALgebraic equation Solvers 是由美国劳伦斯利福摩尔国立实验室 xff08 Lawr
  • 【ing】在Linux虚拟机上安装Sundials库(图文)

    1 Sundials库下载 Sundials下载地址 2 具体步骤 2 1 下载sundials 2 2 0 本次尝试选择sundials 2 2 0进行安装 Sundials文件内容如下 xff1a 2 2 创建安装目录 安装目录名称为
  • 基于docker部署Prometheus

    文章目录 基于Docker搭建Prometheusgitee 介绍Prometheus一 安装运行Prometheus docker版 部署Prometheus1 安装docker联网状态下阿里云离线安装包下载2 下载镜像包3 启动node
  • 程序设计思维与实践 Week11 作业 E 选做题11-1 东东与 ATM

    题目描述 xff1a 一家银行计划安装一台用于提取现金的机器 机器能够按要求的现金量发送适当的账单 机器使用正好N种不同的面额钞票 xff0c 例如D k xff0c k 61 1 2 N xff0c 并且对于每种面额D k xff0c 机
  • kubectl edit

    文章目录 kubectl edit官方文档语法示例 kubectl edit 官方文档 使用默认编辑器 编辑服务器上定义的资源 使用命令行工具获取的任何资源都可以使用edit命令编辑 edit命令会打开使用KUBE EDITOR xff0c
  • kubectl exec

    文章目录 kubectl exec通过bash获得pod中某个容器的TTY xff0c 相当于登录容器 命令行 创建一个test文件 xff1a kubectl exec exec命令同样类似于docker的exec命令 xff0c 为在一
  • kubectl describe

    文章目录 describe语法选项 示例描述一个node详细信息描述一个pod描述calico yaml中的资源类型和名称指定的pod描述所有的pod描述所有包含label k8s app 61 calico kube controller
  • k8s自动化安装脚本(kubeadm-1.21.1)

    文章目录 介绍软件架构安装教程更新内容2023 02 102022 10 202022 08 06准备部署包 操作步骤环境准备结构备注 解压部署包修改host文件初始化环境验证ansible配置 安装k8s集群登录master的节点添加no
  • Shell——docker启动yapi

    文章目录 脚本简介脚本注解执行方式脚本内容 脚本简介 基于运维统一脚本中 17 平台管理下的Yapi管理平台部署系统版本Centos7docker环境 脚本注解 该脚本快速部署yapi平台 xff0c 已通过docker commit把对应
  • Shell——查看基础信息脚本

    文章目录 脚本简介脚本注解安装方式执行方式执行结果 脚本内容新版本旧版本 脚本简介 基于运维统一脚本中 xff0c 19 脚本安装下的检查服务器脚本安装使用yum安装 yum仓库 xff0c 系统版本Centos7 脚本注解 该脚本为了快速
  • k8s自动化安装脚本(kubeadm-1.23.7)

    文章目录 介绍软件架构版本介绍更新内容2023 02 192023 02 152023 02 142023 02 102022 10 202022 08 06准备部署包 操作步骤环境准备结构备注 解压部署包修改host文件脚本使用方式初始化
  • 在VS code中打开网页预览

    在VS code中打开网页预览 在平时进行前端设计的时候 xff0c 你是否会因为无法实时观察到网页的变化而苦恼 xff0c 每一次都要重新打开html文件的过程过于繁琐 xff0c 现在就有一种新的方式能够让你在coding的时候实时观察
  • 最小生成树+思维 扩散(洛谷 P1661)

    扩散 题目描述 一个点每过一个单位时间就会向四个方向扩散一个距离 xff0c 如图 图略 两个点a b连通 xff0c 记作e a b 当且仅当a b的扩散区域有公共部分 连通块的定义是块内的任意两个点u v都必定存在路径e u a0 e
  • C语言解决百钱买百鸡问题

    百钱买百鸡问题 穷举法举例 求解 百钱买百鸡 问题 xff1a 公鸡每只5钱 xff0c 母鸡每只3钱 xff0c 小鸡3只1钱 求解思路 xff1a 设公鸡数为x xff0c 母鸡数为y xff0c 小鸡数为z xff0c 则可以得到下面
  • 程序设计思维与实践 Week12 作业 C 必做题 - 3

    题目描述 xff1a 东东每个学期都会去寝室接受扫楼的任务 xff0c 并清点每个寝室的人数 每个寝室里面有ai个人 1 lt 61 i lt 61 n 从第i到第j个宿舍一共有sum i j 61 a i 43 43 a j 个人 这让宿
  • VMware虚拟机解决空间不足,增加磁盘空间(磁盘扩容)

    在使用VMware进行linux学习过程中有时会出现磁盘空间不足的情况 xff0c 但是之前一直是只要磁盘空间不足就直接重装系统 xff0c 持续一段时间后感觉计算机科班出生的人这样做有点侮辱 xff0c 所以就静心学习了扩充磁盘的过程 x

随机推荐