【问题标题】:Multiple conditions in if statement in c++ (Stack implementation via Linked List)c++中if语句中的多个条件(通过链表实现堆栈)
【发布时间】:2018-04-28 12:33:26
【问题描述】:

我正在尝试创建一个程序来评估一堆括号以确保它们的正确实现(即,如果括号具有开始和结束组件,则括号有效,因此它返回“true”)。例如 [()]{}{()()} 为真,而 [({}) 为假。

目前,我即将完成程序,但堆栈评估的逻辑运算符不能正常工作。

我在 Xcode 中编程,问题可能与 IDE 相关,但不太可能。问题:线程 1:EXC_BAD_ACCESS (code=1, address=0x0)

程序不完整。我将插入一串括号作为输入,并使用递归来评估堆栈,以便删除堆栈中的所有元素,如果括号逻辑正确,在这种情况下(“[() ]{}{()()}“) 是正确的。所需的逻辑如下:

s.evaluate -> []{[]}

s.evaluate -> {}

s.evaluate -> 真

#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 is\n";
    while(ptr1 != NULL)
    {
        cout << ptr1->bracket << " -> ";
        ptr1 = ptr1->next;
    }
    cout << "NULL\n";
}

// 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++ 和数据结构的新手,不过,非常感谢您的帮助! ????

【问题讨论】:

  • 你的问题可能与获取空字符串的字符有关,看看stackoverflow.com/questions/19239566/…它可以帮助你。
  • 确实,我应该检查一下 targetNext 是否存在。
  • 这与您的问题无关,但由于您是新手:您可能想要创建一个析构函数或查看现代指针类型(unique_ptr、shared_ptr)。此代码当前会造成内存泄漏,因为您在堆上创建了nodes,但如果删除了stack,则永远不要删除它们。
  • @JeromeReinländer,这是我现在遇到的问题。程序永不停止。谢谢你的建议!顺便问一下,你能为这个问题写一个简单的析构函数吗? ??????
  • 你是对的,你检查目标不是 NULL,但不是那个 target->next(又名 targetNext)不是 NULL...

标签: c++ data-structures linked-list stack


【解决方案1】:

我在您的代码中看到的问题:

问题 1

删除targettargetNext 时会留下悬空指针。

假设你有:

          target     targetNext
           |          |
           v          v
+----+     +----+     +----+
|    | --> |    | --> |    |
+----+     +----+     +----+

删除targettargetNext 后,您会得到:

node with dangling pointer
|
v
+----+     +----+     +----+
|    | --> | x  | --> | x  |
+----+     +----+     +----+

您已跟踪target 之前的节点,并确保其next 设置为targetNext-&gt;next

当你这样做时,你必须小心处理toptarget是同一个节点的情况。

你需要使用:

// Special case the top node.
if ( top == target )
{
   top = prev = targetNext->next;
}
else
{
   prev->next = targetNext->next;
}

问题 2

当您删除一对匹配的括号时,您需要从顶部开始检查。否则,您将永远无法匹配外括号。

假设您以“[()]”开头。
您删除了内部匹配对“()”。现在你只剩下“[]”了。
如果您不从顶部开始,则将匹配剩余的一对。

删除targettargetNext后需要使用以下逻辑。

// 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 指向 '(`.

检查targettargetNext 是否指向匹配对的调用是:

if (isPair(targetNext, target)) {

isPair,你有:

bool isPair(node* n2, node* n1) {
    if ((n1->bracket == '(' && n2->bracket == ')') ...

如您所见,n1n2 被翻转了。您应该将其更改为:

bool isPair(node* n1, node* n2) {
    if ((n1->bracket == '(' && n2->bracket == ')') ...

或在调用函数时切换参数。

问题 5

当括号不匹配时,您缺少输出False


isPairevaluate 的清理版本:

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;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-03-24
    • 2012-02-18
    • 2015-01-20
    • 2012-05-24
    • 2019-03-04
    • 2020-01-16
    相关资源
    最近更新 更多