横式计算器

#include"iostream"
#include"windows.h"
#include"stdlib.h"

using namespace std;
#define MAXSIZE 200
#define MAXSIZEOFDATA 100
#define IsSymbol 0 //是符号 
#define IsData 1   //是数字 

typedef double typedata;

typedef struct
{
	char top;
	typedata data[MAXSIZE][2];
	//data[x][0] 记录数据
	//data[x][1] 记录数据类型 数据或操作符 
}stack;//栈

//判断栈是否为空 
char StackIsEmpty(stack &st)
{
	if (st.top == -1)
		return 1;//若栈是空就返回1 
	return 0;	//若栈不是空就返回0 
}
//栈初始化 
void StackInit(stack &st)
{
	st.top = -1;	//当栈是空时,栈顶指针为-1 
}
//压栈 
void StackPush(stack &st, typedata dat, char symbol)
{
	st.top++;
	st.data[st.top][0] = dat;//存入数据 
	st.data[st.top][1] = symbol;//存入数据或符号 
}
//弹栈 
typedata StackPop(stack &st)
{
	if (StackIsEmpty(st) == 0)
	{
		--st.top;//若栈不为空,栈顶指针向下移 
		return st.data[st.top + 1][0];//并将栈顶上面的数据弹出 
	}
	return -1;
}

float PowFloat(int y)//一个递归函数,即factor,处理小数部分的因子; 
{
	if (y == 0)//若y为0就返回1 
		return 1;
	return 0.1*PowFloat(--y);//y不为0就乘0.1再减一 
}

