|
|
bet | 18/23 | Sana | 21.03.2020 | Hajmi | 326,03 Kb. | | #42712 |
| Bog'liq Короткие примеры C
if (!cin)
{
error("no second argument for operation '");
cerr << op << "'\n";
return x;
}
switch (op) // Вычислить результат операции.
{
case '+': x = x + y; break;
case '-': x = x - y; break;
case '*': x = x * y; break;
case '/': x = x / y; break;
}
break;
case ')': case EOF:
return x;
default:
error("unknown operation: '");
cerr << op << "'\n";
return x;
}
}
}
int main()
{
while (true)
{
double answer = infix();
cin.clear();
cin.ignore(cin.rdbuf()->in_avail());
cin.sync();
cout << "answer = " << answer << endl;
}
return EXIT_SUCCESS;
}
0820-infix_calc_p_stack_std.cpp
// infix_calc_p_stack.cpp
// Инфиксный калькулятор без учёта приоритетов операций, но с поддержкой скобок.
// Пример: 2+(2*2) ==> 6.
// Грамматика:
// Терм --> Число | '(' Выражение ')' // term
// Выражение --> Терм { Операция Терм } // infix
// Конверсия рекурсивного варианта infix_calc_p.cpp в вариант с использованием стека.
// Добавлены операции взятия остатка (реализована через std::fmod) и
// возведения в степень (реализована через std::pow) -- символы '%' и '^'.
#include
#include
#include
using namespace std;
// Вспомогательная функция:
// посмотреть следующий непробельный символ в потоке cin, не извлекая его.
// (Пробельные символы пропускаются. Возвращает EOF если поток закончился.)
char peek()
{
char ch = EOF;
if (cin >> ch)
cin.unget();
return ch;
}
// Вспомогательная функция для установки ошибки.
void error(const char *message)
{
cerr << message;
cin.setstate(ios::failbit);
}
double infix()
{
stack<char> ops; // Стек операций.
stack<double> xs; // Стек операндов.
// Вложенная функция, выполняющая операцию на вершине стека ops.
// Возвращает "успех" (false если произошла ошибка, true если выполнено успешно).
auto do_next_op = [&]() -> bool
{
double x, y;
if (xs.empty())
{
error("not enough operands\n");
return false;
}
y = xs.top();
xs.pop();
if (xs.empty())
{
xs.push(y);
error("not enough operands\n");
return false;
}
x = xs.top();
switch (ops.top())
{
case '+': x = x + y; break;
case '-': x = x - y; break;
case '*': x = x * y; break;
case '/': x = x / y; break;
case '%': x = fmod(x, y); break;
case '^': x = pow(x, y); break;
default:
error("internal error\n");
return false;
}
// Сохранить результат операции вместо операндов на стеке xs.
xs.top() = x;
// Убрать со стека операций выполненную операцию.
ops.pop();
return true;
};
bool awaiting_term = true; // Ожидает терм (true) или операцию (false)?
while (true)
{
if (awaiting_term)
{
double x;
switch (peek())
{
case '-': case '+': case '.':
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
if (!(cin >> x))
{
error("number expected\n");
goto Finish;
}
xs.push(x);
awaiting_term = false;
break;
case '(':
cin.ignore(); // Убрать открывающую скобку из потока.
ops.push('(');
break;
case ')':
error("unmatched ')' found\n");
goto Finish;
default:
error("term expected, '");
cerr << peek() << "' found\n";
goto Finish;
}
}
else
{
switch (char op = peek())
{
case '+': case '-': case '*': case '/': case '%': case '^':
cin.ignore(); // Убрать знак операции с потока.
// Выполнить предыдущую операцию, положить на стек следующую.
if (!ops.empty() && ops.top() != '(' && !do_next_op())
goto Finish;
// Положить на стек операций следующую операцию.
ops.push(op);
// Теперь ожидаем терм.
awaiting_term = true;
break;
case ')':
// Убрать скобку с потока cin.
cin.ignore();
// Выполнять операции, пока не встретится открывающая скобка.
while (true)
{
if (ops.empty())
{
error("unmatched ')' found\n");
goto Finish;
}
if (ops.top() == '(')
{
ops.pop();
break;
}
if (!do_next_op())
goto Finish;
}
break;
case EOF:
// Выполнить все оставшиеся операции.
while (!ops.empty())
{
if (ops.top() == '(')
{
error("unmatched '(' found\n");
break;
}
if (!do_next_op())
break;
}
goto Finish;
default:
error("operation expected: '");
cerr << op << "'\n";
goto Finish;
}
}
}
Finish:
if (xs.empty())
{
error("not enough operands\n");
return 0.;
}
return xs.top();
}
int main()
{
while (true)
{
double answer = infix();
cin.clear();
cin.ignore(cin.rdbuf()->in_avail());
cin.sync();
cout << "answer = " << answer << endl;
}
return EXIT_SUCCESS;
}
0830-infix_calc_shunting_yard.cpp
// infix_calc_shunting_yard.cpp
// Инфиксный калькулятор с учётом приоритетов и ассоциативности операций и поддержкой скобок.
// Пример: 2+(2*2) ==> 6.
// Упрощённая грамматика:
// Терм --> Число | '(' Выражение ')' // term
// Выражение --> Терм { Операция Терм } // infix
// Реализован алгоритм сортировочной станции Э.Дейкстры на основе примера infix_calc_p_stack_std.cpp.
#include
#include
#include
using namespace std;
// Вспомогательная функция:
// посмотреть следующий непробельный символ в потоке cin, не извлекая его.
// (Пробельные символы пропускаются. Возвращает EOF если поток закончился.)
char peek()
{
char ch = EOF;
if (cin >> ch)
cin.unget();
return ch;
}
// Вспомогательная функция для установки ошибки.
void error(const char *message)
{
cerr << message;
cin.setstate(ios::failbit);
}
// Числовой приоритет операции.
int precedence(char op)
{
switch (op)
{
case '+': case '-': return 100;
case '*': case '/': case '%': return 200;
case '^': return 300;
default: return 0;
}
}
// Операция op связывает операнды слева направо?
bool is_left_associative(char op)
{
return op != '^';
}
double infix()
{
stack<char> ops; // Стек операций.
stack<double> xs; // Стек операндов.
// Вложенная функция, выполняющая операцию на вершине стека ops.
// Возвращает "успех" (false если произошла ошибка, true если выполнено успешно).
auto do_next_op = [&]() -> bool
{
double x, y;
if (xs.empty())
{
error("not enough operands\n");
return false;
}
y = xs.top();
xs.pop();
if (xs.empty())
{
xs.push(y);
error("not enough operands\n");
return false;
}
x = xs.top();
switch (ops.top())
{
case '+': x = x + y; break;
case '-': x = x - y; break;
case '*': x = x * y; break;
case '/': x = x / y; break;
case '%': x = fmod(x, y); break;
case '^': x = pow(x, y); break;
default:
error("internal error\n");
return false;
}
// Сохранить результат операции вместо операндов на стеке xs.
xs.top() = x;
// Убрать со стека операций выполненную операцию.
ops.pop();
return true;
};
bool awaiting_term = true; // Ожидает терм (true) или операцию (false)?
while (true)
{
if (awaiting_term) // Ожидается терм.
{
double x;
switch (char ch = peek())
{
// - и + могут стоять перед скобкой (, а не перед числом,
// поэтому обрабатываем этот случай особо.
case '-': case '+':
if (cin.ignore() && cin.peek() == '(')
{
// Имитируем отрицание вычитанием из нуля.
if (ch == '-')
{
xs.push(0);
ops.push('-');
}
cin.ignore(); // Убрать открывающую скобку из потока.
ops.push('(');
Do'stlaringiz bilan baham: |
|
|