休息;导致段错误
break; causing segment fault
我正在使用堆栈进行括号检查。包含 break; 语句的 if else 语句之一导致段错误。
我尝试删除 break 程序运行正常但打印错误答案,因为需要 break 才能打印正确的输出。这种段错误的原因是什么?中断不访问任何内存 unit.right?
#include <iostream>
#include<stack>
using namespace std;
int main() {
//code
int n;
char c,comp;
cin>>n;
while(n--)
{
stack<char>s;
while(cin>>c)
{
if(c=='(' || c=='{'|| c=='[')
s.push(c);
else
{
comp=s.top();
if(c==')' && comp=='(')
s.pop();
else if(c==')' && comp!='(')
{
cout<<"not balanced"<<endl;
break; //this one, if i remove this no SIGSEGV
}
if(c=='}' && comp=='{')
s.pop();
else if(c=='}' && comp!='{')
{
cout<<"not balanced"<<endl;
break;
}
if(c==']' && comp=='[')
s.pop();
else if(c==']' && comp!='[')
{
cout<<"not balanced"<<endl;
break;
}
}
}
if(s.empty())
cout<<"balanced"<<endl;
}
return 0;
}
崩溃是因为在平衡输入的情况下你的循环没有终止。所以你最终会从空堆栈中弹出一些东西。
您应该使用 do while 循环编写此代码
do
{
...
if (c == ')' && comp != '(')
break;
...
}
while (!s.empty());
if (s.empty())
cout << "balanced\n";
else
cout << "not balanced\n";
虽然即使那样你也需要同步你的输入。也许您应该读取整个输入(也许每行一个字符串?),然后处理输入字符串。在那种情况下,您可以用 for 循环替换 do while 循环,例如for (char c : input)
因此,first some background information on std::stack
稍后将变得相关:
The programming-by-contract style would be that having a non-empty stack is a precondition of calling pop, and that calling a method without meeting its preconditions has an undefined outcome.
请注意,虽然我找不到来源说当堆栈中有 0 个元素时 s.top()
是错误的,但出于同样的原因,我假设它也是错误的。
为什么这很重要?嗯,,包括段错误。把它记在脑后。
所以,这段代码就在这里:
comp=s.top();
如果您 运行 遇到 s
为空的情况,而您有其他内容来自 std::cin
,会发生什么情况?例如,如果你在括号的末尾有一个额外的 ) 会怎样:
()()) // <-- extra )
()
s 抵消了,但是 ) 仍然存在。因此,当您尝试引用顶部时,那里什么也没有。这可能是导致崩溃的原因。
在尝试引用顶部之前,您需要检查此行以确保 s
不为空:
if(!s.empty()) {
comp=s.top();
}
你也应该在 pop()
前后这样做:
if(c==')' && comp=='(' && !s.empty())
s.pop();
或者类似的东西。您的逻辑可能需要一些修改,但希望这能给您带来灵感。
我正在使用堆栈进行括号检查。包含 break; 语句的 if else 语句之一导致段错误。
我尝试删除 break 程序运行正常但打印错误答案,因为需要 break 才能打印正确的输出。这种段错误的原因是什么?中断不访问任何内存 unit.right?
#include <iostream>
#include<stack>
using namespace std;
int main() {
//code
int n;
char c,comp;
cin>>n;
while(n--)
{
stack<char>s;
while(cin>>c)
{
if(c=='(' || c=='{'|| c=='[')
s.push(c);
else
{
comp=s.top();
if(c==')' && comp=='(')
s.pop();
else if(c==')' && comp!='(')
{
cout<<"not balanced"<<endl;
break; //this one, if i remove this no SIGSEGV
}
if(c=='}' && comp=='{')
s.pop();
else if(c=='}' && comp!='{')
{
cout<<"not balanced"<<endl;
break;
}
if(c==']' && comp=='[')
s.pop();
else if(c==']' && comp!='[')
{
cout<<"not balanced"<<endl;
break;
}
}
}
if(s.empty())
cout<<"balanced"<<endl;
}
return 0;
}
崩溃是因为在平衡输入的情况下你的循环没有终止。所以你最终会从空堆栈中弹出一些东西。
您应该使用 do while 循环编写此代码
do
{
...
if (c == ')' && comp != '(')
break;
...
}
while (!s.empty());
if (s.empty())
cout << "balanced\n";
else
cout << "not balanced\n";
虽然即使那样你也需要同步你的输入。也许您应该读取整个输入(也许每行一个字符串?),然后处理输入字符串。在那种情况下,您可以用 for 循环替换 do while 循环,例如for (char c : input)
因此,first some background information on std::stack
稍后将变得相关:
The programming-by-contract style would be that having a non-empty stack is a precondition of calling pop, and that calling a method without meeting its preconditions has an undefined outcome.
请注意,虽然我找不到来源说当堆栈中有 0 个元素时 s.top()
是错误的,但出于同样的原因,我假设它也是错误的。
为什么这很重要?嗯,
所以,这段代码就在这里:
comp=s.top();
如果您 运行 遇到 s
为空的情况,而您有其他内容来自 std::cin
,会发生什么情况?例如,如果你在括号的末尾有一个额外的 ) 会怎样:
()()) // <-- extra )
()
s 抵消了,但是 ) 仍然存在。因此,当您尝试引用顶部时,那里什么也没有。这可能是导致崩溃的原因。
在尝试引用顶部之前,您需要检查此行以确保 s
不为空:
if(!s.empty()) {
comp=s.top();
}
你也应该在 pop()
前后这样做:
if(c==')' && comp=='(' && !s.empty())
s.pop();
或者类似的东西。您的逻辑可能需要一些修改,但希望这能给您带来灵感。