if (cin >> op)
{
// Считали знак операции?
if (strchr("+-*/", op))
{
// Вычислить операнды.
double x = prefix(), y = prefix();
// Вычислить результат выполнения операции.
switch (op)
{
case '+': return x + y;
case '-': return x - y;
case '*': return x * y;
case '/': return x / y;
}
}
else // не знак операции -- вернуть считанный символ
cin.unget();
}
// Число?
double value;
if (cin >> value)
return value;
// Ошибка ввода.
cerr << "input error\n";
return 0.;
}
int main()
{
while (true)
{
double answer = prefix();
// Сброс потока ввода.
cin.clear();
cin.ignore(cin.rdbuf()->in_avail());
cin.sync();
// Вывод ответа.
cout << "answer = " << answer << endl;
}
return EXIT_SUCCESS;
}
0770-postfix_calc.cpp
// postfix_calc.cpp
// Рекурсивная реализация калькулятора с поддержкой четырёх арифметических действий,
// принимающего выражения в постфиксной записи (она же "обратная польская нотация").
// Грамматика выражения: операнд операнд операция, где операнд может быть числом или опять выражением
// Например, 4 3 2 * + ==> 4 + (3 * 2) == 10
#include
using namespace std;
// Читает выражение из потока cin, возвращает вычисленное значение.
// Для того, чтобы суметь выполнить прочитанную операцию, надо получить уже ранее прочитанные операнды.
// Эти операнды передадим через параметры x (первый операнд), y (второй операнд).
double postfix(double x = 0., double y = 0.)
{
// Операция?
char op;
if (cin >> op)
{
switch (op)
{
// Вычислить значение выражения (операнды уже известны -- x, y) и вернуть результат.
case '+': return x + y;
case '-': return x - y;
case '*': return x * y;
case '/': return x / y;
// Не операция? вернуть считанный символ в поток.
default: cin.unget();
}
}
// Число?
double z;
if (cin >> z)
return postfix(x, postfix(y, z));
// Новые операнды -- y и считанное z.
// Но x тоже никуда не делся. После того, как будет вычислено значение над ним,
// может быть считана операция, которая задействует x. Отсюда второй рекурсивный вызов.
// Этот последний вызов является хвостовым и может быть раскрыт в цикл.
// Иначе конец ввода или ошибка, вернём последнее вычисленное значение (операнд y).
return y;
}
int main()
{
while (true)
{
double answer = postfix();
// Сброс потока.
cin.clear();
cin.ignore(cin.rdbuf()->in_avail());
cin.sync();
// Вывод ответа.
cout << "answer = " << answer << endl;
}
return EXIT_SUCCESS;
}
0771-postfix_calc_tc.cpp
// postfix_calc_tc.cpp
// Рекурсивная реализация калькулятора с поддержкой четырёх арифметических действий,
// принимающего выражения в постфиксной записи (она же "обратная польская нотация").
// Грамматика выражения: операнд операнд операция, где операнд может быть числом или опять выражением
// Например, 4 3 2 * + ==> 4 + (3 * 2) == 10
// От postfix_calc.cpp отличается тем, что один из рекурсивных вызовов раскрыт в цикл.
#include
using namespace std;
// Читает выражение из потока cin, возвращает вычисленное значение.
// Для того, чтобы суметь выполнить прочитанную операцию, надо получить уже ранее прочитанные операнды.
// Эти операнды передадим через параметры x (первый операнд), y (второй операнд).
double postfix(double x = 0., double y = 0.)
{
while (true)
{
// Операция?
char op;
if (cin >> op)
{
switch (op)
{
// Вычислить значение выражения (операнды уже известны -- x, y) и вернуть результат.
case '+': return x + y;
case '-': return x - y;
case '*': return x * y;
case '/': return x / y;
// Не операция? вернуть считанный символ в поток.
default: cin.unget();
}
}
// Число?
double z;
if (cin >> z)
y = postfix(y, z);
else
return y;
}
}
int main()
{
while (true)
{
double answer = postfix();
// Сброс потока.
cin.clear();
cin.ignore(cin.rdbuf()->in_avail());
cin.sync();
// Вывод ответа.
cout << "answer = " << answer << endl;
}
return EXIT_SUCCESS;
}
0780-postfix_calc_stack.cpp
// postfix_calc_stack.cpp
// Реализация калькулятора с поддержкой четырёх арифметических действий,
// принимающего выражения в постфиксной записи (она же "обратная польская нотация").
// Грамматика выражения: операнд операнд операция, где операнд может быть числом или опять выражением
// Например, 4 3 2 * + ==> 4 + (3 * 2) == 10
// От postfix_calc.cpp отличается тем, что вместо рекурсии и неявного использования стека вызовов
// для хранения промежуточных результатов (операндов) используется явный стек чисел в виде
// статического массива (размер зафиксирован в момент компиляции).
#include
#include // strchr
using namespace std;
// Читает выражение из потока cin, возвращает вычисленное значение.
double postfix()
{
static const unsigned STACK_SIZE = 1024; // Размер стека.
double operand[STACK_SIZE]; // Стек (на основе массива).
unsigned operand_top = 0; /* Индекс элемента массива,
который станет вершиной стека при добавлении элемента. */
while (true)
{
// Операция?
char op;
if (cin >> op)
{
double z;
if (strchr("+-*/", op))
{
// Убедиться, что в стеке есть хотя бы два числа.
if (operand_top < 2)
{
cerr << "stack underflow: at least 2 items are needed\n";
break;
}
// Извлечь операнды (для сокращения записи).
const double
x = operand[operand_top - 2],
y = operand[operand_top - 1];
operand_top -= 2;
// Вычислить значение выражения (операнды уже известны -- x, y).
switch (op)
{
case '+': z = x + y; break;
case '-': z = x - y; break;
case '*': z = x * y; break;
case '/': z = x / y; break;
}
// Записать новое значение в стек.
operand[operand_top++] = z;
// Проверить переполнение стека.
if (operand_top == STACK_SIZE)
{
cerr << "stack overflow\n";
break;
}
}
else // Не операция? вернуть считанный символ в поток.
{
cin.unget();
// Число?
if (cin >> z)
{
// Записать новое значение в стек.
operand[operand_top++] = z;
// Проверить переполнение стека.
if (operand_top == STACK_SIZE)
{
cerr << "stack overflow\n";
break;
}
}
else // Ошибка ввода.
break;
}
}
else // Ошибка ввода.
break;
}
// Вернуть текущую вершину стека.
if (operand_top == 0) // Стек пуст.
{
cerr << "stack underflow: at least 1 item is needed\n";
return 0.;
}
return operand[operand_top - 1];
}
int main()
{
while (true)
{
double answer = postfix();
// Сброс потока.
cin.clear();
cin.ignore(cin.rdbuf()->in_avail());
cin.sync();
// Вывод ответа.
cout << "answer = " << answer << endl;
}
return EXIT_SUCCESS;
}
0781-postfix_calc_stack_std.cpp
// postfix_calc_stack_std.cpp
// Реализация калькулятора с поддержкой четырёх арифметических действий,
// принимающего выражения в постфиксной записи (она же "обратная польская нотация").
// Грамматика выражения: операнд операнд операция, где операнд может быть числом или опять выражением
// Например, 4 3 2 * + ==> 4 + (3 * 2) == 10
// От postfix_calc_stack.cpp отличается тем, что вместо статического массива (размер зафиксирован в момент компиляции)
// для хранения промежуточных результатов (операндов) используется стек чисел на основе стандартного класса stack,
// автоматически увеличивающийся по мере надобности (располагает данные в динамической памяти).
#include
#include // strchr
#include
using namespace std;
// Читает выражение из потока cin, возвращает вычисленное значение.
double postfix()
{
stack<double> operands; // Стек операндов.
while (true)
{
// Операция?
char op;
if (cin >> op)
{
double x, y, z;
if (strchr("+-*/", op))
{
// Извлечь операнды, проверяя их наличие.
if (operands.empty())
goto Stack_underflow_error;
y = operands.top();
operands.pop();
if (operands.empty())
goto Stack_underflow_error;
x = operands.top();
operands.pop();
// Вычислить значение выражения (операнды уже известны -- x, y).
switch (op)
{
case '+': z = x + y; break;
case '-': z = x - y; break;
case '*': z = x * y; break;
case '/': z = x / y; break;
}
// Записать новое значение в стек.
operands.push(z);
}
else // Не операция? вернуть считанный символ в поток.
{
cin.unget();
// Число?
if (cin >> z)
operands.push(z);
Do'stlaringiz bilan baham: |