//计算每一项的值 即子串转换成数值 
typedata StringToData(char *dat, int count)//count为子串的位数 
{
	char i, j;
	typedata sum = 0;//子串的结果 
	if (count == 0)
		return 0;
	//遍历找到小数点位置 位置记录为i
	for (i = 0; i < count; i++)
	{
		if (dat[i] == '.')
			break;
	}
	//没有小数点
	if (count == i)
	{
		for (i = 0; i < count; i++)
		{
			sum = sum * 10;
			sum = sum + dat[i] - '0';//前一个数字乘十再加后一个数字即整数部分 
		}
		return sum;//返回整数部分 
	}
	//有小数点
	if (i < count)
	{
		//计算整数部分 
		for (j = 0; j < i; j++)
		{
			sum = sum * 10 + dat[j] - '0';
		}
		//计算小数部分 
		for (++j; j < count; j++)
		{
			sum = sum + (dat[j] - '0')*PowFloat(j - i);
		}
		return sum;//返回整数+小数部分 
	}
	return -1;
}
void ConversionSuffixExpression(char *str, stack &st)//中缀转后缀表达式 
{
	char count = 0;//count记录位数 
	char dat[MAXSIZEOFDATA];//是每一项数据都在此处存储 
	stack buffer;//是符号栈 
	typedata sum;//每一项数据的临时值 
	char flag = 0;//标记位判断str字符串是否使用完毕 
	StackInit(buffer);
	while (*str != '\0' || *str != '\n')
	{
		count = 0;
		//检测含字符串 是否有可能是计算数据
		while ((*str) <= '9' && (*str) >= '0' || *str == '.')//是数字 
		{
			if (*str == '\0' || *str == '\n')
			{
				//标志位 字符串遍历已经结束
				flag = 1;
				break;
			}
			dat[count++] = *str;//是数字就传到dat字符串里 
			str++;
		}
		//获取数字
		if (count)//不是0就执行 即是数字 
		{
			sum = StringToData(dat, count);//sum为该项的值 ,dat为子串,count为该子串位数 
			StackPush(st, sum, IsData);//将该项数据(非符号)压栈 
		}
		//若字符串使用已经结束则退出循环 
		if (flag == 1 || *str == '\0')
			break;
		//是左括号直接进栈 
		if (*str == '(')
			StackPush(buffer, *str, IsSymbol);
		else if (*str == ')')//右括号直接退栈 直至遇到左括号
		{
			//StackPush(buffer, *str, IsSymbol);
			do
			{
				StackPush(st, StackPop(buffer), IsSymbol);
			} while (buffer.data[buffer.top][0] != '(');
			StackPush(st, StackPop(buffer), IsSymbol);
		}
		//遇到加减运算
		else if (*str == '+' || *str == '-')
		{
			if (StackIsEmpty(buffer) == 1)//若buffer这个栈是空的直接将符号压栈 
				StackPush(buffer, *str, IsSymbol);
			else if (buffer.data[buffer.top][0] == '+' || buffer.data[buffer.top][0] == '-')//若栈顶是加号或减号也将符号压栈,无优先级之分 
			{
				StackPush(st, StackPop(buffer), IsSymbol);
				continue;
				//StackPush(buffer,*str,IsSymbol);	
			}
			else if (buffer.data[buffer.top][0] == '/' || buffer.data[buffer.top][0] == '*')
			{
				StackPush(st, StackPop(buffer), IsSymbol);
				continue;
				//StackPush(buffer, *str,IsSymbol);
			}
			else  //栈顶元素为括号
			{
				StackPush(buffer, *str, IsSymbol);
			}
		}
		else if (*str == '/' || *str == '*')//遇乘除运算 
		{
			if (StackIsEmpty(buffer) == 1)
				StackPush(buffer, *str, IsSymbol);
			else if (buffer.data[buffer.top][0] == '+' || buffer.data[buffer.top][0] == '-')
			{
				StackPush(buffer, *str, IsSymbol);
			}
			else if (buffer.data[buffer.top][0] == '/' || buffer.data[buffer.top][0] == '*')
			{
				StackPush(st, StackPop(buffer), IsSymbol);
				continue;
				//StackPush(buffer, *str, IsSymbol);
			}
			else  //栈顶元素为括号
			{
				StackPush(buffer, *str, IsSymbol);
			}
		}
		str++;	//指向下一个字符 
	}

	while (StackIsEmpty(buffer) == 0)//将buffer栈 里的内容传给st 
	{
		count = StackPop(buffer);//将栈内每一个符号出栈并记录有几个符号 
		StackPush(st, count, IsSymbol);//将buffer栈 里的内容接着数字后传给st 
	}
}
void evaluate(char *str)//计算结果 
{
	typedata countleft, countright, count;
	stack dat, counter, draft;
	StackInit(dat);
	StackInit(counter);
	StackInit(draft);
	ConversionSuffixExpression(str, draft);//将输入的字符串str传给draft成为后缀表达式 
	//由于draft中后缀表达式是反的就调换一下
	while (StackIsEmpty(draft) == 0)
	{
		StackPush(dat, StackPop(draft), draft.data[draft.top][1]);
	}//其最终表达式在dat栈中 

	//开始计算
	while (StackIsEmpty(dat) == 0)//判断是否为空 
	{
		count = StackPop(dat);//记录该项 
		//cout<<"count="<<count<<endl;
		//直接判断是不是计算数据
		if (dat.data[dat.top + 1][1] == IsData)
		{
			StackPush(counter, count, IsData);
		}//不是数据即运算符

		else if (count == '+' || count == '-' || count == '*' || count == '/')
		{
			countright = StackPop(counter);//符号右边的值记录 
			countleft = StackPop(counter);//符号左边的值记录

			if (count == '+')//做加法 
			{
				count = countleft + countright;

				StackPush(counter, count, IsData);
			}
			else if (count == '-')//做减法 
			{
				count = countleft - countright;
				StackPush(counter, count, IsData);
			}
			else if (count == '*')
			{
				count = countleft * countright;
				StackPush(counter, count, IsData);
			}
			else if (count == '/')
			{
				count = countleft / countright;
				StackPush(counter, count, IsData);
			}
		}
		else {/*cout<<"Your input I can't operate"<<endl;*/ }
	}

	while (StackIsEmpty(counter) == 0)
	{
		cout << "计算结果为\n" << StackPop(counter) << endl;//将运算结果出栈 
	}
}
void eatspaces(char *p)//去除空格函数 
{
	int i = 0, j = 0;//设置两个变量 
	for (j = 0; p[j] != '\0'; j++)//j是试探的变量 
	{
		if (p[j] == ' ')//如果是空格直接跳过 
		{
		}
		else
		{
			p[i] = p[j];//不是空格那就让这个p[j]的值赋给p[i] 
			i++;//并让i自增一 
		}
	}
	p[i] = '\0';//每次i自增一后就设置成结尾 
}

int main()
{
	cout << "welcome! This is your calculation! Please input your data!" << endl;

	while (1)
	{
		char data[MAXSIZE] = {0};
		for (int i = 0; i < 50; i++)
		{
			scanf_s("%c", &data[i]);
			if (data[i] == '\n')
				break;
		}
		if (data[0] == '\n')
		{
			cout << "输入结束,期待下次见面" << endl;
			break;
		}
		eatspaces(data);
		cout << "你输入的表达式为" << endl;
		for (int i = 0; i < 50; i++)
		{
			printf("%c", data[i]);
			if (data[i] == '\n')
				break;
		}
		evaluate(data);
	}

	system("pause");
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值