Search code examples
c++vectoriostdvectorstd-pair

Overwrite the elements in a vector without specifying specific elements


I am making a calculator that accepts multiple operators at once. I have a vector pair that stores the position of operators, and the type of operator. The vector must be updated after each loop as the previous positions are no longer valid due to the result replacing a part of the input string.

I've attempted to use clear() so that it starts from the beginning again, but that results in Expression: vector iterators incompatible. I don't think I can use std::replace since the number of operators in the string changes after each loop. Is there a way to just have it start from the beginning again and overwrite any existing elements?

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>

int main()
{
    std::cout << "C++ Calculator" << std::endl;

    while (true) //runs forever with loop
    {
        std::string input;
        std::getline(std::cin, input);

        //erases whitespace
        int inp_length = input.length();
        for (int i = inp_length - 1; i >= 0; --i)
        {
            if (input[i] == ' ')
                input.erase(i, 1);
        }
        
        std::vector<std::pair<int, char>> oper_pvec;
        int vec_pos = 0;

        //finds the position of operators and type
        for (std::string::iterator i = input.begin(); i != input.end(); ++vec_pos, ++i)
        {
            switch (*i)
            {
                case 'x':
                {
                    oper_pvec.push_back(std::pair<int, char>(vec_pos, 'x'));
                    break;
                }
                case '/':
                {
                    oper_pvec.push_back(std::pair<int, char>(vec_pos, '/'));
                    break;
                }
                case '+':
                {
                    oper_pvec.push_back(std::pair<int, char>(vec_pos, '+'));
                    break;
                }
                case '-':
                {
                    oper_pvec.push_back(std::pair<int, char>(vec_pos, '-'));
                    break;
                }
            }
        }

        //declarations before loop to make sure they're all able to be accessed, will probably change later
        int loper_pos = 0; //must be set 0 since there's no left operator at first
        int roper_pos;
        double lnum; //left number
        double rnum; //right number
        char loper; //left operator
        char roper; //right operator
        int pos = -1; //position of loop, needs to be -1 since it increments it each time
        std::string holder = input; //copy of input

        auto op = oper_pvec.begin();
        while (op != oper_pvec.end())
        {
            op = oper_pvec.begin();
            ++pos; //position of loop
            int key = std::get<0>(*op); //gets first value from vector pair
            char val = std::get<1>(*op); //gets second value from vector pair


            //gets previous/next vector pairs
            std::vector<std::pair<int, char>>::iterator prev_op = oper_pvec.begin();
            std::vector<std::pair<int, char>>::iterator next_op = oper_pvec.end();

            if (op != oper_pvec.begin()) prev_op = std::prev(op);
            if (op != oper_pvec.end()) next_op = std::next(op);


            //extracts the value of pairs
            if (pos > 0)
            {
                loper_pos = std::get<0>(*prev_op);
                loper = std::get<1>(*prev_op);
            }
            if (pos == oper_pvec.size() - 1) roper_pos = oper_pvec.size();
            else
            {
                roper_pos = std::get<0>(*next_op);
                roper = std::get<1>(*next_op);
            }


            //replaces numbers and etc with product, only multiplication for now
            switch (val)
            {
                case 'x':
                {
                    int lnum_start = loper_pos + 1;
                    if (loper_pos == 0) lnum_start = 0;

                    int lnum_len = key - (loper_pos + 1);
                    if (loper_pos == 0) lnum_len = key;

                    lnum = std::stod(input.substr(lnum_start, lnum_len));

                    int rnum_start = key + 1;
                    int rnum_len = (roper_pos - 1) - key;
                    rnum = std::stod(input.substr(rnum_start, rnum_len));

                    double prod = lnum * rnum;
                    std::string to_string = std::to_string(prod);
                    input.replace(loper_pos, roper_pos, to_string);
                    break;
                }
            }

            /////////////////////////////////problem area////////////////////////////////////////

            //clears the vector and then finds the operators again
            oper_pvec.clear();
            int vpos = 0;
            for (std::string::iterator it = input.begin(); it != input.end(); ++vpos, ++it)
            {
                if (vpos == input.length())
                {
                    vpos = 0;
                    break;
                }
                switch (*it)
                {
                    case 'x':
                    {
                        oper_pvec.push_back(std::pair<int, char>(vpos, 'x'));
                        break;
                    }
                    case '/':
                    {
                        oper_pvec.push_back(std::pair<int, char>(vpos, '/'));
                        break;
                    }
                    case '+':
                    {
                        oper_pvec.push_back(std::pair<int, char>(vpos, '+'));
                        break;
                    }
                    case '-':
                    {
                        oper_pvec.push_back(std::pair<int, char>(vpos, '-'));
                        break;
                    }
                }
            }
            /////////////////////////////////////////////////////////////////////////////////////
        }
        //converts to double then prints on screen
        double out = std::stod(input);
        std::cout << out << std::endl;
    }
}

