当我遇到这种情况时,我正在使用堆栈实现来解决平衡括号问题,在这种情况下,我正在使用'else-if'语句检查右括号,但是输出与预期的不同。将所有的“ else-if”语句更改为普通的“ if”语句后,代码可以正常工作。 我想知道为什么会这样,因为我一直认为使用'else-if'语句是更好的做法。
int main(){
stack<char> bracks;
string s; // input string: {a+(b+c-[e-f])*d}
cin >> s;
for(int i = 0; i < s.size(); i++){
if(s[i] == '{' || s[i] == '(' || s[i] == '[') bracks.push(s[i]);
else if(s[i] == '}')
if(bracks.top() == '{') bracks.pop();
else if(s[i] == ')')
if(bracks.top() == '(') bracks.pop();
else if(s[i] == ']')
if(bracks.top() == '[') bracks.pop();
}
if(bracks.empty()) cout << "Balanced\n";
else cout << "Unbalanced\n";
}
输入字符串“ {a +(b + c- [e-f])* d}”的预期输出为“平衡”,但输出为“不平衡”。
答案 0 :(得分:4)
使用'else-if'语句是一种更好的做法。
if
和else-if
是不同的事物,它们在不同的情况下使用。不论好坏都没有。
考虑该代码:
if (c1) if (c2) a else b
编译器看到它的方式是:
if (c1) {
if (c2)
a
else
b
}
原因是else
始终属于最里面的if
。
在您的情况下,您的情况意味着:
if(s[i] == '{' || s[i] == '(' || s[i] == '[') {
bracks.push(s[i]);
} else if(s[i] == '}') {
if(bracks.top() == '{') {
bracks.pop();
} else if(s[i] == ')') {
if(bracks.top() == '(') {
bracks.pop();
} else if(s[i] == ']') {
if(bracks.top() == '[') {
bracks.pop();
}
}
}
}
您的缩进显示这不是您想要的。
答案 1 :(得分:2)
您需要一些其他的花括号,以便else
适用于正确的if
:
for(int i = 0; i < s.size(); i++){
if(s[i] == '{' || s[i] == '(' || s[i] == '[') bracks.push(s[i]);
else if(s[i] == '}')
{
if(bracks.top() == '{') bracks.pop();
}
else if(s[i] == ')')
{
if(bracks.top() == '(') bracks.pop();
}
else if(s[i] == ']')
{
if(bracks.top() == '[') bracks.pop();
}
}
正确缩进代码将对此有所帮助。
答案 2 :(得分:1)
您的问题是您的for
循环中的代码,我在这里逐字引用
if(s[i] == '{' || s[i] == '(' || s[i] == '[') bracks.push(s[i]); else if(s[i] == '}') if(bracks.top() == '{') bracks.pop(); else if(s[i] == ')') if(bracks.top() == '(') bracks.pop(); else if(s[i] == ']') if(bracks.top() == '[') bracks.pop();
的缩进暗示(对于人类读者)特定的顺序。但是,编译器将忽略缩进。如果我们使用缩进(以及几个额外的换行符)使代码在编译器中看起来像我们一样,我们将得到
if(s[i] == '{' || s[i] == '(' || s[i] == '[')
bracks.push(s[i]);
else if(s[i] == '}')
if(bracks.top() == '{')
bracks.pop();
else if(s[i] == ')')
if(bracks.top() == '(')
bracks.pop();
else if(s[i] == ']')
if(bracks.top() == '[')
bracks.pop();
因此,我们实际上有三个嵌套级别,其中您的缩进仅暗示一个。事实是,由于编译器(大多数情况下)会忽略空格,因此就编译器而言,这两个代码示例是相同的。
由于人类会解释空白,而编译器会忽略它,因此通常被认为是良好实践的准则还涉及添加{}
以确保以合理的方式对代码进行逻辑分组(希望)是指人类和编译器将解释代码具有相同的含义。例如,以下代码在每个嵌套的if语句的开始和结尾处添加一对{}
。
if(s[i] == '{' || s[i] == '(' || s[i] == '[')
{
bracks.push(s[i]);
}
else if(s[i] == '}')
{
if(bracks.top() == '{')
{
bracks.pop();
}
else if(s[i] == ')')
{
if(bracks.top() == '(')
{
bracks.pop();
}
else if(s[i] == ']')
{
if(bracks.top() == '[')
{
bracks.pop();
}
}
}
}
此示例代码与您的示例代码具有相同的含义,但(主观上)一个人可以更轻松地知道将哪些代码段组合在一起。
问题是,有许多用于缩进代码和放置花括号的方案。您会发现倡导者在某些方面有所不同。例如,以下内容是相同的,不同之处在于它遵循以下规则:开头{
应该与与其关联的if
语句在同一行。
if(s[i] == '{' || s[i] == '(' || s[i] == '[') {
bracks.push(s[i]);
}
else if(s[i] == '}') {
if(bracks.top() == '{') {
bracks.pop();
}
else if(s[i] == ')') {
if(bracks.top() == '(') {
bracks.pop();
}
else if(s[i] == ']') {
if(bracks.top() == '[') {
bracks.pop();
}
}
}
}
同样,客观地讲,这段代码具有相同的含义(就编译器而言)。但是,有些人会倡导一种,有些人会倡导另一种。