编译原理 波兰式和四元式及计算

本文介绍编译原理中的逆波兰式转换和计算方法。通过将非后缀式算术表达式转为逆波兰式,利用栈进行运算符优先级判断,最后计算逆波兰式表达式的值。实验环境为Microsoft Visual Studio 2019 Community。
摘要由CSDN通过智能技术生成

编译原理 波兰式和四元式及计算

实验目的
将非后缀式用来表示的算术表达式转换为用逆波兰式来表示的算术表达式,并计算用逆波兰式来表示的算术表达式的值。

实验环境
Microsoft Visual Studio 2019 Community

思路
转换:首先将‘#’压入栈中,依次读取输入字符串的每一个字符,如果遇到数字则继续读取下一个字符,如果还是数字则进行拼凑,直到读取到的不是数字,表明一个运算数已经读取完毕,将其加入到队列中。如果读取到的是运算符,就比较当前运算符与栈顶运算符之间的优先关系,如果栈顶运算符有优先级高,则将栈顶运算符弹出加入到队列中,重新分析当前运算符;如果栈顶运算符优先级低,则将当前读取的运算符压入栈中,继续读取下一个字符;如果两个运算符优先级相等,此时只可能是左右括号或井号相遇,则将栈顶运算符弹出栈,继续读取下一个字符;如果两个运算符没有优先级关系,则出错,直到整个输入字符串都读取完。此时队列里存储的就是完整的逆波兰式。
计算:从队列中依次读取元素,如果是数字,则压入栈中,如果是运算符,则从栈中取出两个数字,第一个数字为右操作数,第二个数字为左操作数,进行计算,计算结果再压入栈中。当队列为空时,计算结束,此时栈中只剩一个元素,就是计算结果。

对学有余力的同学,测试用的表达式事先放在文本文件中,一行存放一个表达式,同时以分号分割。同时将预期的输出结果写在另一个文本文件中,以便和输出进行对照。

运算符优先级
在这里插入图片描述

#pragma once
#include <iostream>
#include <vector>
#include <fstream>
#include <stack>
#include <string>
#include <queue>

using namespace std;

class ReversePolishNotation
{
   
	static vector<char> operators;//存放所有运算符
	static vector<vector<char>> precedenceRelationTable;//存放运算符优先关系,坐标与运算符向量中的位置对应
	static queue<string> reversePolishNotation;//存放逆波兰式的所有元素
	static fstream file;//结果写入的文件
	static int getIndex(char ch);
	static void readOperators(string fileName);
	static bool isDigital(char ch);
	static void getReversePolishNotation(string str);
	static void printReversePolishNotation();
	static void calculateReversePolishNotation();
	static double calculate(char op, double left, double right);

public:
	static void analyse(string operatorsFileName, string str);
};
#include "ReversePolishNotation.h"

vector<char> ReversePolishNotation::operators;
vector<vector<char>> ReversePolishNotation::precedenceRelationTable;
queue<string> ReversePolishNotation::reversePolishNotation;
fstream ReversePolishNotation::file("ReversePolishNotationResult.txt");

/// <summary>
/// 获取运算符在运算符向量中的下标
/// </summary>
/// <param name="ch">运算符</param>
/// <returns>下标,未找到返回-1</returns>
int ReversePolishNotation
下面是使用 C 语言实现逆波兰式的生成和计算的代码示例: ```c #include <stdio.h> #include <stdlib.h> #include <ctype.h> #include <string.h> #define MAX_STACK_SIZE 100 #define MAX_EXPR_SIZE 100 typedef struct { int top; char data[MAX_STACK_SIZE][MAX_EXPR_SIZE]; } Stack; void init_stack(Stack *s) { s->top = -1; } int is_empty(Stack *s) { return s->top == -1; } int is_full(Stack *s) { return s->top == MAX_STACK_SIZE - 1; } void push(Stack *s, char *x) { if (is_full(s)) { printf("Stack overflow.\n"); exit(1); } strcpy(s->data[++s->top], x); } char *pop(Stack *s) { if (is_empty(s)) { printf("Stack underflow.\n"); exit(1); } return s->data[s->top--]; } int is_operator(char *op) { return (strcmp(op, "+") == 0 || strcmp(op, "-") == 0 || strcmp(op, "*") == 0 || strcmp(op, "/") == 0); } int get_precedence(char *op) { if (strcmp(op, "+") == 0 || strcmp(op, "-") == 0) { return 1; } else if (strcmp(op, "*") == 0 || strcmp(op, "/") == 0) { return 2; } else { return 0; } } void infix_to_postfix(char *infix, char *postfix) { Stack op_stack; init_stack(&op_stack); char *p = infix; char *q = postfix; while (*p) { if (isdigit(*p)) { while (isdigit(*p)) { *q++ = *p++; } *q++ = ' '; } else if (is_operator(p)) { while (!is_empty(&op_stack) && get_precedence(p) <= get_precedence(op_stack.data[op_stack.top])) { strcat(q, pop(&op_stack)); strcat(q, " "); } push(&op_stack, p); p++; } else if (*p == '(') { push(&op_stack, p); p++; } else if (*p == ')') { while (op_stack.data[op_stack.top][0] != '(') { strcat(q, pop(&op_stack)); strcat(q, " "); } pop(&op_stack); p++; } else { p++; } } while (!is_empty(&op_stack)) { strcat(q, pop(&op_stack)); strcat(q, " "); } } int evaluate_postfix(char *postfix) { Stack op_stack; init_stack(&op_stack); char *p = postfix; while (*p) { if (isdigit(*p)) { int num = 0; while (isdigit(*p)) { num = num * 10 + (*p - '0'); p++; } push(&op_stack, num); } else if (is_operator(p)) { int a = atoi(pop(&op_stack)); int b = atoi(pop(&op_stack)); int result; if (strcmp(p, "+") == 0) { result = b + a; } else if (strcmp(p, "-") == 0) { result = b - a; } else if (strcmp(p, "*") == 0) { result = b * a; } else if (strcmp(p, "/") == 0) { result = b / a; } char temp[MAX_EXPR_SIZE]; sprintf(temp, "%d", result); push(&op_stack, temp); p++; } else { p++; } } return atoi(pop(&op_stack)); } int main() { char infix_expr[MAX_EXPR_SIZE]; printf("Enter an infix expression: "); scanf("%[^\n]%*c", infix_expr); char postfix_expr[MAX_EXPR_SIZE]; infix_to_postfix(infix_expr, postfix_expr); printf("Postfix expression: %s\n", postfix_expr); int result = evaluate_postfix(postfix_expr); printf("Result: %d\n", result); return 0; } ``` 这段代码中,我们首先实现了将中缀表达式转换为后缀表达式的函数 `infix_to_postfix`,然后实现了利用后缀表达式进行计算的函数 `evaluate_postfix`。在中缀转后缀的过程中,我们使用了来存储运算符,并在遍历完整个表达式后将中剩余的运算符弹出并添加到后缀表达式中。在计算后缀表达式的过程中,我们同样使用了来存储数字,并在遍历完整个表达式后将中剩余的数字弹出并进行运算。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值