使用链接列表

时间:2016-01-23 07:42:08

标签: c++

我编写了一个c ++程序,用于将中缀表达式转换为后缀表达式。 每当我运行它,它似乎进入无限循环。 我已经使用堆栈来存储运算符和括号等,并使用一个队列来存储后缀表达式本身。 用户输入整个中缀表达式,程序一次取一个字符,而中缀表达式的其余部分保留在stdin流中。

我无法弄清楚这个程序中的错误,请帮忙!

程序代码:

 #include<iostream.h>
#include<conio.h>
#include<stdio.h>
#include<string.h>
#include<ctype.h>
struct LIST
{
    char val;
    LIST* next;
};
LIST* start_stack=NULL;
LIST* start_post=NULL;
LIST* end_post=NULL;
LIST* np;


int check_char(char a)
{
    if(isalnum(a))
    return 1;//For operand

    else if(a=='^'||a=='*'||a=='/'||a=='+'||a=='-') //For operator
    {
    if(a=='^')
    return 21;
    else if(a=='*'||a=='/')
    return 22;
    else
    return 23;
    }
    else if(a=='('||a=='['||a=='{')//For openeing parenthesis
    return 3;
    else if(a==')'||a=='}'||a==']')
    return 4;
    else
return 0;

}
void push(LIST* push_element, int i=1)
{
    if(i==1)
    {
        if(start_stack==NULL)
        start_stack=push_element;
        else
        {
            LIST* temp;
            temp=start_stack;
            start_stack=np;
            start_stack->next=temp;
        }
    }
    else
    {
        if(start_post==NULL)
        start_post=end_post=np;
        else
            {
                end_post->next=np;
                end_post=np;
            }
    }
}

void pop(LIST* pop_element)
{
    LIST *temp;
    temp=pop_element;
    pop_element=pop_element->next;
    delete temp;
}



void Infix_to_Postfix()
{

     char a;
     cin>>a;
     while(a!='.')
     {
         if(check_char(a)==1)
         {
             np=new LIST;
             np->val=a;
             np->next=NULL;
             push(np,2);
         }
         else if(check_char(a)>20)
         {
             while(start_stack!=NULL&&check_char(start_stack->val)!=3)
             {
                 if(check_char(a)>=check_char(start_stack->val))
                 {
                      np=new LIST;
                      np->val=start_stack->val;
                      np->next=NULL;
                      push(np,2);
                      pop(start_stack);
                 }
             }
             np=new LIST;
             np->val=a;
             np->next=NULL;
             push(np);
         }
         else if(check_char(a)==3)
         {
             np=new LIST;
             np->val=a;
             np->next=NULL;
             push(np);
         }
         else if(check_char(a)==4)
         {
             while(start_stack!=NULL&&check_char(start_stack->val)!=3)
             {
                 np=new LIST;
                 np->val=start_stack->val;
                 np->next=NULL;
                 push(np,2);
                 pop(start_stack);
             }
             pop(start_stack);
         }
     cin>>a;
     }

     while(start_stack!=NULL)
     {
          np=new LIST;
          np->val=start_stack->val;
          np->next=NULL;
          push(np,2);
          pop(start_stack);
     }

     while(start_post!=NULL)
     {
         cout<<endl;
         cout<<start_post->val;
         start_post=start_post->next;
     }
}


int main()
{
    clrscr();
    Infix_to_Postfix();
    getch();
    return 1;
}

1 个答案:

答案 0 :(得分:0)

功能中存在问题。

void pop(LIST* pop_element)

弹出的值可以找到,但它不会修改sent in参数。

所以行

 pop(start_stack);

删除内存start_stack,但不会更改指针start_stack。 创建引用将解决此问题。

void pop(LIST* & pop_element)
{
    LIST *temp;
    temp=pop_element;
    pop_element=pop_element->next;
    delete temp;
}

如何找到这些错误

我的调试环境使用了MSVC和调试堆。当第二次释放相同的内存时,它在调试器中破坏并且相对容易解决这个问题。对于linux,你可以在windows上使用valgrind,非MS编译器Application Verifier会发现这个问题。

如果您使用调试器单步执行代码。查看变量的值,并检查它们是否符合您的预期。

在这种情况下(没有调试堆,我可以看到指针start_stack没有改变值。

提供的代码是列表,堆栈的实现,并将它们一起用于所需的中缀到后缀转换。

尝试单独测试列表行为与较大问题的单元测试。 尝试单独测试堆栈行为与较大问题的单元测试。堆栈溢出需要最小的可验证代码示例(SO : MCVE)。这是为了鼓励您解构您的问题,以找到最不起作用的最小代码。这也应该有助于您专注于如何解决它。

当您实现堆栈和队列时,请尝试与std :: stack和std :: queue行为进行比较,再次帮助您识别失败的单元。

最后,对于堆栈溢出,一个吃stdin的程序很难让人们看到正在发生的事情。确保指定导致行为所需的输入,或提供从其自身获取输入的程序....

 void Old()
 {  
     int myVar;
     cin > myVar;
 }
 int main()
 {
      Old();
 }

应该是

 void Old( std::istream & stm )
 {  
     int myVar;
     stm > myVar;
 }
 int main()
 {
      std::stringstream s( "123" ); // test value causes issue.
      Old(s );
 }