【问题标题】:Overwrite the elements in a vector without specifying specific elements覆盖向量中的元素而不指定特定元素
【发布时间】:2021-03-15 13:56:23
【问题描述】:

我正在制作一个同时接受多个运算符的计算器。我有一个向量对,用于存储运算符的位置和运算符的类型。由于结果替换了输入字符串的一部分,因此先前的位置不再有效,因此必须在每次循环后更新向量。

我尝试使用clear() 使其重新从头开始,但结果为Expression: vector iterators incompatible。我认为我不能使用std::replace,因为字符串中的运算符数量在每次循环后都会发生变化。有没有办法让它从头开始并覆盖任何现有元素?

#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;
    }
}

【问题讨论】:

  • 请创建一个minimal, reproducible example - 定义您的期望、您尝试修改但失败的代码等。
  • 无关,但可以使用oper_pvec.push_back({vec_pos, '/'}) 使代码紧凑。
  • 这并没有解决问题,但由于input 是用std::cin &gt;&gt; input 读取的,因此其中不会有任何空格。流提取器在遇到空格时停止。因此,该循环无需删除空格。
  • 您可能会得到两个向量,一个用于操作数,一个用于运算符,而不是存储字符串位置。 (尤其是当您不处理括号时;使用括号,构建一棵树)。
  • 您能否提及示例输入、您获得的输出/错误以及所需的输出。

标签: c++ vector io stdvector std-pair


【解决方案1】:

不是真正的标题答案,而是我没有尝试覆盖向量,而是继续使用clear()并将while循环更改为oper_pvec.size() != 0

(完整的代码,因为我必须更改很多东西才能使其正常工作)

#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;
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-30
    相关资源
    最近更新 更多