简体   繁体   中英

Segmentation fault on continuous calculator program

I tried to write a calulator which allows for chaining. So my firstSet() function handles division an multiplication and the. modifies the vector, until the secondSet() function handle addition and subtraction.I had some bugs with the part where I am erasing vector elements, which is where I suspect the segmentation fault is occurring from.

#include <vector>
#include <iostream>

//Structure:
//Vector 'stream' of data objects , where each element is either a num or operator
//Heirarchy:
//1.* & /
//2.+ & -
//expected input : Spaced integers with operators and a semicolon to end the input statement.
//for ex:
//3+2;
//5/6;
struct Data
{
    char type;
    int val;
    char op;
    Data(char x , char y)
        : type(x) , op(y){} 
    Data(char x , int y) : type(x) , val(y){} 
};
void firstSet(std::vector<Data> & v)    // / & *
{
    int temp;
    for (auto i = v.begin(); i != v.end()-1 ; ++i)
    {
        if ((*i).type == 'o' && ((*i).op == '/' || (*i).op == '*'))
        {
            if ((*i).op == '/')
            {
                temp =  (*(i-1)).val / (*(i+1)).val;
            }
            if ((*i).op == '*')
            {
                temp = (*(i-1)).val * (*(i+1)).val;
            }
            (*(i-1)).val = temp; // change lhs
            v.erase(i);         //delete operator
            v.erase(i);         //delete rhs

        }
    }
}
void secondSet(std::vector<Data> & v) // + & - 
{

    int temp;
    for (auto i = v.begin(); i != v.end() ; ++i)
    {
        if ((*i).type == 'o' && ((*i).op == '+' || (*i).op == '-') )
        {
            if ((*i).op == '+')
            {
                temp =  (*(i-1)).val + (*(i+1)).val;
            }
            if ((*i).op == '-')
            {
                temp = (*(i-1)).val - (*(i+1)).val;
            }

            (*(i-1)).val = temp;
            v.erase(i);
            v.erase(i);


        }
    }
}

int main()
{
    std::vector<Data> v;
    char T;
    std::cin >>T;
    while (T != ';')
    {
        if (T == '/' || T == '*' || T == '+' || T == '-')
        {
            v.push_back(Data{'o' , T});
        }
        if (T >= '0' && T <= '9')
        {
            std::cin.putback(T);
            int x;
            std::cin >> x;
            v.push_back(Data{'n' , x});
        }

        std::cin >> T;
    }
    firstSet(v);
    secondSet(v);
    std::cout << v[0].val;
}

ps any comments on code readability and neatness in general would be helpful as I want the code to be 'clean'.

Using i after v.erase(i) is invalid, because calling erase [...]invalidates iterators and references at or after the point of the erase, including the end() iterator.[...]

So the second v.erase(i) is wrong, but also continuing the loop using ++i is invalid, and would result in undefined behavior.

You need to replace i with a valid iterator after your erase called. Eg using:

i = v.erase(i);

But doing so will result in skipping each element after the erased one, so you need to change the logic of your loop.

But there are other parts that are invalid:

  • (*(i-1)).val = temp; will be invalid if i==v.begin()
  • (*(i+1)).val will be invalid if (i+1)==v.end()

So you need to think over the complete logic of your code in general.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM