3-3-2 堆栈 求前缀表达式的值 (25分)
算术表达式有前缀表示法、中缀表示法和后缀表示法等形式。前缀表达式指二元运算符位于两个运算数之前,例如2+3*(7-4)+8/4的前缀表达式是:
++ 2 * 3 - 7 4 / 8 4。请设计程序计算前缀表达式的结果值。
输入格式:
输入在一行内给出不超过30个字符的前缀表达式,只包含+、-、*、/以及运算数,不同对象(运算数、运算符号)之间以空格分隔。
输出格式:
输出前缀表达式的运算结果,保留小数点后1位,或错误信息ERROR。
输入样例:
++ 2 * 3 - 7 4 / 8 4
输出样例:
13.0
- 下面这个代码还有一个测试点没过
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<ctype.h>
#include<math.h>
#define MAXN 100
typedef struct SNode* PtrToSNode;
#define ERROR 1e9
typedef enum{false,true} bool;//vs这个不用加
struct SNode {
double data;
PtrToSNode next;
};
typedef PtrToSNode Stack;
//Stack CreateStack();//创造指向链表的头结点
bool IsEmpty(Stack S);//判断表是否为空
bool Push(Stack S, double X);//入栈
double Pop(Stack S);//出栈
double PostfixExp(Stack S, char* str);//计算
double reverse(int n);//因为是从后忘前读 所以当一串字符串为72 读进去就是27 所以写了一个reverse函数把它再倒过来 但是当字符串是30时 读进去的数就是3 再怎么颠倒也是3
//(这就是那一个测试点出错的问题)
int main()
{
Stack S;
S = (Stack)malloc(sizeof(struct SNode));
S->next = NULL;
char str[MAXN];
double f;//f为计算结果(double型)
gets_s(str);
f = PostfixExp(S, str);
if (f != ERROR)
printf("%.1f", f);
else printf("ERROR");
return 0;
}
//Stack CreateStack()//创造链表 头节点(只指向链表,并不存储数据)
//{
// //创建一个堆栈的头节点,返回该结点指针
// Stack S;
// S = (Stack)malloc(sizeof(struct SNode));
// S->next = NULL;
// return S;
//}
bool IsEmpty(Stack S)//判断链表是否为空
{
return (S->next == NULL);//如果为空返回true,因为当指针为空 S->next指向为空,就是头指针什么都不指向,否则返回false
}
bool Push(Stack S, double X)//入栈函数 从链表头入栈(头插法)(后入再前)
{
PtrToSNode TmpCell;
TmpCell = (PtrToSNode)malloc(sizeof(struct SNode));
TmpCell->data = X;//头插法
TmpCell->next = S->next;
S->next = TmpCell;
return true;
}
double Pop(Stack S)//出栈
{
PtrToSNode FirstCell;//栈顶元素出栈
double TopElem;
if (IsEmpty(S))//判断是否为空链表
{
return ERROR;
}
else
{
FirstCell = S->next;
TopElem = FirstCell->data;
S->next = FirstCell->next;//S只是一个头指针,它并不含有值,只是指向链表(栈)的头节点
//当出栈的时候,就是将头结点右移(S->next指向原本s->next的下一个),最后再将原先的头结点释放
free(FirstCell);
return TopElem;//出栈并将出栈元素返回
}
}
double PostfixExp(Stack S, char* str)
{
int n = strlen(str);
n--;
double Op1, Op2;
for (; n >= 0; n--)
{//因为是从字符串尾部输入的,所以如果有小数先输入的试小数点后面的数
if (str[n] >= '0' && str[n] <= '9' || str[n] == '.')
{
double a = 0;
int flag = 0;//判断是否含有小数 如果有小数
//flag=1,a为小数部分,b为整数部分,否则a为整数部分
int dou = 0;
while (str[n] >= '0' && str[n] <= '9')
{
a = a * 10 + str[n] - '0';
dou++;
n--;
}
a = reverse((int)a);//刚开始没写reverse 如果字符串是72 读入就是27 错了
if (str[n] == '.')
{
flag = 1;
n--;
}
double b = 0;
if (flag == 1) {
while (str[n] >= '0' && str[n] <= '9')
{
b = b * 10 + str[n] - '0';
n--;
}
b = reverse((int)b);
}
double sum = 0;
if (flag == 0) sum = a;
else sum = b + a / pow(10, dou);
if (str[n] == ' '||n==-1) Push(S, sum);//n==-1这个不能丢 就是只有数字没有正负号和运算符的时候能入栈 丢了的话字符串27入不了栈
else if (str[n] == '-'||str[n]=='+') {
if(str[n]=='-') sum = -sum;
Push(S, sum);
}
}
else if (str[n] == '+' || str[n] == '-' || str[n] == '*' || str[n] == '/')
{
if (IsEmpty(S)!=ERROR) Op1 = Pop(S);//前缀从右向左入栈,从左向右出栈
if (IsEmpty(S)!=ERROR) Op2 = Pop(S);
double sum = 0;
switch (str[n])
{
case '+':
sum = Op1 + Op2;
Push(S, sum);
break;
case '-':
sum = Op1 - Op2;
Push(S, sum);
break;
case '*':
sum = Op1 * Op2;
Push(S, sum);
break;
case '/':
if (Op2 != 0.0)
{
sum = Op1 / Op2;
Push(S,sum);
break;
}
else return ERROR;
}
}
}
double sum = 0;
if (!IsEmpty(S))
sum = Pop(S);
free(S);
return sum;
}
double reverse(int n)
{
double sum = 0;
while (n)
{
sum = sum * 10 + n % 10;
n = n / 10;
}
return sum;
}

