#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;
}
横式计算器
最新推荐文章于 2025-05-03 10:20:22 发布