C++ 连续计算器程序中的分段错误

C++ 连续计算器程序中的分段错误,c++,C++,我试着写一个允许链接的计算器。 因此,我的firstSet()函数处理除法和乘法。修改向量,直到secondSet()函数处理加法和减法。我在擦除向量元素的部分出现了一些错误,我怀疑这是发生分段错误的地方 #include <vector> #include <iostream> //Structure: //Vector 'stream' of data objects , where each element is either a num or operator

我试着写一个允许链接的计算器。 因此,我的
firstSet()
函数处理除法和乘法。修改向量,直到
secondSet()
函数处理加法和减法。我在擦除向量元素的部分出现了一些错误,我怀疑这是发生分段错误的地方

#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;
}
#包括
#包括
//结构:
//数据对象的向量“流”,其中每个元素都是num或运算符
//继承权:
//1.* & /
//2.+ & -
//预期输入:带运算符和分号的间隔整数,用于结束输入语句。
//例如:
//3+2;
//5/6;
结构数据
{
煤焦类型;
int-val;
char op;
数据(字符x,字符y)
:type(x),op(y){}
数据(字符x,整数y):类型(x),值(y){
};
无效第一集(标准::向量&v)///&*
{
内部温度;
对于(自动i=v.begin();i!=v.end()-1;++i)
{
if((*i).type='o'&(*i.op='/'| |(*i.op=='*'))
{
if((*i.op=='/'))
{
温度=(*(i-1)).val/(*(i+1)).val;
}
如果((*i.op='*'))
{
温度=(*(i-1)).val*(*(i+1)).val;
}
(*(i-1)).val=temp;//更改lhs
v、 擦除(i);//删除运算符
v、 删除(i);//删除rhs
}
}
}
无效第二集(标准::向量和v)//+&-
{
内部温度;
对于(自动i=v.begin();i!=v.end();++i)
{
if((*i).type='o'&(*i.op=='+'| |(*i.op=='-'))
{
if((*i.op=='+'))
{
温度=(*(i-1)).val+(*(i+1)).val;
}
如果((*i.op='-'))
{
温度=(*(i-1)).val-(*(i+1)).val;
}
(*(i-1)).val=温度;
v、 删除(i);
v、 删除(i);
}
}
}
int main()
{
std::向量v;
查尔特;
标准:cin>>T;
而(T!=';')
{
如果(T='/'| | T='*'| | T='+'| | T=='-')
{
v、 向后推(数据{'o',T});
}
如果(T>='0'&&T>x;
v、 推回(数据{'n',x});
}
标准:cin>>T;
}
第一组(v);
第二组(v);

std::cout在
v.erase(i)
之后使用
i
是无效的,因为调用
[…]会使迭代器和引用在擦除点或之后失效,包括end()迭代器。[…]

因此,第二个
v.erase(i)
是错误的,但是使用
++i
继续循环也是无效的,并且会导致未定义的行为

调用
erase
后,需要使用有效的迭代器替换
i
。例如,使用:

i = v.erase(i);
但是这样做会导致在删除的元素之后跳过每个元素,因此需要更改循环的逻辑

但还有其他无效部分:

  • (*(i-1)).val=temp;
    如果
    i==v.begin()
  • (*(i+1)).val如果
    (i+1)=v.end()

因此,您需要考虑代码的完整逻辑。

v.erase(i)
之后使用
i
是无效的,因为调用
[…]会使迭代器和引用在擦除点或之后失效,包括end()迭代器。[…]

因此,第二个
v.erase(i)
是错误的,但是使用
++i
继续循环也是无效的,并且会导致未定义的行为

调用
erase
后,需要使用有效的迭代器替换
i
。例如,使用:

i = v.erase(i);
但是这样做会导致在删除的元素之后跳过每个元素,因此需要更改循环的逻辑

但还有其他无效部分:

  • (*(i-1)).val=temp;
    如果
    i==v.begin()
  • (*(i+1)).val如果
    (i+1)=v.end()

因此,您需要考虑代码的完整逻辑。

为什么要调用
v.erase(i)
两次?当i=
v.begin()时
*(i-1)
的值是多少,当
i=v.end()时
*(i+1)
的值是多少
如何输入负值?例如
9--3
?为什么要调用
v.erase(i)
两次?当i=
v.begin()时
*(i-1)
的值是多少,当
i=v.end()时
*(i+1)
的值是多少
如何输入负值?例如
9--3
?但即使我输入了有效的输入,为什么
(*(I-1)).val=temp
无效(代码不会分支到if条件)?@ChiragM我没有检查代码的完整逻辑。如果你只查看
void secondSet(std::vector&v)
假设
v
的第一个元素的类型为
type='o'
op='+'
,然后将调用
(*(i-1)).val=temp
(从代码审查的角度来看,如果认为调用
secondSet
的代码可以防止这种情况发生,这并不重要。)但是,即使我输入了有效的输入,为什么
(*(I-1)).val=temp
无效(代码不会分支到if条件)?@ChiragM我没有检查代码的完整逻辑。如果您限制自己只查看
void secondSet(std::vector&v)
假设
v
的第一个元素的类型为
type='o'
op='+'
,然后将调用
(*(i-1)).val=temp
(从代码审查的角度来看,如果认为调用
secondSet
的代码可以防止这种情况发生,这并不重要。)