[英]Parsing Parenthesis using stack template class in C++
I have a homework and its just bugging for the last 2 days, I've been doing exactly what the pseudo code and still haven't got it right yet. 我有一个作业,并且在最近的两天里一直在窃听,我一直在做伪代码,但是仍然没有正确。 For example, if I put in "mike]" or "mike]123", my program will crash, due to the stack is empty...From what I observe, the program will crash when: - The stack is empty - And there is a close parenthesis PS: with the help of us2012, I can fix the crash problem.
例如,如果我输入“ mike]”或“ mike] 123”,则由于堆栈为空,我的程序将崩溃...根据我的观察,该程序将在以下情况下崩溃:-堆栈为空-并且附上一个括号:PS:在us2012的帮助下,我可以解决崩溃问题。 However, the result is not right.
但是,结果不正确。 Instead of printing out "invalid", it outputs "valid"
而不是打印出“无效”,它输出“有效”
:( :(
Here is the pseudo code from my professor: 这是我教授的伪代码:
def parse_parenthesis(str):
stack = create a new empty stack of OpenParen objects
for i from 0 to str.size() - 1:
if str[i] is an open parenthesis
stack.push(new OpenParen(str[i]))
else if str[i] is not a close parenthesis:
# str[i] is not a parenthesis of any kind, so ignore it
continue
# otherwise str[i] must be a close parenthesis, try to
# match it with the most recent open paren, on the top
# of the stack
else if stack is empty
return false;
else if stack.peek() is of the same type as str[i]:
# close properly
stack.pop()
else
return false;
if stack is not empty
return false;
else
return true
and here is what I have so far: 这是我到目前为止所拥有的:
.cpp file .cpp文件
bool ParenMatching(const string& s, unique_ptr<string>& output)
{
unique_ptr<OpenParen> stack(new OpenParen);
bool validOpen, validClose, valid;
bool match; //haveCloseParen;
/*string unMatch = "Unmatch";
string unExpected = "Unexpected close paren";
string noError = "No Error";*/
for (size_t i = 0; i < s.length(); i++)
{
// check if its open parenthesis
validOpen = stack->IsOpenParen(s[i]);
// check if its close parenthesis
validClose = stack->IsCloseParen(s[i]);
// if there is open paren, push into the stack
if(validOpen)
stack->PushObj(s[i]);
else if(!validClose)
{
continue;
}
else if(stack->GetObj().IsEmpty())
valid = false;
else if(match = IsMatchParen(s[i], stack))
stack->PopObj();
else
valid = false;
}
if(!stack->GetObj().IsEmpty())
valid = false;
else
valid = true;
return valid;
}
bool IsMatchParen(const char c, const unique_ptr<OpenParen>& stack)
{
bool valid;
if(c == ')' && stack->PeekObj() == '(')
valid = true;
else if (c == ']' && stack->PeekObj() == '[')
valid = true;
else if (c == '}' && stack->PeekObj() == '{')
valid = true;
else if (c == '>' && stack->PeekObj() == '<')
valid = true;
else
valid = false;
return valid;
}
OpenParen.cpp OpenParen.cpp
// Check if its open paren
bool OpenParen::IsOpenParen(const char c)
{
bool isOpen;
if(c == '(' || c == '[' || c == '{' || c == '<')
isOpen = true;
else
isOpen = false;
return isOpen;
}
// check if its close paren
bool OpenParen::IsCloseParen(const char c)
{
bool isClose;
if(c == ')' || c == ']' || c == '}' || c == '>')
isClose = true;
else
isClose = false;
return isClose;
}
One important thing you should keep in mind about C++ : Multiple else if
s do not live at the same level. 关于C ++,您应该牢记一件事:
else if
s 不在同一级别,则应考虑多个else if
。 That's because else if
is not a single entity, it's an else
that belongs to the preceding statement and an if
that begins a new statement, so 那是因为
else if
不是一个单一的实体,它是一个属于前面的语句的else
,而if
是一个新语句的开始,所以
if (cond1)
a();
else if (cond 2)
b();
else if (cond 3)
c();
else
d();
is actually 实际上是
if (cond1)
a();
else {
if (cond 2)
b();
else {
if (cond 3)
c();
else
d();
}
}
Therefore, your check whether the stack is empty needs to be before the check whether the current close parens matches the top of the stack. 因此,您需要先检查堆栈是否为空, 然后再检查当前的封闭状态是否与堆栈顶部匹配。 Otherwise, your program will try to examine the top of the stack when it's empty, and that results in a crash.
否则,您的程序将尝试在栈顶为空时检查栈顶,这将导致崩溃。
Also, setting valid = false
is not the right thing to do when you find a condition that indicates a non-match. 同样,当您发现表示不匹配的条件时,将
valid = false
设置valid = false
也不是正确的选择。 The loop will still continue and can reset valid
to true
in a later iteration. 循环仍将继续,并且可以在以后的迭代中将
valid
重置为true
。 You need to immediately return false
, as you can already see in your pseudocode. 您需要立即
return false
,就像您在伪代码中已经看到的那样。
gcc 4.7.3: g++ -Wall -Wextra -std=c++0x parens.cpp gcc 4.7.3:g ++ -Wall -Wextra -std = c ++ 0x parens.cpp
#include <iostream>
#include <stack>
#include <string>
#include <vector>
bool isOpen(char c) {
return c == '(' || c == '[' || c == '{' || c == '<'; }
bool isClose(char c) {
return c == ')' || c == ']' || c == '}' || c == '>'; }
bool isMatch(char c1, char c2) {
return (c1 == '(' && c2 == ')')
|| (c1 == '[' && c2 == ']')
|| (c1 == '{' && c2 == '}')
|| (c1 == '<' && c2 == '>'); }
bool parse(const std::string& s) {
std::stack<std::string::value_type> stk;
for (std::string::size_type i = 0; i < s.size(); ++i) {
if (isOpen(s[i])) { stk.push(s[i]); }
else if (isClose(s[i])) {
if (!stk.empty() && isMatch(stk.top(), s[i])) { stk.pop(); }
else { return false; } } }
return stk.empty(); }
int main() {
std::vector<std::string> ptests = {
"", "()", "()()", "(())", "a(a)a" };
std::vector<std::string> ftests = {
"(", ")", ")(", ")()(", "))((" };
for (const auto& t : ptests) {
if (!parse(t)) { std::cout << "fail: " << t << std::endl; } }
for (const auto& t : ftests) {
if (parse(t)) { std::cout << "fail: " << t << std::endl; } }
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.