(C语言)栈应用简易计算器实现

2023-05-16

//利用栈实现简易计算器,进行包含+,-,*,/,(,)间的计算 
#include<stdio.h>
#include<string.h>
#define MaxSize 100 

typedef struct CharStack				//字符栈 
{
	char data[MaxSize];
	int top;
}cStack;

typedef struct DoubleStack				//数据栈 
{
	double data[MaxSize];
	int top;
}dStack;

int Isop(char );				//当前扫描元素优先级 
int Inop(char );				//栈顶元素优先级 

void Initc(cStack *);				//初始化字符栈 
int Pushc(cStack *,char);			//字符栈压栈 
char Gettopc(cStack *);				//返回栈顶元素 
char Popc(cStack *);				//出栈 

void Initd(dStack *);				//初始化数据栈 
int Pushd(dStack *,double);			//数据压栈 
double Popd(dStack *);				//出栈 

void Trans(char*s1,char*s2);		        //转化为后缀表达式 

double Calculate(char *s2);			//后缀表达式求值 





int main()
{
	char s1[MaxSize];			//用于存储前缀表达式 
	char s2[MaxSize];			//用于存储转换后的表达式 
	printf("请输入表达式:");
	scanf("%s",s1);
	
	Trans(s1,s2);				//处理字符串,并转化为后缀表达式,存放在s2中 
	
	printf("计算结果为: %f",Calculate(s2));		//后缀表达式求值 
	
		
	return 0;
}

//初始化 
void Initc(cStack *s1)
{
	s1->top=-1;
}
 
 //字符栈压栈 
 int Pushc(cStack *c1,char op)
 {
 	if(c1->top<MaxSize)
 	{
 		c1->data[++c1->top]=op;
 		return 1;
	}
	else return 0;
}

//GET栈顶元素 
char Gettopc(cStack *c1)
{
	return c1->data[c1->top];
}

//字符栈出栈 
char Popc(cStack *c1)
{
	return c1->data[c1->top--];
}

//初始化数据栈 
void Initd(dStack *d1)
{
	d1->top=-1;
}

//数据栈压栈 
int Pushd(dStack *d1,double data)
{
	if(d1->top<MaxSize)
	{
		d1->data[++d1->top]=data;
		return 1;
	}
	else return 0;
}

//数据栈出栈 
double Popd(dStack *d1)
{
	return d1->data[d1->top--];
}

int Isop(char op)		//当前扫描运算符优先级
{
	switch(op)
	{
		case '(': return 6;
		case '+': case '-': return 2;
		case '*': case '/': return 4;
	}
}
int Inop(char op)		//当前扫描运算符优先级
{
	switch(op)
	{
		case '(': return 1;
		case '+': case '-': return 3;
		case '*': case '/': return 5;
	}
}

void Trans(char *s1,char *s2)
{
	int i=0;
	int j=0;
	int flag1=-1;				//flag1为0表示上次输出为数字,flag1为1表示上次输出为字符
	int flag2=-1; 				//flag2为0表示上次扫描为数字,flag为1表示上次扫描为运算符,用于区分数字后加空格
	cStack st1;				//暂放运算符 
	Initc(&st1);
	
	while(s1[i]!='\0')			//处理负数 
	{
		if(s1[0]=='-')			//第一位数字为负数时 
		{
			j=strlen(s1);
			while(j>0)
			{
				s1[j+5]=s1[j];
				j--;
			}
			s1[j++]='(';
			s1[j++]='0';
			s1[j++]='-';
			s1[j++]='1';
			s1[j++]=')';
			s1[j]='*';
			
		}
		if(s1[i]=='('&&s1[i+1]=='-')	//非第一位负数时 
		{
			j=strlen(s1);
			while(j>i+1)
			{
				s1[j+5]=s1[j];
				j--;
			}
			s1[j++]='(';
			s1[j++]='0';
			s1[j++]='-';
			s1[j++]='1';
			s1[j++]=')';
			s1[j]='*';
			i=i+5;
		}
		i++;
	}
	
	i=0;
	j=0;
	while(s1[i]!='\0')
	{
		if(flag1==0&&flag2==1)		//若上次的输出为数字,上次循环扫描为字符,则表示该数字串结束,则在数字后加空格区分 
		{
			s2[j++]=' ';
			flag1=1; 
		}
		if(s1[i]>='0'&&s1[i]<='9'||s1[i]=='.')
		{
			s2[j++]=s1[i];
			flag2=0;
			flag1=0;
		}
		else if(s1[i]=='+'||s1[i]=='-'||s1[i]=='*'||s1[i]=='/'||s1[i]=='(')
		{
			flag2=1;
			if(st1.top<0||Isop(s1[i])>Inop(Gettopc(&st1)))
			{
				Pushc(&st1,s1[i]);
			}
			else
			{
				while(st1.top>=0&&Isop(s1[i])<Inop(Gettopc(&st1)))		//当前扫描字符优先级不断与栈顶字符优先级比较,当前字符小于栈顶字符时退栈并输出 
				{
						s2[j++]=Popc(&st1);
						flag1=1;
				}
				if(st1.top<0||Isop(s1[i])>Inop(Gettopc(&st1)))			//当前字符优先级大于栈顶优先级或栈空时当前字符压入字符栈内 
				{
					Pushc(&st1,s1[i]);
				}
				
			}
		}
		else if(s1[i]==')')				 
		{
			flag2=1;
			if(Gettopc(&st1)!='(')		//若括号仅包含数字则没有输出运算符 
			{
				flag1=1;
			}
			while(Gettopc(&st1)!='(')
			{
				s2[j++]=Popc(&st1);
			}
			Popc(&st1);		//将'('出栈 
		}
		i++;
	}
	while(st1.top>=0)		//将栈内剩余的运算符依次退栈输出 
	{
		s2[j++]=Popc(&st1);
	}
	s2[j]='\0';
}

