编译原理实践第1次课-初步实验
- 编程环境
Python 2.7
- 中缀表达式转后缀表达式
实现中缀表达式转化为后缀表达式,如: 9 - 5 + 2 转化为 9 5 - 2 +
中缀表达式转后缀表达式的规则:
1.遇到操作数,直接输出;
2.栈为空时,遇到运算符,入栈;
3.遇到左括号,将其入栈;
4.遇到右括号,执行出栈操作,并将出栈的元素输出,直到弹出栈的是左括号,左括号不输出; (3) 3
5.遇到其他运算符’+”-”*”/’时,弹出所有优先级大于或等于该运算符的栈顶元素,然后将该运算符入栈; 1+2+3 左结合
6.最终将栈中的元素依次出栈,输出。
经过上面的步骤,得到的输出既是转换得到的后缀表达式。
# 定义运算符优先级
priority = {'+':1, '-':1, '*':2, '/':2, '^':3}
def infix_to_postfix(expression):
# 建立一个栈和列表以存储后缀表达式
stack = []
postfix_lst = []
# 对中缀表达式的每个字符进行循环
for char in expression:
# 如果字符是操作数,直接添加到后缀表达式的列表中
if char.isalnum():
postfix_lst.append(char)
# 如果字符是左括号,直接压栈
elif char == '(':
stack.append(char)
# 如果字符是右括号,弹出栈中左括号之前的操作符,加入到后缀表达式的列表中
elif char == ')':
while stack[-1] != '(':
postfix_lst.append(stack.pop())
stack.pop()
# 如果字符是运算符,比较栈顶运算符与当前运算符的优先级,决定是否弹出运算符加入到后缀表达式的列表中
elif char in priority:
while (len(stack) > 0 and stack[-1] != '(' and priority[stack[-1]] >= priority[char]):
postfix_lst.append(stack.pop())
stack.append(char)
# 将栈中剩余的元素弹出,加到后缀表达式的列表中
while len(stack) > 0:
postfix_lst.append(stack.pop())
return ''.join(postfix_lst)
# 测试
print(infix_to_postfix("3+(6*7-2)+2*3"))
- 正则表达式
3.1验证
- 验证jpg,jpeg,gif,bmp格式的文件名,大小写均可?
import re
def validate_filename(filename):
pattern = re.compile(r'\w+\.(jpg|jpeg|gif|bmp)', re.IGNORECASE)
if re.match(pattern, filename):
return True
else:
return False
# 测试
filename1 = 'test.jpg'
filename2 = 'sample.jpeg'
filename3 = 'picture.gif'
filename4 = 'image.bmp'
filename5 = 'file.doc'
print(validate_filename(filename1)) # True
print(validate_filename(filename2)) # True
print(validate_filename(filename3)) # True
print(validate_filename(filename4)) # True
print(validate_filename(filename5)) # False
首先定义了一个名为`validate_filename()`的函数,用于验证文件名是否符合指定的格式。
正则表达式`r'^\w+\.(jpg|jpeg|gif|bmp)$'`用于匹配文件名。其中:
^表示字符串的开始位置;
\w+表示匹配一个或多个字母、数字或下划线;
\.表示匹配一个实际的点(需要转义);
(jpg|jpeg|gif|bmp)`表示匹配指定的文件格式名称;
$表示字符串的结束位置。
如果文件名符合指定的格式,返回True;否则返回False。
最后,分别测试了符合及不符合格式要求的5个文件名,并输出相应的验证结果。
- 匹配日期格式:13/5/2021
import re
date = "13/5/2012"
pattern = r"^(0?[1-9]|[12][0-9]|3[01])\/(0?[1-9]|1[012])\/\d{4}$"
result = re.match(pattern, date)
if result:
print("日期格式正确")
else:
print("日期格式错误")
^ 表示匹配字符串开头
$ 表示匹配字符串结尾
\d 用于匹配数字
[01]?[0-9] 匹配 0-19
- |[0-9] 匹配 10-29
3[01]|[12][0-9] 匹配 10-31
(0?[1-9]|1[012]) 匹配 01-09 或 10-12
\d{4} 匹配四位数字
- 电话号码(区号提取):(0579) 68078800-6852
import re
phone_num = '(0579) 68078800-6852'
area_code = re.search(r'\((.*?)\)', phone_num).group(1)
print(area_code)
定义了一个电话号码字符串变量`phone_num`,其中包含区号和电话号码。
然后使用`re.search()`函数进行正则表达式的匹配和提取。
正则表达式`r'\((.*?)\)'`用于匹配括号中的内容。其中,`\(`和`\)`表示匹配左右括号,`(.*?)`表示匹配括号内的任意字符(非贪婪模式)。最后使用`group(1)`方法提取第一个匹配的括号内容,即区号。
最后输出区号。
3.2提取
(1)提取list.html中的所有超链接
(2)提取content中的标题与正文
参考示例,提取浙师大首页网站的新闻标题和超链接
#! /usr/bin/env python
#coding=utf-8
import re
p=re.compile(r'<.*?http://news.zjnu.edu.cn/2023/04.*?>(.*?)</a></div>')
# read html file
html_content=open('2.html','rb').read()
# regex match
matches=p.findall(html_content)
print len(matches)
for m in matches:
print m
附录
代码 | 说明 |
. | 匹配除换行符以外的任意字符 |
\w | 匹配字母或数字或下划线或汉字 |
\s | 匹配任意的空白符 |
\d | 匹配数字 |
\b | 匹配单词的开始或结束 |
^ | 匹配字符串的开始 |
$ | 匹配字符串的结束 |
代码/语法 | 说明 |
* | 重复零次或更多次 |
+ | 重复一次或更多次 |
? | 重复零次或一次 |
{n} | 重复n次 |
{n,} | 重复n次或更多次 |
{n,m} | 重复n到m次 |
- 完成实验报告,并提交。