Рекурсивная функция для преобразования строки, содержащей математику, в целое число - PullRequest
0 голосов
/ 29 марта 2020

Если у меня есть строка 4+6*7/2 Мне нужна функция, которая вычисляет значение, в данном случае 25. Для этого я написал рекурсивную функцию, которая анализирует строку символ за символом.

Основа Алгоритм c работает (или должен go) так: если символ, который мы анализируем сейчас, является обычным шифром, и мы не встретили оператор (+, -, *, /), мы сохраняем его в строке с именем first_nr, который в конечном итоге станет номером на левой стороне оператора. Это мы делаем, пока не встретим оператора. Если мы сталкиваемся с оператором, мы сохраняем, какой это был оператор, поэтому мы знаем, что делать позже. Поскольку мы столкнулись с оператором, теперь мы должны добавить следующие числа в другую строку с именем second_nr, которая в конечном итоге станет номером справа от оператора. [Я реализовал до сих пор] Конечно, нам также нужно учитывать порядок вычислений, поэтому я сначала проигнорирую все плюсы и минусы, пока не будут проанализированы все времена и деления.

Таким образом, если у меня есть, например, следующая строка действия: 123+789+4. Моя функция сначала помещает 123 в first_nr, затем видит оператора и сохраняет + в operator. Потому что operator != NULL теперь добавляет следующие цифры: от 789 до second_str. Объединяя эти три параметра, мы могли бы сформировать first_nr + operator + second_str в этом случае 123+789. Моя программа должна выполнить это до того, как встретит следующий оператор, поэтому в этом случае она сформирует 912+4, и рекурсия повторяется.

Я приложил усилие, но в ней все еще есть много дыр. Сейчас я был бы счастлив, если бы смог запустить строку 12+5. Поэтому игнорируйте все операторы, кроме «плюс», игнорируйте порядок вычислений (первые разы и деления, чем «плюс» и «мин») и игнорируйте несколько операторов в одной строке.

Если я могу получить наибольшую c строку, запущенную Я улучшу свой алгоритм для работы с более сложными строками.

Мои усилия:

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

//Enumeration of all the possible
//math operators
enum Operator {
    PLUS,
    MIN,
    TIMES,
    DIVIDE,
    UNDEFINED
};




/************************IGNORE********************/
Operator charToOperator(char c) {
    switch(c) {
        case '+':
            return Operator::PLUS;
            break;
        case '-':
            return Operator::MIN;
            break;
        case '*':
            return Operator::TIMES;
            break;
        case '/':
            return Operator::DIVIDE;
            break;
        default:
            return Operator::UNDEFINED;
            break;
    }
}
/***************************************************/

/*
 * Recursive function performing all the calculations from an action string.
 * For example, if the string actions has value "5+7" in the first recursive run
 * result should contain 12 after the last recursion.
 *
 * :param result: Double containing the calculated result after the last recursion
 * :param actions: Action string (what you type in your calculator; e.g: 5+5). We analyze the first character of this string each time and add it to first_nr, second_nr, or make it the operator. First character gets deleted after each recursion
 * :param first_nr: Empty at first recursion, number of left side of the operator. So in 55+77 this paramater will be "55". Gets resetted at the next operator
 * :param second_nr: Idem as first_nr but for the right side of the operator.
 * :param oper: Operation to calculate the first_nr and second_nr
 */
int calculate(double& result, std::string& actions, std::string& first_nr, std::string& second_nr, Operator& oper) {
    //Base-condition:
    //If action string is empty return 
    if (actions == "") {
       return result;
    }

    //Get first character from action string
    char c = actions[0];

    //If first character is an operator
    char operatorInChar[] = {'+', '-', '*', '/'};
    if (std::find(std::begin(operatorInChar), std::end(operatorInChar), c) != std::end(operatorInChar)) {
        //If operator is not yet set in a previous recursion
        if (oper == NULL || oper == Operator::UNDEFINED) {
            oper = charToOperator(c);

            //If second_nr is not empty, we need to calculate the two numbers together
            if (second_nr != "") {
                //Update result
                result = std::stod(first_nr) + std::stod(second_nr); //For now we only implement plus

                //Calculation is done, so reset first_nr, second_nr and operator
                //for the next 'first_nr [operator] second_nr' block in the action string
                first_nr = "";
                second_nr = "";
                oper = Operator::UNDEFINED;
            }
        }
    } else {
        //If the character is not a operator but a number we append it to the correct nr
        //we add to first_nr if the operator is not yet set, if we already encountered an operator
        //we add to second_nr.
        //e.g: actions = "123+789"

        if (oper == NULL || oper == Operator::UNDEFINED) {
            first_nr += c;
        } else {
            second_nr += c;
        }

    }

    //Remove first character from action string because it's analysed in this recursion
    actions = actions.erase(0, 1);

    //Make recursive call
    return calculate(result, actions, first_nr, second_nr, oper);
}

int main() {
    //String we want to calculate
    std::string str = "5+7";
    std::string str_copy_for_output = str;

    //Variables
    double result = 0;
    std::string first_nr = "";
    std::string second_nr = "";
    Operator oper = Operator::UNDEFINED;

    //Call function
    int calculation = calculate(result, str, first_nr, second_nr, oper);

    //Output
    std::cout << str_copy_for_output << " = " << calculation << std::endl;

    return 0;
}


Проблема в том, что result всегда равно 0. Любая помощь будет принята с благодарностью!

1 Ответ

0 голосов
/ 29 марта 2020

Пошаговая программа (с отладчиком, printf s тут и там, или хотя бы мысленно). Несколько интересных моментов по порядку:

  1. oper НЕ УКАЗАН (это не может быть NULL, кстати, поскольку это не указатель; компилятор может предупредить вас), first_nr это "", second_nr это "", действия: "5 + 7".
  2. first_nr += c; выполнено.
  3. оператор НЕ УКАЗАН, first_nr - "5", second_nr - "", действие - "+7".
  4. oper = charToOperator(c); выполняется.
  5. oper - PLUS, first_nr - "5", second_nr - "", действие - "7".

Упс! «+» больше не находится в actions, поэтому actions[0] никогда не будет найден в operatorInChar, и эта ветвь больше не будет выполняться. Возможно, вам потребуется выполнить его дополнительно в конце строки.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...