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

标签 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; 

我知道我的代码很长,但我很感激帮助。尤其是任何时候为了提高效率或 future 编码。

再次感谢

附言Zemoudeh 博士,这是您的学生 Macaire

最佳答案

我将扩展 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(“backtrace”的缩写)获取该信息。在以下回溯中,您会看到函数 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) 

仅使用这 2 个命令(runbt),您就解决了 80% 的问题:找到程序崩溃的位置。如果您停止阅读此处,您应该能够通过添加打印语句或断言来解决问题,以查看 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()。当我们看一些 good documentation对于 std::vector,我们看到您调用了未定义的行为,在本例中是程序崩溃。

现在查看您的程序,并尝试找出为什么当您的程序不希望它为空时 Well 为空。如果您喜欢 gdb,请阅读有关它的一些教程并了解如何执行设置断点或单步执行等操作。

关于c++ - 为什么我使用 std::vector 创建堆栈的程序会崩溃?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4716688/

相关文章:

c++ - 有没有比 getchar() (C/C++) 更快地读取字符串的方法?

c - 当递归也使用堆栈时,使用堆栈而不是递归如何在 C 中提供更好的性能?

c++ - 我们可以在 O(1) 时间内反转一个堆栈吗

c++ - 在命名空间 'names'::std::vs std::

c++ - 动态创建二维数组时使用了多少大小

c++ - init_seg和库代码中的警告C4073?

c++ - std::stack 是使用双链表实现的吗?

c++ - 在 C++ 中通过多个函数嵌套按值返回 vector

c++ - 如何从 x64 程序集中的堆栈获取参数?

c++ - 将 Stack.top() 添加到 vector 中?