//表达式求值 
double Calculate(char *s1)
{
	int i=0;
	int flag;				//char类型转换为double类型数据标记 
	double data1,data2;
	double sum;
	dStack ds1;
	Initd(&ds1);
	while(s1[i]!='\0')
	{
		if(s1[i]=='+'||s1[i]=='-'||s1[i]=='*'||s1[i]=='/')			//若为运算符获取栈顶两个元素进行计算 
		{
			data1=Popd(&ds1);
			data2=Popd(&ds1);
			if(s1[i]=='+') Pushd(&ds1,data2+data1);
			else if(s1[i]=='-') Pushd(&ds1,data2-data1);
			else if(s1[i]=='*') Pushd(&ds1,data2*data1);
			else if(s1[i]=='/') Pushd(&ds1,data2/data1);
		}
		else							//为数据时转化为double类型压栈 
		{
			flag=0;					//初始化为0为整数部分标记,1为小数部分标记 
			sum=0;
			double divider=1;
			while(s1[i]!=' '&&s1[i]!='+'&&s1[i]!='-'&&s1[i]!='*'&&s1[i]!='/')
			{
				if(s1[i]=='.')		//若有小数点,进入小数转化模式 
				{
					flag=1;
					i++;
					continue;
				}
				if(flag==0)
				{
					sum=sum*10+(double)(s1[i]-'0');
				}
				else
				{
					divider=divider*10;
					sum=sum+((double)(s1[i]-'0'))/divider;
				}
				i++;
			}
			if(s1[i]=='+'||s1[i]=='-'||s1[i]=='*'||s1[i]=='/') i--;	//转化成功一个数据,若下个字符为运算符,则i--,回到当前运算的数据位置 
			Pushd(&ds1,sum);
		}
		i++;		//i++准备下一个字符的转换 
	}
	 return Popd(&ds1);
}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

(C语言)栈应用简易计算器实现 的相关文章