Solution

  • Not really the answer to the title but instead of trying to overwrite the vector I just continued to use clear() and changed the while loop to oper_pvec.size() != 0.

    (Full code since I had to change quite a few things to get it to work properly)

    #include <iostream>
    #include <string>
    #include <vector>
    #include <algorithm>
    
    int main()
    {
        std::cout << "C++ Calculator" << std::endl;
    
        while (true) //runs forever with loop
        {
            std::string input;
            std::getline(std::cin, input);
    
            //erases whitespace
            int inp_length = input.length();
            for (int i = inp_length - 1; i >= 0; --i)
            {
                if (input[i] == ' ')
                    input.erase(i, 1);
            }
            
            std::vector<std::pair<int, char>> oper_pvec;
            int vec_pos = 0;
    
            //finds the position of operators and type
            for (std::string::iterator i = input.begin(); i != input.end(); ++vec_pos, ++i)
            {
                switch (*i)
                {
                    case 'x':
                    {
                        oper_pvec.push_back(std::pair<int, char>(vec_pos, 'x'));
                        break;
                    }
                    case '/':
                    {
                        oper_pvec.push_back(std::pair<int, char>(vec_pos, '/'));
                        break;
                    }
                    case '+':
                    {
                        oper_pvec.push_back(std::pair<int, char>(vec_pos, '+'));
                        break;
                    }
                    case '-':
                    {
                        oper_pvec.push_back(std::pair<int, char>(vec_pos, '-'));
                        break;
                    }
                }
            }
    
            //declarations before loop to make sure they're all able to be accessed, will probably change later
            int loper_pos = 0; //must be set 0 since there's no left operator at first
            int roper_pos;
            double lnum; //left number
            double rnum; //right number
            char loper; //left operator
            char roper; //right operator
            int pos = -1; //position of loop, needs to be -1 since it increments it each time
            std::string holder = input; //copy of input
    
            std::vector<std::pair<int, char>> vec_copy = oper_pvec;
    
            auto op = oper_pvec.begin();
            while (oper_pvec.size() != 0)
            {
                op = oper_pvec.begin();
                ++pos; //position of loop
                int key = std::get<0>(*op); //gets first value from vector pair
                char val = std::get<1>(*op); //gets second value from vector pair
    
    
                //gets previous/next vector pairs
                std::vector<std::pair<int, char>>::iterator prev_op = oper_pvec.begin();
                std::vector<std::pair<int, char>>::iterator next_op = oper_pvec.end();
    
                if (op != oper_pvec.begin()) prev_op = std::prev(op);
                if (op != oper_pvec.end()) next_op = std::next(op);
    
    
                //extracts the value of pairs
                if (pos > 0)
                {
                    loper_pos = std::get<0>(*prev_op);
                    loper = std::get<1>(*prev_op);
                }
                if (op == oper_pvec.begin()) loper_pos = 0;
    
                if (oper_pvec.size() == 1) roper_pos = input.length();          
                else
                {
                    roper_pos = std::get<0>(*next_op);
                    roper = std::get<1>(*next_op);
                }
    
    
                //replaces numbers and etc with product, only multiplication for now
                switch (val)
                {
                    case 'x':
                    {
                        int lnum_start = loper_pos + 1;
                        if (lnum_start == 1) lnum_start = 0;
    
                        if (loper_pos > 0)
                            if (isdigit(input[loper_pos - 1])) lnum_start = 0;
    
                        int lnum_len = key - (loper_pos + 1);
                        if (lnum_start == 0)
                        {
                            if (key == 1) lnum_len = 1;
                            else lnum_len = key - 1;
                        }
                        lnum = std::stod(input.substr(lnum_start, lnum_len));
    
                        int rnum_start = key + 1;
                        int rnum_len = (roper_pos - 1) - key;
                        rnum = std::stod(input.substr(rnum_start, rnum_len));
    
                        double prod = lnum * rnum;
                        std::string to_string = std::to_string(prod);
                        input.replace(loper_pos, roper_pos, to_string);
                        break;
                    }
                }
    
                //clears the vector and then finds the operators again
                oper_pvec.clear();
                int vpos = 0;
                for (std::string::iterator it = input.begin(); it != input.end(); ++vpos, ++it)
                {
                    if (vpos == input.length())
                    {
                        vpos = 0;
                        break;
                    }
                    switch (*it)
                    {
                        case 'x':
                        {
                            oper_pvec.push_back(std::pair<int, char>(vpos, 'x'));
                            break;
                        }
                        case '/':
                        {
                            oper_pvec.push_back(std::pair<int, char>(vpos, '/'));
                            break;
                        }
                        case '+':
                        {
                            oper_pvec.push_back(std::pair<int, char>(vpos, '+'));
                            break;
                        }
                        case '-':
                        {
                            oper_pvec.push_back(std::pair<int, char>(vpos, '-'));
                            break;
                        }
                    }
                }
            }
            //converts to double then prints on screen
            double out = std::stod(input);
            std::cout << out << std::endl;
        }
    }