此程序实现的功能为输入一个中缀表达式,将其转换为后缀表达式
并求出后缀表达式的值。
主要算法:
// 后缀表达式的计算过程
/**************************************************************/
/* 算法过程,顺序扫描后缀表达式,如果是操作数,则压入栈中,如果是操作符,则从栈中弹出两个操作数进
/* 行计算,结果再压入栈。
/* 扫描结束时,栈顶元素就是表达式的值
/**************************************************************/
// 中缀表达式转化为后缀表达式
/**************************************************************/
/* 从左至右依次扫描中缀表达式
/* 如果是操作数,直接输出,如果是 ( ,放入栈中
/* 如果是 ) ,则弹出栈顶元素并放入后缀表达式中,反复执行直到栈顶元素为 ( 位置,表示括号内操作完毕
/* 如果是操作符,则将该操作符和操作符栈顶元素比较
/* 如果大于栈顶元素的优先级时,则入栈
/* 如果小于栈顶元素的优先级时,则取出栈顶元素放入后缀表达式,并弹出该栈顶元素,反复执行直到栈顶元
素的优先级小于当前操作符优先级
/* 重复上述步骤直到遇到结束符时结束,弹出栈中所有元素并放入后缀表达式中。算法结束
/**************************************************************/
代码分三个文件。SeqStack.h SeqStack.c main.c
下方分别列出
SeqStack.h
#ifndef SEQSTACK_H
#define SEQSTACK_H
struct SeqStack
{
int MAXNUM; // 栈中最大元素个数
int t; // 栈顶位置
int *s; // 栈中元素的起始位置
};
typedef struct SeqStack *PSeqStack; // 定义顺序栈类型
typedef int DataType1; // 定义第一种元素类型为int型
typedef int DataType2; // 定义第二种元素类型为char型
PSeqStack creatEmptyStack_seq(int m); // 创建空顺序表
int isEmptyStack_seq(PSeqStack pastack); // 判断一个栈是否为空
void push_seq_int(PSeqStack pastack, DataType1 x); // 进栈(int)
void push_seq_char(PSeqStack pastack, DataType2 x); // 进栈(char)
void pop_seq(PSeqStack pastack); // 删除栈顶元素
int pop_seq_return(PSeqStack pastack); // 删除栈顶元素,同时返回栈顶元素
int top_seq(PSeqStack pastack); // 当pastack所指的栈不为空栈时,求栈顶元素的值
void print_int(PSeqStack pastack); // 输出栈内元素,不影响栈的结构(int)
void print_char(PSeqStack pastack); // 输出栈内元素,不影响栈的结构(char)
#endif
SeqStack.c
#include <stdio.h>
#include <stdlib.h>
#include "SeqStack.h"
#define TRUE 1
#define FALSE 0
// 创建空顺序栈
PSeqStack creatEmptyStack_seq(int m)
{
PSeqStack pastack = (PSeqStack)malloc(sizeof(struct SeqStack));
if (pastack != NULL)
{
pastack->s = (int*)malloc(sizeof(int)*m);
if (pastack->s)
{
pastack->MAXNUM = m;
pastack->t = -1;
return(pastack);
}
else
{
free(pastack);
return NULL;
}
}
else
{
printf("out of space.\n");
}
}
// 判断一个栈是否为空
int isEmptyStack_seq(PSeqStack pastack)
{
return (pastack->t == -1);
}
// 进栈(int)
void push_seq_int(PSeqStack pastack, DataType1 x)
{
if (pastack->t >= (pastack->MAXNUM-1))
// 检查是否栈满
{
printf("overflow! \n");
}
else
{
// 若不满,先修改栈顶变量
pastack->t++;
// 把元素x放到栈顶变量的位置中
pastack->s[pastack->t] = x;
}
}
// 进栈(char)
void push_seq_char(PSeqStack pastack, DataType2 x)
{
if (pastack->t >= (pastack->MAXNUM - 1))
// 检查是否栈满
{
printf("overflow! \n");
}
else
{
// 若不满,先修改栈顶变量
pastack->t++;
// 把元素x放到栈顶变量的位置中
pastack->s[pastack->t] = x;
}
}
// 删除栈顶元素
void pop_seq(PSeqStack pastack)
{
if (isEmptyStack_seq(pastack))
{
printf("Underflow! \n");
}
else
{
pastack->t = pastack->t-1;
}
}
// 删除栈顶元素,同时返回栈顶元素
int pop_seq_return(PSeqStack pastack)
{
int temp;
if (isEmptyStack_seq(pastack))
{
printf("Underflow!\n");
}
else
{
temp = pastack->s[pastack->t];
pastack->t--;
}
return temp;
}
// 当pastack所指的栈不为空栈时,求栈顶元素的值
int top_seq(PSeqStack pastack)
{
if (isEmptyStack_seq(pastack))
{
printf("It is empty");
return 0;
}
else
{
return (pastack->s[pastack->t]);
}
}
// 输出栈内元素,不影响栈的结构(int)
void print_int(PSeqStack pastack)
{
int temp, i;
if (isEmptyStack_seq(pastack))
{
printf("It is empty.\n");
}
printf("现在栈内元素为:");
for(i=0; i<=pastack->t; i++)
{
printf("%d ", pastack->s[i]);
}
printf("\n");
}
// 输出栈内元素,不影响栈的结构(char)
void print_char(PSeqStack pastack)
{
int temp, i;
if (isEmptyStack_seq(pastack))
{
printf("It is empty.\n");
}
printf("现在栈内元素为:");
for (i = 0; i <= pastack->t; i++)
{
printf("%c ", pastack->s[i]);
}
printf("\n");
}
main.c
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include "SeqStack.h"
#define TRUE 1
#define FALSE 0
#define MAX 30
// 定义栈和数组的最大范围
char zhong[MAX] = { '\0' }, hou[MAX] = { '\0' };
// 定义中缀表达式与后缀表达式为全局变量。
//********************************************************************
// 后缀表达式的计算过程
//********************************************************************
void HouCalculate()
{
int num1, num2, num3;
int i = 0, theValue = 0, temp = 0;
char ch;
PSeqStack stack1;
stack1 = creatEmptyStack_seq(MAX);
while (hou[i] != '#')
{
ch = hou[i];
//*******************
//调试时把这段注释去掉
//printf("\n现在处理的字符是:%c\n", ch);
//print_int(stack1);
//*******************
// 判断数字,使数字存为整体
if (isdigit(ch))
{
temp = ch - '0';
while (hou[i] != '#')
{
i++;
ch = hou[i];
// 预读一位,如果为数字则继续累加
if (isdigit(ch))
{
temp = temp * 10 + (ch - '0');
// 使数字存为一个整体
}
else
// 否则视为数字结束。
{
push_seq_int(stack1, temp);
break;
}
}
}
// 判断空格,直接跳至下一位
else if (ch == ' ')
{
i++;
}
// 判断加减乘除
else if (ch == '+' || ch == '-' || ch == '*' || ch == '/')
{
// 将第一个弹出来的数作为算术表达式中第二个操作数
num2 = pop_seq_return(stack1);
num1 = pop_seq_return(stack1);
// 根据不同标点进行不同计算
if (ch == '+')
{
num3 = num1 + num2;
}
else if (ch == '-')
{
num3 = num1 - num2;
}
else if (ch == '*')
{
num3 = num1 * num2;
}
else
{
num3 = num1 / num2;
}
// 将得到的计算结果再推回至栈中
push_seq_int(stack1, num3);
i++;
// 指针向后读一位
}
else
{
// 特殊情况备用项
if (ch != '#')
{
i++;
// 指针向后读一位
}
}
}
// 如果栈不为空,将栈中元素输出
while (!isEmptyStack_seq(stack1))
{
theValue = pop_seq_return(stack1);
}
printf("计算后缀表达式的值为: %d\n", theValue);
printf("========================\n");
}
//********************************************************************
// 中缀表达式转化为后缀表达式
//********************************************************************
void zhongToHou()
{
int num1, num2, num3;
int i = 0, j = 0, k, flag = 0;
char ch, temp;
PSeqStack stack1, stack2;
stack1 = creatEmptyStack_seq(MAX);
printf("请输入中缀表达式:(用'#'表示结束)\n");
gets(zhong);
while (zhong[i] != '#')
{
ch = zhong[i];
//*******************
//调试时把这段注释去掉
//printf("\n现在处理的字符是:%c\n", ch);
//print_char(stack1);
//*******************
// 判断数字,使数字存为整体
if (isdigit(ch))
{
hou[j++] = ch;
while (zhong[i] != '#')
{
i++;
ch = zhong[i];
// 预读一位,如果为数字则继续输出
if (isdigit(ch))
{
hou[j++] = ch;
}
else
// 否则视为数字结束。
{
hou[j++] = ' ';
break;
}
}
}
// 判断左括号
else if (ch == '(')
{
push_seq_char(stack1, ch);
// 左括号直接入栈
i++;
// 指针向后读一位
}
// 判断右括号
else if (ch == ')')
{
do
{
temp = pop_seq_return(stack1);
hou[j++] = temp;
hou[j++] = ' ';
} while (top_seq(stack1) != '(');
// 栈顶元素不为 ( 时,弹出其中元素至后缀表达式中
if (top_seq(stack1) == '(')
{
pop_seq(stack1);
// 将栈中的 ( 弹出
}
i++;
// 指针向后读一位
}
// 判断加号和减号
else if (ch == '+' || ch == '-')
{
if (isEmptyStack_seq(stack1))
// 如果栈为空,直接将符号压入。
{
push_seq_char(stack1, ch);
}
else
{
while (1)
{
if (isEmptyStack_seq(stack1))
// 考虑在弹出几个元素后,栈空的情况。所以要放在if-else结构的第一位。
{
push_seq_char(stack1, ch);
break;
}
else if (top_seq(stack1) == '+' || top_seq(stack1) == '-' || top_seq(stack1) == '*' || top_seq(stack1) == '/')
// 如果栈顶元素优先级比ch高级或与ch平级,弹出栈顶元素直到进入其他条件跳出死循环
{
temp = pop_seq_return(stack1);
hou[j++] = temp;
hou[j++] = ' ';
}
else
{
push_seq_char(stack1, ch);
break;
}
}
}
i++;
// 指针向后读一位
}
// 判断乘号和除号
else if (ch == '*' || ch == '/')
{
if (isEmptyStack_seq(stack1))
// 如果栈为空,直接将符号压入。
{
push_seq_char(stack1, ch);
}
else
{
temp = top_seq(stack1);
while (1)
{
if (isEmptyStack_seq(stack1))
// 考虑在弹出几个元素后,栈空的情况。
{
push_seq_char(stack1, ch);
break;
}
else if (top_seq(stack1) == '*' || top_seq(stack1) == '/')
// 如果栈顶元素优先级比ch高级或与ch平级,弹出栈顶元素直到进入其他条件跳出死循环
{
temp = pop_seq_return(stack1);
hou[j++] = temp;
hou[j++] = ' ';
}
else
{
push_seq_char(stack1, ch);
break;
}
}
}
i++;
// 指针向后读一位
}
else
{
// 此为误输入的情况,报错后退出程序,以保证后缀表达式的值能正确计算
if (ch != '#')
{
printf("您的输入中包含不合法字符。\n");
exit(0);
}
}
}
// 如果栈不为空,将栈中元素输出
while (!isEmptyStack_seq(stack1))
{
hou[j++] = pop_seq_return(stack1);
hou[j++] = ' ';
}
// 输出转换后的后缀表达式
printf("========================\n");
printf("转换后的后缀表达式为:\n");
printf("%s\n", hou);
printf("========================\n");
// 为后缀表达式设置终止符
i = 0;
while (hou[i] != NULL)
{
i++;
}
hou[i] = '#';
}
int main()
{
zhongToHou();
HouCalculate();
return 0;
}
ps不知道为啥代码段里面的注释都没能变色显示。凑合着看一下。
部分运行结果截图: