摘要:(1)后缀表达式是给计算机看的,有些情况下我们需要将它转换成中缀表达式。
(2)这是一个重构的过程。
【1】首先考虑一些细节问题。作为表达式输入时要用空格将数字分开(1 2+),不能是(12+),因为数字没有用操作符隔开。那么在读入到的时候就要将空格给去掉,然后放入一个链表之中(放入数组不能区分间隔)。
【2】其次要考虑小数点的存在要将字符串(“12.35”)转换成数字(12.35);
【3】然后是基本的思路:首先遍历链表,直到遇到一个操作符号,然后找到该操作符号前面的两个节点(temp1,temp2),进行分类,如果两个都是数字,就是temp2 (符号)temp1的顺序保留,如果有一个或两个是操作符号,则按temp2,temp1的顺序放入一个字符串数组S里。
【4】同时注意后来的表达式转换后在S中的位置,需要判断应该插入在那个位置。执行代码:(strcpy(&S[strlen(S)],temp1->A);)
代码如下:
// chap3_计算后缀表达式.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include "malloc.h"
#include "math.h"
#include "stdlib.h"
#include "string.h"
typedef struct Node *PtrtoNode;
#define operation 1
#define num 2
#define Expression 3
#define empty 0
#define Power 80
#define Multiply 50
#define Divide 50
#define Plus 40
#define Subtract 40
int mark = 0;
struct Node
{
int Type;
char symbol[1];
char A[100];
double number;
PtrtoNode Next;
};
typedef PtrtoNode List;
List Create(int N)//用来创建一个单向链表
{
List P,L ;
L = (List)malloc(sizeof( struct Node));
P = L;
L->Type = empty;
for (int i = 1;i<=N;i++)
{
P->Next = (List)malloc(sizeof( struct Node));
P = P->Next;
P->Type = empty;
for(int i = 0;i<=99;i++)
P->A[i] = '\0';
}
P->Next = NULL;
return L;
}
double GetDigit(char *A)
{
double number = 0;
int i = 1;
while(*A<='9'&&*A>='0')
number = number*10 + *(A++) + (0-'0');
if (*A == '.'){
A++;
while(*A<='9'&&*A>='0')
number += pow((long double)10,-(i++))*(*(A++)+(0-'0'));
}
return number;
}
List FindPrevious(List L,List X)//找到X的前一个元素,也可能返回最后一个
{
List P;
P = L;
while(P->Next!=NULL&&P->Next!=X)
P = P->Next;
return P;
}
void Delete(List L,List P)
{
List temp;
if (L->Next == NULL){
puts("cannot delete an empty list");
return;
}
temp = FindPrevious(L,P);
temp->Next = P->Next;
free(P);
}
void Fix(char *S)//用来添加括号
{
int x = strlen( S);
while(x)
{
S[x] = S[x-1];
x--;
}
//x = 0
S[0] = '(';
S[strlen(S)] = ')';
}
List Convert(List L,List P,int * Last,int * This)
{
char * S = P->A;
double a,b;
List temp1,temp2;
int i = 0;
switch(P->symbol[0])
{
case '+': *This = Plus;
break;
case '-': *This = Subtract;
break;
case '*': *This = Multiply;
break;
case '/': *This = Divide;
break;
case '^':*This= Power;
break;
}
if (*This > *Last)
{
temp1 = FindPrevious(L,P);
temp2 = FindPrevious(L,temp1);
//判断是否给原来的表达式加括号
if (temp1->Type == Expression){
S = temp1->A;
Fix(S);
}
if (temp2->Type == Expression)
{
S = temp2->A;
Fix(S);
}
}
S = P->A ;
temp1 = FindPrevious(L,P);
temp2 = FindPrevious(L,temp1);
if(temp2->Type == Expression)
{
strcpy(S,temp2->A);
}
else
{
sprintf(S,"%f",temp2->number);
}
S[strlen(S)] = P->symbol[0];//输出操作符号
if(temp1->Type == Expression)
{
strcpy(&S[strlen(S)],temp1->A);
}
else
{
sprintf(&S[strlen(S)],"%f",temp1->number);
}
*Last = *This;
P->Type = Expression;
Delete(L,temp1);
temp1 = P->Next;
Delete(L,temp2);
P = temp1;
return P;
}
int _tmain(int argc, _TCHAR* argv[])
{
int i = 0;
int Last = 100,This;
char A[100] = {0};
char S[100] = {0};
List L = Create(20);
List P = L->Next;
puts("please input the expression: ");
gets(A);
while(A[i]!='\0')
{
while(A[i] == ' ')
//去掉间隔的空格
i++;
if(A[i]>='0'&&A[i]<='9')
{
P->Type = num;
P->number = GetDigit(&A[i]);
while(A[i]>='0'&&A[i]<='9'||A[i] == '.')
//直到下一个符号 operation or ' '
i++;
P = P->Next;
continue;
}
//处理操作符号
P->Type = operation;
P->symbol[0] = A[i];
i++;
while(A[i] == ' ' )//去掉空格或者
i++;
P = P->Next;
}
P = L->Next;
while(P->Type!= empty)
{
while(P->Type == num)
P = P->Next;
if(P->Type == operation)
P = Convert(L, P,&Last,&This); //p进入时指向运算符号
}
puts(L->Next->A);
return 0;
}
运行: