c++ 中 if 语句中的多个条件(通过链表实现堆栈)
Multiple conditions in if statement in c++ (Stack implementation via Linked List)
我正在尝试创建一个程序来评估一堆括号的正确实现(即,如果括号具有开始和关闭组件,则括号有效,因此返回"true")。例如 [()]{}{()()} 为 true,而 [({}) 为 false。
目前,我即将完成该程序,尽管堆栈评估的逻辑运算符工作不太正确。
我用 Xcode 编程,这个问题可能专门与 IDE 相关,但不太可能。问题:线程 1:EXC_BAD_ACCESS(代码 = 1,地址 = 0x0)
程序不完整。我即将插入一串括号作为输入,并使用递归来评估堆栈,以便删除堆栈中的所有元素,如果括号逻辑正确,在这种情况下("[()]{}{()()}")是正确的。所需的逻辑如下:
s.evaluate -> []{[]}
s.evaluate -> {}
s.评估 -> 真
#include<iostream>
using namespace std;
struct node
{
char bracket;
node* next;
};
class stack
{
node* top;
public:
// constructure
stack()
{
top = NULL;
}
void push(char bracket); // to insert an element
void pop(); // to delete an element
void evaluate(); // to evaluate the stack for brackets' logic
void show(); // to show the stack
bool isPair(node* n2, node* n1) {
if ((n1->bracket == '(' && n2->bracket == ')') || (n1->bracket == '[' && n2->bracket == ']') || (n1->bracket == '{' && n2->bracket == '}')) {
return true;
} else {
return false;
}
}
};
// insert an element
void stack::push(char bracket)
{
char value = bracket;
node* ptr;
ptr = new node;
ptr->bracket = value;
ptr->next = NULL;
if (top != NULL)
ptr->next = top;
top = ptr;
}
// delete an element
void stack::pop()
{
node* temp;
if (top == NULL)
{
cout << "nThe stack is empty.";
}
temp = top;
top = top->next;
cout << "nPOP Operation" << endl << "Poped value is " << temp->bracket;
delete temp;
}
// evaluate a stack for bracket logic
void stack::evaluate()
{
node* target = top;
node* targetNext = target->next;
node* temp;
node* tempNext;
if (target == NULL)
{
cout << "nTrue" << endl;
}
while (target != NULL)
{
if (isPair(targetNext, target)) {
temp = targetNext->next;
tempNext = temp->next;
cout << target->bracket << " and " << targetNext->bracket << " are deleted" << endl;
delete target;
delete targetNext;
target = temp;
targetNext = tempNext;
} else {
target = target->next;
targetNext = target->next;
}
}
}
// Show stack
void stack::show()
{
node* ptr1 = top;
cout<<"nThe stack isn";
while(ptr1 != NULL)
{
cout << ptr1->bracket << " -> ";
ptr1 = ptr1->next;
}
cout << "NULLn";
}
// Main function
int main()
{
stack s1;
string brackets = "[()]{}{[()()]()}";
for(char& c : brackets) {
s1.push(c);
}
s1.show();
s1.evaluate();
s1.show();
return 0;
}
现在,我专注于 if 逻辑部分。我已将符号从:
bool isPair(node* n2, node* n1) {
if ((n1->bracket == '(' && n2->bracket == ')') || (n1->bracket == '[' && n2->bracket == ']') || (n1->bracket == '{' && n2->bracket == '}')) {
return true;
} else {
return false;
}
}
自:
bool isPair(node* n2, node* n1) {
if (n1->bracket == '(' && n2->bracket == ')')
{
return true;
}
else if (n1->bracket == '[' && n2->bracket == ']')
{
return true;
}
else if (n1->bracket == '{' && n2->bracket == '}')
{
return true;
}
else
{
return false;
}
}
但它并没有改变任何东西(正如预期的那样)。为什么 Xcode 不想完全继续我的代码?
电流输出为:
The stack is
} -> ) -> ( -> ] -> ) -> ( -> ) -> ( -> [ -> { -> } -> { -> ] -> ) -> ( -> [ -> NULL
( and ) are deleted
{ and } are deleted
(lldb)
我知道,代码很菜鸟,我是C++和数据结构的新手,不过,非常感谢您的帮助!
我在你的代码中看到的问题:
问题1
删除target
和targetNext
时,您会留下悬空的指针。
假设您有:
target targetNext
| |
v v
+----+ +----+ +----+
| | --> | | --> | |
+----+ +----+ +----+
删除target
和targetNext
后,将剩下:
node with dangling pointer
|
v
+----+ +----+ +----+
| | --> | x | --> | x |
+----+ +----+ +----+
您已跟踪target
之前的节点,并确保其next
设置为targetNext->next
。
执行此操作时,必须小心处理top
和target
是同一节点的情况。
您需要使用:
// Special case the top node.
if ( top == target )
{
top = prev = targetNext->next;
}
else
{
prev->next = targetNext->next;
}
问题2
删除一对匹配的括号时,您需要从顶部开始检查。否则,您将永远无法匹配外部括号。
假设您以"[()]"开头。
删除内部匹配对"()"。现在只剩下"[]"。
如果您不从顶部开始,则剩余的一对杠杆将匹配。
删除target
并targetNext
后,您需要使用以下逻辑。
// Start checking from the top.
target = top;
if (target == NULL)
{
cout << "nTrue" << endl;
return;
}
targetNext = target->next;
if ( targetNext == NULL )
{
cout << "nFalse" << endl;
return;
}
问题3
使用防御性编程。在设置targetNext
之前,请务必检查target
是否有效,即它不是 NULL。将函数顶部更改为:
node* target = top;
node* targetNext = NULL;
if ( target != NULL )
{
targetNext = target->next;
}
在循环内也添加类似的检查。
if (isPair(targetNext, target)) {
...
} else {
target = target->next;
if ( target != NULL )
{
targetNext = target->next;
}
else
{
targetNext = NULL;
}
}
问题4
isPair
中的预期节点已切换。
当输入字符串为"[()]"时,堆栈对象为:
] -> ) -> ( -> [ -> NULL
当target
指向")"时,targetNext
指向"("。
检查target
和targetNext
是否指向匹配对的调用是:
if (isPair(targetNext, target)) {
在isPair
中,您有:
bool isPair(node* n2, node* n1) {
if ((n1->bracket == '(' && n2->bracket == ')') ...
如您所见,n1
和n2
是翻转的。您应该将其更改为:
bool isPair(node* n1, node* n2) {
if ((n1->bracket == '(' && n2->bracket == ')') ...
或者在调用函数时切换参数。
问题5
当括号不匹配时,您缺少输出False
。
清理了isPair
和evaluate
的版本:
bool isPair(node* n1, node* n2)
{
return ( (n1->bracket == '(' && n2->bracket == ')') ||
(n1->bracket == '[' && n2->bracket == ']') ||
(n1->bracket == '{' && n2->bracket == '}'));
}
void stack::evaluate()
{
node* target = top;
node* prev = top;
while ( target )
{
node* targetNext = target->next;
if ( targetNext == NULL )
{
cout << "nFalse" << endl;
return;
}
if (isPair(targetNext, target)) {
cout << target->bracket << " and " << targetNext->bracket << " are deleted" << endl;
// Special case the top node.
if ( top == target )
{
top = prev = targetNext->next;
}
else
{
prev->next = targetNext->next;
}
delete target;
delete targetNext;
// Intermediate output for troubleshooting.
// this->show();
// Start checking from the top.
target = top;
}
else
{
prev = target;
target = target->next;
}
}
cout << "nTrue" << endl;
return;
}
- 在 C++ 中使用链表进行堆栈
- 实现基于链表的堆栈的基于范围的 for 循环
- 使用带有链表的堆栈数据结构将中缀转换为后缀
- 使用链表在 c++ 中堆栈嵌入
- 使用链表实现堆栈时出错
- 未分配被释放的指针(将堆栈实现为链表时)
- 在C++中使用链表的堆栈实现中,访问结构体headNode成员count和top会导致运行时错误
- 双链表堆栈删除函数不起作用
- 使用链表在堆栈中插入和删除
- 链表堆栈头文件中"<"标记之前的预期初始值设定项
- 使用链表C++堆栈
- 链表堆栈类的复制构造函数:我的正在向后复制
- 尝试创建链表堆栈时出现链接器错误
- 学习在C++中实现链表堆栈类
- 使用指针的C++链表堆栈
- 实现与链表堆栈的交集
- 在链表堆栈上弹出函数
- 使用链表堆栈
- 使用链表堆栈错误
- 链表堆栈复制构造函数