随机推荐

  • python变量命名规范

    一 变量的命名 变量是对象的引用 xff0c 变量存放于栈中 xff0c 对象存放于堆中 python对变量的命名比较简明 xff0c 不得使用数字开头即可 xff0c 在此可引申下 xff0c 包和变量名 xff0c 全都小写 xff0c
  • python-基本数据运算

    一 基本数据运算 xff1b 0不能作除数 xff0c 否则报错 1 43 加 1 43 2 61 3 2 减 3 1 61 2 3 乘 3 2 61 6 4 除 6 2 61 3 5 整除 7 2 61 3 6 求余数 9 2 61 1
  • Verilog电路设计小技巧之表达式位宽

    不积跬步无以至千里 记录Verilog电路设计中的点点滴滴 今天想说说verilog中表达式的位宽问题 xff0c 编码过程中 xff0c 经常会出现很多表达式位宽不匹配 基本上在跑lint的时候 xff0c 只要一个表达式中有任意2个操作
  • MicroPython在Pycharm上的运行方式

    安装插件micropython 安装CP210x VCP Winodws 可在设备管理器中查看 安装python环境变量envs 在Pycharm中激活环境变量 eg xff1a activate MicroPython pip insta
  • VS2012运行C++程序出现fatal error LNK1104: 无法打开文件“kernel32.lib”错误

    VS2012运行C 43 43 程序出现fatal error LNK1104 无法打开文件 kernel32 lib 错误 一 本人的安装环境 xff1a win7 64位 二 解决方法 当时安装完成之后 xff0c 运行一个简单的Hel
  • 调试llvm时出现collect2: fatal error: ld terminated with signal 9

    安装llvm debug版本 release版本的安装过程可以参考https blog csdn net vincentuva article details 82993563 在安装使用debug版本时 xff0c 只需要进入到build
  • 地址栏中的#是什么意思

    我们在开发vue时 xff0c 地址栏中会出现 xff0c 如下图所示 xff1a 当我们点击跳转A页面时 xff1a 那么地址栏中的 到底是什么意思 xff1f 如何去掉 xff1f 路由的两种显示模式 Hash模式 这个模式下地址栏中包
  • Anaconda静默安装

    我们默认安装Anaconda时 xff0c 需要进行交互才可以完成安装 xff0c 例如需要输入yes xff0c 或者回车 有时候我们只需要他进行默认安装即可 xff0c 不需要进行交互 命令如下 xff1a span class tok
  • 使用godoc创建可以本地浏览的go文档站点

    Golang 的官网地址是golang org xff0c 有的时候国内打不开 现在国内的可以使用 xff08 golang google cn xff09 其实 xff0c 如果已经安装好了 go xff0c 可以在本地直接查看go 文档
  • 慎用 dpkg --force-all 安装 linuxqq

    最近与一个朋友联络 xff0c 要用 QQ 去 xff31 xff31 官网上只有比较早的版本 xff0c 安装后 xff0c 还提示必须更新 xff0c 点击还找不到下载 xff0c 悲了个催 后面幸好有 web qq 暂时解决了这个问题
  • 又开了一个BLOG,发个贴纪念一下

    很久没写技术方面的BLOG了 xff0c 最近因为查询资料看了很多比人的BLOG 感觉心里有些痒痒的 xff0c 所以决定再次开一个BLOG xff0c 本人是搞嵌入式开发的 xff0c 对各种通讯终端 xff0c CPU以及LINUX比较
  • How to make linux boot from network

    1 Enable dhcp server on a linux server the etc dhcpd conf should be looked like this ddns update style interim ignore cl
  • 转回CSDN了

    在BLOGSPOT上面挣扎了几个月 xff0c 还是放弃了 xff0c 毕竟看我的BLOG绝大多数肯定是中国人 xff0c 一个老被中国政府封的BLOG是没办法让别人接受的 xff0c 哎 xff0c 还是对BLOGSPOT恋恋不舍阿 xf
  • 最近在研究Mythtv

    mythtv是一个linux下的开源电视节目观看 录制和管理的软件 xff0c 如果装在普通PC上就可以变成一台电视PC xff0c 可以使用遥控器来看电视 xff0c 录节目 xff0c 如果装在一个嵌入式系统里就是一个机顶盒啦 xff0
  • arm linux 内核移植及驱动调试-网卡(1)

    最近在给一块ARM开发板 扬创的2440 移植新的kernel xff0c 原来的驱动都在 xff0c 不过还是碰到不少问题 xff0c 主要是对ARM LINUX的一些结构不甚了解 xff0c 这里作个笔记以便自己或他人查阅 前面没有什么
  • UBUNTU 下的IE6搞定

    可以上网上银行 支付宝 就是有点卡 不知道为什么 另外还有些小bug 不过我已经非常满意了 先装好wine 在ubuntu下面就是 sudo apt get install wine cabextract 然后直接下载安装ie4linux就
  • UBUNTU 下编译POKY

    记录一下我在UBUNTU下编译POKY的一些TIPS xff0c 防止以后再编的时候忘掉 xff0c 又要重新GOOGLE 1 解开pinky的包 2 进入pinky目录输入 source poky init build env 3 修改b
  • LLVM编译collect2: fatal error: ld terminated with signal 9

    报错 xff1a collect2 fatal error ld terminated with signal 9 查了一下这个报错 xff0c 可能是内存不足 xff0c 看到有前人的解决方法 xff0c 创建了20G的交换空间 xff1
  • Rust安装与编写第一个rust程序

    Rust 是 Mozilla 开发的注重安全 性能和并发性的编程语言 下边来演示一下如何安装rust xff0c 并尝试创建第一个rust项目 使用 rustup 脚本安装 xff1a 第一步 xff1a 执行 curl https sh
  • (C语言)栈应用简易计算器实现

    利用栈实现简易计算器 进行包含 43 间的计算 include lt stdio h gt include lt string h gt define MaxSize 100 typedef struct CharStack 字符栈 cha