下面这个代码就没问题了:
在计算的那个函数那块修改一下 就是把字符串(倒读)转换成数字这块修改一下
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<ctype.h>
#include<math.h>
#define MAXN 100
typedef struct SNode* PtrToSNode;
#define ERROR 1e9
typedef enum{false,true} bool;
struct SNode {
double data;
PtrToSNode next;
};
typedef PtrToSNode Stack;
//Stack CreateStack();//创造指向链表的头结点
bool IsEmpty(Stack S);//判断表是否为空
bool Push(Stack S, double X);//入栈
double Pop(Stack S);//出栈
double PostfixExp(Stack S, char* str);//计算
double reverse(int n);
int main()
{
Stack S;
S = (Stack)malloc(sizeof(struct SNode));
//S= NULL;
S->next = NULL;
char str[MAXN];
double f;//f为计算结果(double型)
gets(str);
f = PostfixExp(S, str);
if (f != ERROR)
printf("%.1f", f);
else printf("ERROR");
return 0;
}
//Stack CreateStack()//创造链表 头节点(只指向链表,并不存储数据)
//{
// //创建一个堆栈的头节点,返回该结点指针
// Stack S;
// S = (Stack)malloc(sizeof(struct SNode));
// S->next = NULL;
// return S;
//}
bool IsEmpty(Stack S)//判断链表是否为空
{
return (S->next == NULL);//如果为空返回true,因为当指针为空 S->next指向为空,就是头指针什么都不指向,否则返回false
}
bool Push(Stack S, double X)//入栈函数 从链表头入栈(头插法)(后入再前)
{
PtrToSNode TmpCell;
TmpCell = (PtrToSNode)malloc(sizeof(struct SNode));
TmpCell->data = X;//头插法
TmpCell->next = S->next;
S->next = TmpCell;
return true;
}
double Pop(Stack S)//出栈
{
PtrToSNode FirstCell;//栈顶元素出栈
double TopElem;
if (IsEmpty(S))//判断是否为空链表
{
return ERROR;
}
else
{
FirstCell = S->next;
TopElem = FirstCell->data;
S->next = FirstCell->next;//S只是一个头指针,它并不含有值,只是指向链表(栈)的头节点
//当出栈的时候,就是将头结点右移(S->next指向原本s->next的下一个),最后再将原先的头结点释放
free(FirstCell);
return TopElem;//出栈并将出栈元素返回
}
}
double PostfixExp(Stack S, char* str)
{
int n = strlen(str);
n--;
double Op1, Op2;
for (; n >= 0; n--)
{//因为是从字符串尾部输入的,所以如果有小数先输入的试小数点后面的数
if (str[n] >= '0' && str[n] <= '9' || str[n] == '.')
{
double a = 0;
int flag = 0;//判断是否含有小数 如果有小数
//flag=1,a为小数部分,b为整数部分,否则a为整数部分
int dou = 0;
while (str[n] >= '0' && str[n] <= '9')
{
a = a + (str[n] - '0') * pow(10, dou);//这块这样写就没问题了
dou++;
n--;
}
//a = reverse((int)a);
if (str[n] == '.')
{
flag = 1;
n--;
}
double b = 0;
if (flag == 1) {
int s = 0;
while (str[n] >= '0' && str[n] <= '9')
{
b = b + (str[n] - '0') * pow(10, s);
s++;
n--;
}
//b = reverse((int)b);
}
double sum = 0;
if (flag == 0) sum = a;
else sum = b + a / pow(10, dou);
if (str[n] == ' ' || n == -1) Push(S, sum);
else if (str[n] == '-' || str[n] == '+') {
if (str[n] == '-') sum = -sum;
Push(S, sum);
}
}
else if (str[n] == '+' || str[n] == '-' || str[n] == '*' || str[n] == '/')
{
if (IsEmpty(S) != ERROR) Op1 = Pop(S);//前缀从右向左入栈,从左向右出栈
//else return ERROR;
if (IsEmpty(S) != ERROR) Op2 = Pop(S);
//else return ERROR;
double sum = 0;
switch (str[n])
{
case '+':
sum = Op1 + Op2;
Push(S, sum);
break;
case '-':
sum = Op1 - Op2;
Push(S, sum);
break;
case '*':
sum = Op1 * Op2;
Push(S, sum);
break;
case '/':
if (Op2 != 0.0)
{
sum = Op1 / Op2;
Push(S, sum);
break;
}
else return ERROR;
}
}
}
double sum = 0;
if (!IsEmpty(S))
sum = Pop(S);
free(S);
return sum;
}
double reverse(int n)
{
double sum = 0;
while (n)
{
sum = sum * 10 + n % 10;
n = n / 10;
}
return sum;
}
浙公网安备 33010602011771号