Стоит задача, написать интерпретатор на C++. Почему-то он не считает корень "z = sqrt(x);".
Вот код:
#include <iostream>
#include <string>
#include <sstream>
#include <unordered_map>
#include <cmath>
#include <stdexcept>
using namespace std;
enum DataType { INT, FLOAT };
struct Variable {
DataType type;
union {
int intValue;
float floatValue;
} value;
};
unordered_map<string, Variable> variables;
float to_float(const Variable& var) {
return var.type == INT ? var.value.intValue : var.value.floatValue;
}
int to_int(const Variable& var) {
if (var.type == FLOAT) throw runtime_error("Cannot convert float to int");
return var.value.intValue;
}
Variable parse_value(const string& str) {
Variable result;
if (str.find('.') == string::npos) {
result.type = INT;
result.value.intValue = stoi(str);
}
else {
result.type = FLOAT;
result.value.floatValue = stof(str);
}
return result;
}
Variable apply_math_function(const string& func, const Variable& arg) {
if (arg.type == INT) throw invalid_argument("Math functions require float arguments");
float argValue = arg.value.floatValue;
Variable result;
result.type = FLOAT;
if (func == "sqrt") result.value.floatValue = sqrt(argValue);
else if (func == "sin") result.value.floatValue = sin(argValue);
else if (func == "cos") result.value.floatValue = cos(argValue);
else throw invalid_argument("Unknown function: " + func);
return result;
}
Variable perform_operation(Variable lhs, char op, Variable rhs) {
Variable result;
if (lhs.type == FLOAT || rhs.type == FLOAT) {
float left = to_float(lhs);
float right = to_float(rhs);
result.type = FLOAT;
switch (op) {
case '+': result.value.floatValue = left + right; break;
case '-': result.value.floatValue = left - right; break;
case '*': result.value.floatValue = left * right; break;
case '/': result.value.floatValue = left / right; break;
case '^': result.value.floatValue = pow(left, right); break;
default: throw invalid_argument("Unknown operator: " + string(1, op));
}
}
else {
int left = to_int(lhs);
int right = to_int(rhs);
result.type = INT;
switch (op) {
case '+': result.value.intValue = left + right; break;
case '-': result.value.intValue = left - right; break;
case '*': result.value.intValue = left * right; break;
case '/': result.value.intValue = left / right; break;
case '^': result.value.intValue = pow(left, right); break;
default: throw invalid_argument("Unknown operator: " + string(1, op));
}
}
return result;
}
Variable eval_expr(string expr) {
istringstream iss(expr);
Variable result = parse_value("0");
char op = '+';
string segment, func;
while (iss >> segment) {
if (segment == "+" || segment == "-" || segment == "*" || segment == "/" || segment == "^") {
op = segment[0];
}
else if (segment == "sqrt" || segment == "sin" || segment == "cos") {
func = segment;
}
else if (isdigit(segment[0]) || segment.find('.') != string::npos) {
Variable value = parse_value(segment);
if (!func.empty()) {
value = apply_math_function(func, value);
func = "";
}
result = perform_operation(result, op, value);
}
else if (variables.find(segment) != variables.end()) {
Variable value = variables[segment];
result = perform_operation(result, op, value);
}
}
return result;
}
int main() {
string script = R"(
x = 5;
x = x + 1;
y = x * x + 12.5;
z = sqrt(x);
)";
istringstream iss(script);
string line;
while (getline(iss, line)) {
size_t eqPos = line.find('=');
if (eqPos != string::npos) {
string var = line.substr(0, eqPos);
var.erase(remove_if(var.begin(), var.end(), ::isspace), var.end());
string expr = line.substr(eqPos + 1);
variables[var] = eval_expr(expr);
}
}
for (const auto& kv : variables) {
cout << kv.first << ": ";
if (kv.second.type == INT)
cout << kv.second.value.intValue;
else
cout << kv.second.value.floatValue;
cout << endl;
}
return 0;
}