2015-03-04 2 views
-1

У меня есть назначение, где мне нужно создать постфиксный калькулятор. Я сталкиваюсь с некоторыми трудностями, что предыдущие вопросы, касающиеся предмета на SO, не покрывали должным образом.Создание постфиксного калькулятора на C++?

Вот пример ввода я хочу обращаться:

12 6 +

2 *

[возврат каретки]

Результат: 36

описания присвоение:

Арифметические выражения, которые мы обычно используем, являются инфиксными выражениями, что означает, что оператор появляется между двумя операндами, как в «4 + 5». В постфиксных выражениях оператор появляется после своих операндов, как в «4 5 +». Вот несколько более сложное постфиксное выражение: «25 12 7 - 2 * /». Эквивалентное выражение инфикса: «25/((12 - 7) * 2)». Результат этого выражения должен быть 2,5 (не использовать целочисленное деление). Постфиксные выражения не требуют скобок.

Напишите программу, которая использует стек для оценки постфиксных выражений. Каждое входное выражение должно вводиться в его собственной строке, а программа должна заканчиваться, когда пользователь вводит пустую строку. Только символы в выражении будут +, -, *, /, цифры и пробелы.

Подсказка: прочитайте постфиксное выражение слева направо. Когда вы читаете номер , нажмите его в стек. Когда вы читаете операнд, поместите верхние два номера из стека, примените к ним оператор и нажмите на результат поверх стека. В конце результат выражения должен быть единственным номером в стеке.

Вот мой код до сих пор:

#include <list> /* Linked Lists */ 
#include <stack> /* Stacks */ 
#include <iostream> /* cout cin */ 


int main() { 

    std::stack< double, std::list<double> > postfixStack; 
    std::string input; 

    std::cout << "Enter a postfix expression: "; 

    std::getline(std::cin, input); 

    while (input != "") { 
     std::cout << "Input expression: " << input << std::endl; 
     for (int i = 0; i<input.length()-1; i++) { 
      if (input.compare(i, 1, " ")) { // should ignore spaces, but doesn't 
       std::cout << "Skipping element " << i << " \n"; 
      } else if (static_cast<int>(input[i]) == input[i]) { // push numbers onto the stack 
       postfixStack.push(static_cast<double>(input[i])); 
       std::cout << "Pushing " << input[i] << " onto the stack.\n"; 
      } else if (input.compare(i, 1, "+")) { // pop two numbers off the stack (1), apply the operator to them (2), and push that onto the stack (3) 
       double operand1 = postfixStack.top(); 
       postfixStack.pop(); 
       double operand2 = postfixStack.top(); 
       postfixStack.pop(); 
       postfixStack.push(operand1 + operand2); 
       std::cout << "Adding " << operand1 << " and " << operand2 << std::endl; 
      } 
     } 
     std::getline(std::cin, input); 
    } 

    if (!postfixStack.empty()) { 
     std::cout << "Result of expression: " << postfixStack.top() << std::endl; 
    } else { 
     std::cout << "It appears that you did not enter an expression to evaluate.\n"; 
    } 

    return 0; 
} 

Syntax highlighting and line numbers on Gist.

Где я изо всех сил:

  • Мои в то время как цикл должен иметь более одной строки согласно спекуляция Первоначально я использовал cin вместо getline, но это представляло противоположную проблему: неограниченные строки для ввода чего-либо вообще, даже при проверке на/r и пустую строку.

  • Я пытаюсь пропустить пробелы в своем цикле, но вместо этого мой условный код пропускает все, что не является пространством.

  • Проверка строковых индексов означает, что я могу использовать только цифры с одной цифрой, что определенно не то, что я хочу. Когда я сталкиваюсь с числом: я думаю, что я мог бы проверить следующий элемент, если это число, то я мог бы объединить их и поднять счетчик циклов. Теоретически, по крайней мере. Я хотел бы получить базовые функции, прежде чем я буду работать над этим.

+0

'std :: istringstream' - ваш друг для этого. –

+0

Ах! Я хотел бы упомянуть, что это домашнее задание: нет струнного потока или повышения. – Lithedreamer

+0

Ох. Хорошо, тогда, читайте по очереди, разбирайте символ строк по символу. –

ответ

1

Мои в то время как цикл должен иметь более чем одну строку ввода в спецификации.

Вы уже нашли getline. Вы можете просто использовать это для чтения целых строк. Этот подход, который вы сделали, выглядит отлично.

Я пытаюсь пропустить пробелы в своем цикле, но вместо этого мой условный код пропускает все, что не является пространством.

Это верно. Вы проверяете результат string::compare, но результат не является логическим, а ненулевой не означает, что строки равны, это означает, что они не равны.

Путь вы выполнили сравнение редко, кстати, и более обычно было бы просто сравнить характер ' ', или использовать isspace или, может быть, isblank.

Проверка строковых индексов означает, что я могу использовать только цифры с одной цифрой, что определенно не то, что я хочу.

Право. Когда вы видите цифру, вы можете ввести вложенный цикл, чтобы прочитать все последующие цифры. Базовый регистр, одноразрядная строка, тривиально преобразуется в число. (Но немного менее тривиально, чем вы думаете, см. Примечание ниже.) И если вы знаете, как определить значение N-разрядной строки (скажем, ABC), вы можете определить значение N + 1-цифры string (допустим, ABCD) умножением на 10 и добавлением значения следующей цифры.

Примечание: static_cast<int>(input[i]) == input[i] всегда верно. Это не значит, что вы думаете. Используйте свой отладчик для проверки значения static_cast<int>(input[i]) для некоторых символов и попытайтесь понять, что делает этот притвор. Когда вы поймете, что это значит, подумайте о другой проверке, которую вы могли бы сделать, и о том, как вы можете использовать это, после проверки символа есть цифра, чтобы определить числовое значение этой цифры.

+0

Спасибо! Я поменялся по сравнению с isspace, который выглядит намного лучше. Я также добавил свои номера в std :: stod, поскольку статическое кастинг давал мне ошибки. Наконец, я заменил статический касторий условным (почему я думаю, что это была хорошая идея?) С isdigit и разработал решение, которое успешно объединяет числа. Кажется, я получаю «завершение с неперехваченным исключением типа std :: out_of_range: basic_string», когда мой отладчик доходит до условия «+». – Lithedreamer