简单计算器的代码在VS中运行错误

问题遇到的现象和发生背景
#include <iostream>
#include <cstdio>
#include <string>
#include <stack>
#include <map>
#include <queue>
using namespace std;

struct node {
    double num;  //操作数
    char op;     //操作符
    bool flag;   //true表示操作数,false表示操作符
};

string str;
stack<node> s;//操作符栈
queue<node> q;//后缀表达式序列
map<char, int> op;

//将中缀表达式转换为后缀表达式
void Change() {
    double num;
    node temp;
    for (int i = 0;i < str.length();) {
        if (str[i] >= '0' && str[i] <= '9') {//如果是数字
            temp.flag = true;//标记是数字数
            temp.num = str[i++] - '0';//记录这个操作数的第一个位数
            while (i < str.length() && str[i] >= '0' && str[i] <= '9') {
                temp.num = temp.num * 10 + (str[i] - '0');  //更新这个操作数
                i++;
            }
            q.push(temp);//将操作数压入后缀表达式的队列
        }
        else {  //如果是操作符
            temp.flag = false;//标记是操作符
            //只要操作符栈顶元素比该操作符优先级高
            //就把操作符栈栈顶元素弹出到后缀表达式的队列中
            while (!s.empty() && op[str[i]] <= op[s.top().op]) {
                q.push(s.top());
                s.pop();
            }
            temp.op = str[i];
            s.push(temp); //把该操作符压入操作符栈中
            i++;
        }
    }
    while (!s.empty()) {
        q.push(s.top());
        s.pop();
    }
}

double Cal() {
    double temp1, temp2;
    node cur, temp;
    while (!q.empty()) {    //只要后缀表达式非空
        cur=q.front();      //记录队的首元素
        q.pop();
        if (cur.flag == true) s.push(cur); //如果是操作数,直接压入栈
        else {//如果是操作符
            temp2 = s.top().num;//弹出第二操作数
            s.pop();
            temp1 = s.top().num;//弹出第一操作数
            s.pop();
            temp.flag = true;//记录临时操作数
            if (cur.op == '+') temp.num = temp1 + temp2;//加法
            else if (cur.op == '-') temp.num = temp1 - temp2;//减法
            else if (cur.op == '*') temp.num = temp1 * temp2;//乘法
            else temp.num = temp1 / temp2;//除法
            s.push(temp);//把该操作数压入栈
        }
    }
    return s.top().num; //栈顶元素就是后缀表达式的值
}

int main() {
    op['+'] = op['-'] = 1;//设定操作符的优先级
    op['*'] = op['/'] = 2;
    while (getline(cin, str), str != "0") {
        //for (string::iterator it = str.end();it != str.begin();it--) {
            //if (*it == ' ') str.erase(it);//把表达式中的空格全去掉
        //}
        while (!s.empty()) s.pop();//初始化栈
        Change();//将中缀表达式转换为后缀表达式
        printf("%.2f\n", Cal());//计算后缀表达式
    }
    return 0;
}

 //for (string::iterator it = str.end();it != str.begin();it--) {
            //if (*it == ' ') str.erase(it);//把表达式中的空格全去掉
        //}

主函数用把表达式中空格去掉这步出错

我的解答思路和尝试过的方法
我想要达到的结果

调用string::erase(it)会导致迭代器it失效。可以用下面方法删除字符串str中的所有空白符(空格、制表符、换行符),结果存到new_str

string new_str;
copy_if(str.begin(), str.end(), back_inserter(new_str), [](auto c) { return !std::isspace(c); });

好多错误啊,首先,从后往前遍历,应该是

for (auto it = str.rbegin();it != str.rend();it++) 
        

你这个从end到begin就离谱,因为end并不是最后一个元素的迭代器,而是最后一个元素+1,对end的访问无效,而begin是开头的元素,你这样无法访问第一个元素。
而且,删除元素后,迭代器会失效,可以用erase+remove_if实现删除所有空白字符
应改为:

str.erase(std::remove_if(str.begin(),str.end(),[](char ch){return std::isspace(ch);}),str.end());