分析:由于要求用C语言编写,栈的操作我不知道C里面有没有库函数,所以直接将书上代码打下来单独用了一个头文件,代码如下:
PS:由于定义栈的存储类型不可变,除非再定义另外一个栈,比较麻烦,我将运算符也存在double栈中,添加一个运算符(char)转double子函数对其处理,±*/等分别对应一个数。
创建一个SeqStack.h头文件存顺序栈的操作,代码如下:
#ifndef _SEQSTACK_H_
#define _SEQSTACK_H_
#include <stdio.h>
#include <stdlib.h>
#define MAXSIZE 100
#define DataType double
typedef struct
{ /*顺序栈*/
DataType data[MAXSIZE];
int top;
}SeqStack, *PSeqStack;
PSeqStack Init_SeqStack()
{ /*1.初始化空栈*/
PSeqStack S = (PSeqStack)malloc(sizeof(SeqStack));
if(S) S->top = -1;
return S;
}
int Empty_SeqStack(PSeqStack S)
{ /*2.判栈空*/
return (S->top == -1);
}
int Push_SeqStack(PSeqStack S, DataType x)
{ /*3.入栈*/
if(S->top == MAXSIZE -1) return 0; //栈满不能插入
else
{
S->data[++S->top] = x;
return 1;
}
}
int Pop_SeqStack(PSeqStack S, DataType *x)
{ /*4.出栈*/
if(Empty_SeqStack(S)) return 0; //栈空不能出栈
else
{
*x = S->data[S->top]; //用指针的方式取出栈中元素给x
S->top--;
return 1;
}
}
int GetTop_SeqStack(PSeqStack S, DataType *x)
{ /*5.取栈顶元素*/
if(Empty_SeqStack(S)) return 0; //栈空
else
{
*x = S->data[S->top]; //用指针的方式将栈顶元素存入x中
return 1;
}
}
void Destroy_SeqStack(PSeqStack *S)
{ /*6.销毁栈*/
if(*S) free(*S);
*S = NULL;
return;
}
#endif
创建一个priority.h头文件,代码如下:
#ifndef _PRIORITY_H_
#define _PRIORITY_H_
//求运算符优先级
int priority(double o)
{
switch((int)o)
{
case 0: return 0;
case 5: return 1;
case 1:
case 2: return 2;
case 3:
case 4: return 3;
}
}
//判断是否为运算符
int isOperator(char c)
{
if(c == '+' || c == '-' || c == '*' || c == '/') return 1;
else if(c == '(') return 2;
else if(c == ')') return 3;
else return 0;
}
//判断是否为数字
int isNum(char c)
{
if(c >= '0' && c <= '9') return 1;
else return 0;
}
//运算符转double
double operatorToDouble(char c)
{
switch(c)
{
case '+': return 1;
case '-': return 2;
case '*': return 3;
case '/': return 4;
case '(': return 5;
default: return 0;
}
}
#endif
创建一个main.c文件,代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>
#include "SeqStack.h"
#include "priority.h"
PSeqStack num; //数字栈
PSeqStack op; //字符栈
char s[512], *ps = s; //输入的字符串和遍历该字符串的指针
double x, o, y; //x,y:两数字, o:运算符的double形式
int flag = 0; //0:当前运算不在括号内, 1:当前运算在括号内
//字符串转double
void doNum()
{
char numTemp[32]; //字符串转double的临时字符型数组
int i; //下标,索引,遍历介质
memset(numTemp, 0, sizeof(numTemp));
i = 0;
if(*ps == '-') numTemp[i++] = *(ps++);
while(isNum(*ps))
{
numTemp[i] = *ps;
i++, ps++;
}
if(*ps == '.')
{
numTemp[i++] = '.';
ps++;
while(isNum(*ps)) //小数部分
{
numTemp[i] = *ps;
i++, ps++;
}
}
Push_SeqStack(num, atof(numTemp));
}
void doOperator()
{
Pop_SeqStack(num, &y);
Pop_SeqStack(num, &x);
Pop_SeqStack(op, &o);
switch((int)o)
{
case 1: Push_SeqStack(num, x+y); break;
case 2: Push_SeqStack(num, x-y); break;
case 3: Push_SeqStack(num, x*y); break;
case 4: Push_SeqStack(num, x/y); break;
}
}
int main()
{
num = Init_SeqStack();
op = Init_SeqStack();
memset(s, 0, sizeof(s));
gets(s);
int leftKH = 0, rightKH = 0;
while(*ps)
{
if(*ps == '(') leftKH++;
else if(*ps == ')') rightKH++;
ps++;
}
if(leftKH != rightKH)
{
puts("括号不匹配!\n");
return EOF;
}
ps = s;
while(*ps) //解析字符串并入栈
{
if(isNum(*ps) || *(ps) == '-' && (isOperator(*(ps-1)) == 1 || isOperator(*(ps-1)) == 2 || !*(ps-1))) //如果是数字或者负数
{
doNum();
ps--;
}
else if(isOperator(*ps)) //如果是运算符
{
if(GetTop_SeqStack(op, &o)) //如果运算符栈非空,读栈顶元素并进行操作
{
if(*ps == '(') Push_SeqStack(op, operatorToDouble(*ps));
else if(*ps == ')') //如果遇到')',将()里的元算符取出进行计算
{
while((int)o != 5)
{
doOperator();
GetTop_SeqStack(op, &o);
}
Pop_SeqStack(op, &o);
}
else if(priority(operatorToDouble(*ps)) > priority(o)) //如果当前运算符优先级大于栈顶运算符优先级
{
Push_SeqStack(op, operatorToDouble(*ps)); //直接入栈
}
else
{
while(!Empty_SeqStack(op) && priority(operatorToDouble(*ps)) <= priority(o)) //如果栈顶运算符的优先级大于当前运算符,将栈顶元素进行计算
{
doOperator(); //直到符合条件
GetTop_SeqStack(op, &o);
}
Push_SeqStack(op, operatorToDouble(*ps));
}
}
else Push_SeqStack(op, operatorToDouble(*ps));
}
else
{
printf("表达式错误!\n");
return EOF;
}
ps++;
}
while(!Empty_SeqStack(op))
doOperator();
GetTop_SeqStack(num, &x);
printf("结果为:%lf\n", x);
system("pause");
return 0;
}