每一个点开我的文章的小伙伴大家好!
在发这篇文章的时候,我是一名大二的学生,我将在博客记载我的学习之路!
这是我的第十二篇博客文章,这是关于C语言利用顺序栈实现算术四则运算
利用顺序栈来实现的话,按我的理解可以利用栈的两种不同存在形式来实现
第一就是带结构体的栈,就是很平常的定义结构体那种
第二种就是模拟栈,因为栈只需要一个指向栈顶的指针,所以可以用数组来模拟顺序栈
我个人觉得模拟栈比较方便,而且利用模拟栈会让你对栈的理解更深 (队列也可以模拟)
思路是:
设置两个栈,用来存储数字和计算符号
计算函数来计算优先级正确时两个相邻数字的计算结果
比较函数比较两个相邻运算符优先级
在读入操作数的各位数时,需要注意转化为十进制数。
这两种我都把他们的代码发上来供小伙伴们参考
如果找出错误,欢迎提出
这里从键盘输入的数据只适合整数 如图
如果要实现输入小数的话,会复杂一些
卖个关子,如果需要适合输入整数和小数的代码的话,欢迎关注并且私信我
首先是带结构体的栈:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef struct
{
float a[100];
int top;
}Num;
typedef struct
{
char a[100];
int top;
}Symb;
void IniStack(Num* num, Symb* symb) //初始化
{
num->top = -1;
symb->top = 0;
}
//假如读出的运算符的优先级高于运算符栈栈顶运算符的优先级,将其压入运算符栈,读取下一个符号。
假如读出的运算符优先级等于或者低于运算符栈栈顶运算符的优先级,则从操作数栈连续退出两个操作数,从运算符栈中退出一个运算符,然后做相应运算,并将运算结果压入操作数栈,不读入下一个符号。
int compare(char str) //判断符号优先级的函数
{
if (str == '!')
return 0;
if (str == '+' || str == '-')
return 1;
if (str == '/' || str == '*')
return 2;
}
float YunSuan(float a, float b, char str) //进行两个数字间的运算的函数
{
if (str == '+')
return a + b;
if (str == '-')
return a - b;
if (str == '/')
return a / b;
if (str == '*')
return a * b;
}
int main()
{
Num* num = (Num*)malloc(sizeof(Num));
Symb* symb = (Symb*)malloc(sizeof(Symb));
IniStack(num, symb);
char str[50]; //记录输入的内容
int flag = -1; //设置标志符,根据值来判断要进行的操作:将数字入数字栈 将符号入符号栈 将两个数进行运算
printf("请输入表达式:\n");
scanf_s("%s", str, 50);
float x = 0.0;
int length = strlen(str);
str[length++] = '!'; //末尾加上! 用于判断
for (int i = 0; i < length;)
{
if (str[i] <= '9' && str[i] >= '0')
{
x *= 10;
x += str[i++] - '0'; //这个if用来记录数字,比如11,在str中是分开的1,1,必须得做乘法加法运算才能表达为11
flag = 1;
}
else
{
if (flag == 1) //属于数字,得入数字栈
{
num->a[++num->top] = x;
x = 0; flag = -1; //数字入完了就到符号了,flag改成-1
}
if (compare(symb->a[symb->top]) < compare(str[i])) //根据符号优先级比较,例如:a+b*c 这里逻辑上可以看成a+(b*c)
symb->a[++symb->top] = str[i++];
else
{
float a = num->a[num->top--];
float b = num->a[num->top];
num->a[num->top] = YunSuan(b, a, symb->a[symb->top--]); //例如输入的是:a+b-c 经过这一步就变成了(a+b)-c
if (str[i] == '!' && symb->top== 0) //末尾设置!的作用就是用来判断符号栈是否已经为空 就是运算是否结束了
break;
}
}
}
printf("最终的结果为:\n%lf\n", num->a[num->top]);
system("pause");
}
接着是数组模拟栈:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
//假如读出的运算符的优先级高于运算符栈栈顶运算符的优先级,将其压入运算符栈,读取下一个符号。
假如读出的运算符优先级等于或者低于运算符栈栈顶运算符的优先级,则从操作数栈连续退出两个操作数,从运算符栈中退出一个运算符,然后做相应运算,并将运算结果压入操作数栈,不读入下一个符号。
int compare(char str) //判断符号优先级的函数
{
if (str == '!')
return 0;
if (str == '+' || str == '-')
return 1;
if (str == '/' || str == '*')
return 2;
}
float YunSuan(float a, float b, char str) //进行两个数字间的运算的函数
{
if (str == '+')
return a + b;
if (str == '-')
return a - b;
if (str == '/')
return a / b;
if (str == '*')
return a * b;
}
int main()
{
float numStack[100] = { 0.0 }; //数字栈
int numTop = -1;
char SymbStack[100] = { '!' }; //符号栈
int SymbTop = 0;
char str[50]; //记录输入的内容
int flag = -1; //设置标志符,根据值来判断要进行的操作:将数字入数字栈 将符号入符号栈 将两个数进行运算
printf("请输入表达式:\n");
scanf_s("%s", str, 50);
float x = 0.0;
int length = strlen(str);
str[length++] = '!'; //末尾加上! 用于判断
for (int i = 0; i < length;)
{
if (str[i] <= '9' && str[i] >= '0')
{
x *= 10;
x += str[i++] - '0'; //这个if用来记录数字,比如11,在str中是分开的1,1,必须得做乘法加法运算才能表达为11
flag = 1;
}
else
{
if (flag == 1) //属于数字,得入数字栈
{
numStack[++numTop] = x;
x = 0; flag = -1; //数字入完了就到符号了,flag改成-1
}
if (compare(SymbStack[SymbTop]) < compare(str[i])) //根据符号优先级比较,例如:a+b*c 这里逻辑上可以看成a+(b*c)
SymbStack[++SymbTop]=str[i++];
else
{
float a = numStack[numTop--];
float b = numStack[numTop];
numStack[numTop] = YunSuan(b, a, SymbStack[SymbTop--]); //例如输入的是:a+b-c 经过这一步就变成了(a+b)-c
if (str[i] == '!' && SymbTop == 0) //末尾设置!的作用就是用来判断符号栈是否已经为空 就是运算是否结束了
break;
}
}
}
printf("最终的结果为:\n%lf\n", numStack[numTop]);
system("pause");
}
最后可以在自己的编译器上试试啦!