我尝试创建一个程序,该程序使用堆栈来检查HTML文件是否具有正确数量的结束标记和结束标记。
我使用的堆栈类非常基本:
class Stack:
def __init__(self):
self.items = []
def isEmpty(self):
return self.items == []
def push(self, item):
self.items.append(item)
def pop(self):
return self.items.pop()
def peek(self):
return self.items[len(self.items)-1]
def size(self):
return len(self.items)
到目前为止,我为HTML检查程序创建的代码是:
def htmlChecker(html):
htmlStack = Stack()
htmlOpen = ['<html>','<head>','<title>','<body>',\
'<p>','<b>','<u>','<div>','<span>']
htmlClose = ['</html>','</head>','</title>','</body>',\
'</p>','</b>','</u>','</div>','</span>']
htmlList = html.split()
for opener in htmlList:
if opener in htmlOpen:
htmlStack.push(opener)
for closer in htmlClose:
if htmlStack.pop() == closer.replace('/',''):
return True
else:
return False
我知道让两个列表中的开启者和关闭者可能效率不高,但我对代码非常基本以了解问题。
如果我插入'<html> <head> </head> <body> </body> </html>'
我应该获得True
的回复,但是当我输入'<html> <head> </head> <body> </body>'
时,我还是应该返回True
得到False
。
我已经使用for循环和缩进玩了很多,我仍然无法弄清楚为什么它不会因错误的脚本而返回False
。
答案 0 :(得分:0)
第一个结束标记后立即终止该功能:
for opener in htmlList:
if opener in htmlOpen:
htmlStack.push(opener)
for closer in htmlClose:
if htmlStack.pop() == closer.replace('/',''):
return True
else:
return False
无论最后if
条件是True
还是False
,您返回以及该程序。您应该仅return False
。如果情况确实存在,您应该继续前进,直到下一个令牌中的一个失败,或者您到达终点,在这种情况下您应该返回True
。所以:
for opener in htmlList:
if opener in htmlOpen:
htmlStack.push(opener)
for closer in htmlClose:
if htmlStack.isEmpty() or htmlStack.pop() != closer.replace('/',''):
return False
return True
请注意,您不必编译HTML标记本身,您可以使用正则表达式来简化生活。但这可能值得另一个问题。
答案 1 :(得分:0)
除了早期退出,你可以做一个比嵌套for
循环更好的方法,只需检查htmlClose
中的入站值,其中包含来自堆栈顶部的pop
{ :
if len(htmlList) % 2:
return False
for v in htmlList:
if v in htmlOpen:
htmlStack.push(v)
else:
if htmlStack.isEmpty():
return False
else:
v2 = htmlStack.pop()
if v.replace('/', '') != v2:
return False
return True
如果显示关闭标记时堆栈isEmpty
,则没有开放标记(您可以修改代码并立即pop
使用try-except
抓住特殊情况并返回)。如果从末尾弹出的值与结束标记不匹配,则表示您没有余额。