Загрузка данных
ef MATH_H
#define MATH_H
// ОТДЕЛЬНЫЙ ЗАГОЛОВОЧНЫЙ ФАЙЛ MATH.H ПО ЗАДАНИЮ
double math_sin(double x);
double math_cos(double x);
double math_sqrt(double x);
double math_pow(double x, double y);
#endif
#include "math.h"
#include <cmath>
double math_sin(double x) {
return sin(x);
}
double math_cos(double x) {
return cos(x);
}
double math_sqrt(double x) {
if (x < 0) return 0;
return sqrt(x);
}
double math_pow(double x, double y) {
return pow(x, y);
}
#ifndef CALCULATOR_H
#define CALCULATOR_H
#include <QString>
#include <QMap>
#include "math.h"
// ЛЕКСЕМА (пункт 1)
struct Lexeme {
QString type;
QString value;
int position;
};
// ПАРСЕР
class Parser {
public:
double evaluate(const QString& expression, QMap<QString, double>& variables, QString& error);
};
// КАЛЬКУЛЯТОР С ЗАВИСИМОСТЬЮ (вариант 4)
class Calculator {
public:
explicit Calculator(Parser* parser);
bool setFormula(const QString& formula);
bool compute(double x, double y);
double getResult() const { return result; }
QString getTable();
QString getError() const { return errorMsg; }
// Копирование и перемещение
Calculator(const Calculator& other);
Calculator(Calculator&& other) noexcept;
Calculator& operator=(const Calculator& other);
Calculator& operator=(Calculator&& other) noexcept;
private:
Parser* parser;
QString formula;
double result;
QString errorMsg;
QMap<QString, double> variables;
};
#endif
#include "calculator.h"
#include <cmath>
#include <functional>
double Parser::evaluate(const QString& expr, QMap<QString, double>& vars, QString& error) {
QString str = expr;
// ПОДСТАНОВКА ПЕРЕМЕННЫХ
for (auto it = vars.begin(); it != vars.end(); ++it) {
str.replace(it.key(), "(" + QString::number(it.value()) + ")");
}
int pos = 0;
auto skipSpaces = [&]() {
while (pos < str.length() && str[pos].isSpace()) pos++;
};
auto readNumber = [&]() -> double {
skipSpaces();
int start = pos;
while (pos < str.length() && (str[pos].isDigit() || str[pos] == '.')) pos++;
if (start == pos) return 0;
return str.mid(start, pos - start).toDouble();
};
auto readName = [&]() -> QString {
skipSpaces();
int start = pos;
while (pos < str.length() && str[pos].isLetter()) pos++;
return str.mid(start, pos - start);
};
std::function<double()> parseExpr;
std::function<double()> parseTerm;
std::function<double()> parseFactor;
parseFactor = [&]() -> double {
skipSpaces();
if (pos >= str.length()) return 0;
QChar ch = str[pos];
if (ch.isDigit() || ch == '.') {
return readNumber();
}
if (ch == '(') {
pos++;
double val = parseExpr();
skipSpaces();
if (pos < str.length() && str[pos] == ')') pos++;
return val;
}
if (ch.isLetter()) {
QString name = readName();
// ФУНКЦИИ ИЗ MATH.H
if (name == "sin" || name == "cos" || name == "sqrt" || name == "pow") {
skipSpaces();
if (pos < str.length() && str[pos] == '(') {
pos++;
double arg1 = parseExpr();
double arg2 = 0;
skipSpaces();
if (name == "pow" && pos < str.length() && str[pos] == ',') {
pos++;
arg2 = parseExpr();
}
skipSpaces();
if (pos < str.length() && str[pos] == ')') pos++;
if (name == "sin") return math_sin(arg1);
if (name == "cos") return math_cos(arg1);
if (name == "sqrt") {
if (arg1 < 0) {
error = "Корень из отрицательного";
return 0;
}
return math_sqrt(arg1);
}
if (name == "pow") return math_pow(arg1, arg2);
}
}
return vars.value(name, 0);
}
return 0;
};
parseTerm = [&]() -> double {
double value = parseFactor();
skipSpaces();
while (pos < str.length() && (str[pos] == '*' || str[pos] == '/')) {
char op = str[pos].toLatin1();
pos++;
double next = parseFactor();
if (op == '*') value *= next;
else if (op == '/') {
if (next == 0) {
error = "Деление на ноль";
return 0;
}
value /= next;
}
skipSpaces();
}
return value;
};
parseExpr = [&]() -> double {
double value = parseTerm();
skipSpaces();
while (pos < str.length() && (str[pos] == '+' || str[pos] == '-')) {
char op = str[pos].toLatin1();
pos++;
double next = parseTerm();
if (op == '+') value += next;
else value -= next;
skipSpaces();
}
return value;
};
return parseExpr();
}
// ============ CALCULATOR ============
Calculator::Calculator(Parser* p) : parser(p), result(0) {}
Calculator::Calculator(const Calculator& other)
: parser(other.parser), formula(other.formula),
result(other.result), errorMsg(other.errorMsg), variables(other.variables) {}
Calculator::Calculator(Calculator&& other) noexcept
: parser(other.parser), formula(std::move(other.formula)),
result(other.result), errorMsg(std::move(other.errorMsg)), variables(std::move(other.variables)) {
other.parser = nullptr;
}
Calculator& Calculator::operator=(const Calculator& other) {
if (this != &other) {
parser = other.parser;
formula = other.formula;
result = other.result;
errorMsg = other.errorMsg;
variables = other.variables;
}
return *this;
}
Calculator& Calculator::operator=(Calculator&& other) noexcept {
if (this != &other) {
parser = other.parser;
formula = std::move(other.formula);
result = other.result;
errorMsg = std::move(other.errorMsg);
variables = std::move(other.variables);
other.parser = nullptr;
}
return *this;
}
bool Calculator::setFormula(const QString& f) {
formula = f;
variables.clear();
// ОПРЕДЕЛЕНИЕ ПЕРЕМЕННЫХ
if (formula.contains("x")) variables["x"] = 0;
if (formula.contains("y")) variables["y"] = 0;
// ВЫДЕЛЕНИЕ КОМАНД
if (formula.startsWith("calc ")) formula = formula.mid(5);
if (formula.startsWith("table ")) formula = formula.mid(6);
if (formula == "help") errorMsg = "Команды: sin, cos, sqrt, pow, +, -, *, /";
errorMsg.clear();
return true;
}
bool Calculator::compute(double x, double y) {
if (!parser) {
errorMsg = "Парсер не задан";
return false;
}
variables["x"] = x;
variables["y"] = y;
result = parser->evaluate(formula, variables, errorMsg);
return errorMsg.isEmpty();
}
QString Calculator::getTable() {
QString table = "═══════════════════════════════════\n";
table += " ТАБЛИЦА ЗНАЧЕНИЙ (y = 1)\n";
table += "═══════════════════════════════════════\n";
table += " x │ F(x, y)\n";
table += "─────────────┼─────────────────\n";
for (int x = -5; x <= 5; x++) {
Calculator temp = *this;
Calculator moved = std::move(temp);
if (moved.compute(x, 1.0)) {
table += QString(" %1 │ %2\n").arg(x, 3).arg(moved.getResult(), 8, 'f', 4);
} else {
table += QString(" %1 │ ошибка\n").arg(x, 3);
}
}
table += "═══════════════════════════════════════\n";
return table;
}
#include <QCoreApplication>
#include <QTextStream>
#include "calculator.h"
int main(int argc, char *argv[]) {
QCoreApplication a(argc, argv);
QTextStream cin(stdin);
QTextStream cout(stdout);
cout << "\n╔══════════════════════════════════════╗\n";
cout << "║ ФОРМЕННЫЙ КАЛЬКУЛЯТОР ║\n";
cout << "║ Вариант 4 - ЗАВИСИМОСТЬ ║\n";
cout << "╚══════════════════════════════════════╝\n\n";
Parser parser;
Calculator calc(&parser);
cout << "Функции: sin, cos, sqrt, pow\n";
cout << "Переменные: x, y\n";
cout << "Операции: +, -, *, /, (, )\n\n";
cout << "Введите формулу: ";
cout.flush();
QString formula;
formula = cin.readLine();
if (!calc.setFormula(formula)) {
cout << "Ошибка: " << calc.getError() << "\n";
return 1;
}
cout << "Введите x и y: ";
double x, y;
cin >> x >> y;
if (calc.compute(x, y)) {
cout << "\n▶ РЕЗУЛЬТАТ: " << calc.getResult() << "\n\n";
cout << calc.getTable() << "\n";
} else {
cout << "Ошибка: " << calc.getError() << "\n";
}
return 0;
}
#include <QtTest>
#include "calculator.h"
class CalculatorTest : public QObject {
Q_OBJECT
private slots:
void testAddition() {
Parser parser;
Calculator calc(&parser);
calc.setFormula("2+3");
QVERIFY(calc.compute(0, 0));
QCOMPARE(calc.getResult(), 5.0);
}
void testSin() {
Parser parser;
Calculator calc(&parser);
calc.setFormula("sin(0)");
QVERIFY(calc.compute(0, 0));
QVERIFY(qAbs(calc.getResult() - 0.0) < 0.001);
}
void testCos() {
Parser parser;
Calculator calc(&parser);
calc.setFormula("cos(0)");
QVERIFY(calc.compute(0, 0));
QVERIFY(qAbs(calc.getResult() - 1.0) < 0.001);
}
void testSqrt() {
Parser parser;
Calculator calc(&parser);
calc.setFormula("sqrt(16)");
QVERIFY(calc.compute(0, 0));
QCOMPARE(calc.getResult(), 4.0);
}
void testPow() {
Parser parser;
Calculator calc(&parser);
calc.setFormula("pow(2,3)");
QVERIFY(calc.compute(0, 0));
QCOMPARE(calc.getResult(), 8.0);
}
void testVariables() {
Parser parser;
Calculator calc(&parser);
calc.setFormula("x + y");
QVERIFY(calc.compute(3, 4));
QCOMPARE(calc.getResult(), 7.0);
}
void testCopySemantics() {
Parser parser;
Calculator calc1(&parser);
calc1.setFormula("x * 2");
calc1.compute(5, 0);
Calculator calc2 = calc1;
calc2.compute(10, 0);
QCOMPARE(calc2.getResult(), 20.0);
QCOMPARE(calc1.getResult(), 10.0);
}
void testMoveSemantics() {
Parser parser;
Calculator calc1(&parser);
calc1.setFormula("x * 3");
calc1.compute(4, 0);
Calculator calc2 = std::move(calc1);
calc2.compute(5, 0);
QCOMPARE(calc2.getResult(), 15.0);
}
void testTable() {
Parser parser;
Calculator calc(&parser);
calc.setFormula("x");
QString table = calc.getTable();
QVERIFY(table.contains("x"));
QVERIFY(table.contains("-5"));
}
void testDivisionByZero() {
Parser parser;
Calculator calc(&parser);
calc.setFormula("5/0");
QVERIFY(!calc.compute(0, 0));
QVERIFY(!calc.getError().isEmpty());
}
};
QTEST_APPLESS_MAIN(CalculatorTest)
#include "tst_calculatortest.moc"