Странная функция возвращает результат

#c #function

#c #функция

Вопрос:

 float Calculate(const string amp;query)
{
        std::cout << "Query: " << query << "n";
        unsigned int size = query.length();
        char stack[70];
        float res;
        int m = 0;

        for (int i = 0; i < size; i  )
        {
                if (query[i] >= '0' amp;amp; query[i] <= '9')
                {
                        stack[m] = query[i] - '0';
                        m  ;
                        continue;
                }

                switch (query[i])
                {
                        case ' ':
                        {
                                res = stack[m - 2]   stack[m - 1];
                                break;
                        }
                        case '-':
                        {
                                res = stack[m - 2] - stack[m - 1];
                                break;
                        }
                        case '*':
                        {
                                res = stack[m - 2] * stack[m - 1];
                                break;
                        }
                        case '/':
                        {
                                res = stack[m - 2] / stack[m - 1];
                                break;
                        }
                }

                    stack[m - 2] = res;
                m--;
                cout << "RES: " << res << "n";
        }

        return res;
}
  

Она вычисляет обратную польскую нотацию.

Когда я вызываю что-то вроде: Calculate("11 ") это возвращает правильный результат: 2 .

Но, когда я передаю переменную после получения строки RPN:

 string inputStr;
string outputStr;

cout << "Put exercisen";
getline(std::cin, inputStr);

outputStr = GetRPN(inputStr);
cout << "Output str :" << outputStr << ":n";

float res = Calculate(outputStr);
std::cout << res << "n";
  

Итак, когда я ввожу string: 1 1 , функция GetRPN возвращает 11 , и я вижу это во втором cout. Но результат есть 0 !

Что бы это могло быть?


 string GetRPN(string input)
{
    vector <char> operation;
    string outputStr;      //output string, keep RPN
    int stack_count = 0;

    for(int i = 0; i < input.length(); i  )
    {
        if(input[i] >= '0' amp;amp; input[i] <= '9')
        {
            outputStr  = input[i];
        }
        else
        {
            if(operation.empty())
            {
                operation.push_back(input[i]);
                stack_count  ;
            }
            else if(operation[stack_count - 1] == ' ' || operation[stack_count - 1] == '-')
            {
                operation.push_back(input[i]);
                stack_count  ;
            }
            else if ((operation[stack_count - 1] == '*' || operation[stack_count - 1] == '/') amp;amp; (input[i] == '*' || input[i] == '/'))
            {
                outputStr  = operation[stack_count - 1]; // move mark of operation to output str
                operation.pop_back(); // delet last element from vector
                operation.push_back(input[i]);// plus new operation mark to vector
                stack_count  ;
            }
            else if (operation[stack_count - 1] == '*' || operation[stack_count - 1] == '/')
            {
                outputStr  = input[i];
            }
        }
    }

    for(int i = operation.size(); i >= 0; i--)
    {
        outputStr  = operation[i]; // move all operation marks to otput str
    }

    return outputStr;
}
  

Комментарии:

1. Убедитесь, что у вас нет завершающих пробелов или других «мусорных» символов-пробелов, возвращающихся из GetRPN — вы можете распечатать длину.

2. Не уверен, что GetRPN делает, но это может оставить окончательное n или r в строке outputStr , которое не может быть сопоставлено в switch (query[i]) , оставляя res каким-то образом null…

3. Ваш Calculate() выглядит нормально, и при идентичном вводе должен выдаваться тот же результат. Можете ли вы также опубликовать свою GetRPN() функцию?

4. Я никогда не знал, что std::string есть lenght() функция-член, которая возвращает то же значение, что и size() .

5. Заключительный цикл GetRPN выглядит подозрительно — вы не хотите начинать с i = operation.size()-1? Если у вас есть строка из 2 символов, вы хотите добавить только элементы 1 и 0, а не 2, 1 и 0. Однако это не объясняет, почему вы видите правильный вывод.

Ответ №1:

Ваш цикл здесь

 for(int i = operation.size(); i >= 0; i--)
{
    outputStr  = operation[i]; // move all operation marks to otput str
}
  

не имеет никакого смысла. Очевидно, что вы пытаетесь получить доступ к вектору с недопустимым индексом. Недопустимо обращаться к элементу в момент, когда operation[i] значение i равно operation.size() . Индекс находится вне диапазона.

Любая уважающая себя реализация немедленно сообщила бы об этой проблеме с утверждением. В любом случае, как я сказал в комментарии, подобные проблемы решаются путем отладки кода. Почему вы просите других людей отлаживать ваш код вместо того, чтобы делать это самостоятельно?

Ответ №2:

Если в вашей строке есть какие-либо пробелы или непечатаемые символы, вы в конечном итоге сохраните в stack с отрицательным индексом, что перезапишет другие данные в вашем фрейме стека и может привести к тому, что что-нибудь произойдет.

Вам следует добавить некоторую проверку ошибок в Calculate — переключатель должен иметь default , который выводит разумное сообщение об ошибке, и вы должны проверить значение m перед обращением к stack[m] or stack[m-2] , чтобы убедиться, что стек не переполняется (и вы должны напечатать разумную ошибку, если это произойдет.) Вы должны быть в состоянии передать ЛЮБУЮ случайную строку для вычисления и заставить ее сообщить вам, почему это недопустимое выражение RPN.