为什么我的程序使用std :: vector创建堆栈崩溃?

时间:2011-01-17 18:49:47

标签: c++ stack

我正在为我的数据结构类创建自己的堆栈。对于我们的任务,我们使用赋值将实时中缀方程转换为后缀方程     我以为我的计划:
        接受了输入         确定它是数字还是数字(操作数)
            将它打印出来         确定输入是否为运算符(+, - ,/,*)
            添加到堆栈或打印输出,具体取决于堆栈优先级

相反,它按预期打印出操作数,但是当我输入运算符

时出现此错误
>.../dorun.sh line 33: 4136 Segmentation fault     <core dumped> sh "$<SHFILE>"


#include <vector>
using namespace std;

class DishWell{  
public:  
    char ReturnEnd(){  
        return Well.back();  
    }  
    void Push(char x){  
        Well.push_back(x);  
    }  
    void Pop(){  
        Well.pop_back();  
    }  
    bool IsEmpty(){  
        return Well.empty();  
    }  
private:  
    vector<char> Well;  
};   
#include <iostream>  
bool Precidence(char Input, char Stack){  
    int InputPrecidence,StackPrecidence;  
    switch (Input){  
        case '*':  
            InputPrecidence = 4;  
            break;
        case '/':
            InputPrecidence = 4;  
            break;  
        case '+':  
            InputPrecidence = 3;  
            break;  
        case '-':  
            InputPrecidence = 3;  
            break;  
        case '(':  
            InputPrecidence = 2;  
            break;  
        default:  
            InputPrecidence = 0;  
    }  
    switch (Stack){  
        case '*':  
            StackPrecidence = 4;  
            break;  
        case '/':  
            StackPrecidence = 4;  
            break;  
        case '+':  
            StackPrecidence = 3;  
            break;  
        case '-':  
            StackPrecidence = 3;  
            break;  
        case '(':  
            StackPrecidence = 2;  
            break;  
        default:  
            StackPrecidence = 0;  
    }  
    if(InputPrecidence>StackPrecidence) return true;  
    else return false;  
}  
int main(int argc, char** argv) {  
    DishWell DishTray;  
    char Input;  
    bool InputFlag;  
    InputFlag = true;  
    while(InputFlag){  
        cin>>Input;  
        if((((Input>='a'&&Input<='z')||(Input>='A'&&Input<='Z'))|| (Input>='0'&&Input<='9')))//If Digit or Number  
            cout<<Input;  
        if((Input=='*'||Input=='/'||Input=='+'||Input=='-')){//if operand  
            if(Precidence(Input,DishTray.ReturnEnd()))  
                DishTray.Push(Input);  
            else if(!Precidence(Input,DishTray.ReturnEnd()))  
                cout<<Input;  
        }  
        else if(!((((Input>='a'&&Input<='z')||(Input>='A'&&Input<='Z'))||    (Input>='0'&&Input<='9')))||((Input=='*'||Input=='/'||Input=='+'||Input=='-')))//if not digit/numer or operand  
            InputFlag = false;  
    }  
    while(!DishTray.IsEmpty()){  
        cout<<DishTray.ReturnEnd();  
        DishTray.Pop();  
    }  
    return 0; 

我的代码很长,我知道,但我很感激帮助。特别是效率或未来编码的任何时候。

再次感谢

P.S。 Zemoudeh博士,这是你的学生Macaire

3 个答案:

答案 0 :(得分:6)

我会扩展Rup的回答,回答你没有问的问题,但更重要的是:如何找出我的程序崩溃的位置?

一种方法是在整个程序中添加std::coutprintf语句。在每个函数的开头写一个声明,“function x enter”,最后说“function x exit”。运行你的程序,当它崩溃时,你会看到它的功能。此时,你可以添加行来打印每个变量的内容,以找出出错的地方。

另一种方法是使用调试器,如gdb

首先,使用-g开关编译程序以启用调试信息。

linux@linux-ubuntu:~/t$ g++ prog.cpp -o prog -g

接下来,告诉调试器gdb运行您的程序。

linux@linux-ubuntu:~/t$ gdb ./prog

在gdb提示符下,键入run以启动您的程序。我输入了4*(3+2),程序崩溃了at prog.cpp:7,即return Well.back();行。

(gdb) run
Starting program: /home/linux/t/prog 
4*(3+2)
4
Program received signal SIGSEGV, Segmentation fault.
0x08048d0b in DishWell::ReturnEnd (this=0xbffff460) at prog.cpp:7
7           return Well.back();  

对于更复杂的程序,您通常需要列出当前正在调用的所有函数。您可以使用bt获取该信息,简称为“回溯”。在下面的回溯中,您会看到函数main(#1)正在调用函数DishWell::ReturnEnd(#0)。 #0是当前函数,因为函数形成堆栈,其中当前函数是堆栈的顶部(偏移0是顶部)。

(gdb) bt
#0  0x08048d0b in DishWell::ReturnEnd (this=0xbffff460) at prog.cpp:7
#1  0x08048b35 in main (argc=1, argv=0xbffff534) at prog.cpp:75
(gdb) 

只有这两个命令(runbt),您已经解决了80%的问题:找到程序崩溃的位置。如果您在这里停止阅读,您应该能够通过添加print语句或断言来解决问题,以查看Well的状态以及back()导致程序崩溃的原因。但是让我们再使用gdb ......

您可以键入list以查看该行周围的源代码,以获得更多上下文,而无需离开调试器。

(gdb) list
2   using namespace std;
3   
4   class DishWell{  
5   public:  
6       char ReturnEnd(){  
7           return Well.back();  
8       }  
9       void Push(char x){  
10          Well.push_back(x);  
11      }  
(gdb) 

gdb可以打印变量和简单表达式。在这里打印Well的值对初学者来说没什么用处,因为它是一个复杂的数据结构,而不是一个简单的变量。但我们可以告诉gdb在该变量上调用一个方法......

(gdb) print Well.size()
$2 = 0
(gdb) print Well.empty()
$3 = true

啊哈,Well是空的,你已经打电话给back()了。当我们查看std::vector的{​​{3}}时,我们会看到您调用未定义的行为,在这种情况下是程序崩溃。

现在查看您的程序,并尝试找出当您的程序不期望它为空时Well为空的原因。如果您喜欢gdb,请阅读其中的一些教程,并学习如何设置断点或单步操作。

答案 1 :(得分:2)

错误发生在您的while(InputFlag)循环中:

    if((Input=='*'||Input=='/'||Input=='+'||Input=='-')){//if operand  
        if(Precidence(Input,DishTray.ReturnEnd()))  

问题是第一次通过你在空向量上调用DishTray.ReturnEnd()。在调用Precidence并正确操作之前,您需要检查向量是否为空,如果向量为空,则需要从ReturnEnd()返回0值。这一切都说我无法真正看到你在这里尝试做什么,因为你将操作数直接传递到输出而没有以任何方式将它们引用到堆栈 - 这真的是算法的正确实现吗? / p>

但你真的需要学习如何自己调试这个。您应该真正阅读dorun.sh以了解它是如何编译代码的,您应该了解如何使用gdbdbx或您系统上的任何调试器来自行解决这个问题。如果它是gdb,你可能想要像

这样的东西
 g++ -g mystack.cpp -o mystack
 gdb mystack
 run
 <enter input, e.g. 2+3+4+5>
 bt

答案 2 :(得分:1)

如果我理解正确,您的任务就是实施Shunting-yard algorithm

因为,这是一个数据结构分配,如果我是你,我不会使用std::vector。因为,通常是不允许的。您应该使用char stack[STACK_SIZE]实现ADT,或使用链接列表方法动态实现。