Что именно не работает в выражении в интерпретаторе?

У меня возникла проблема с написанием интерпретатора на C++. В частности, он не обрабатывает функцию "z = sqrt(x);". <br/> <br/> Вот мой код: <br/> <pre><code class="cpp">#include &lt;iostream&gt;
#include &lt;string&gt;
#include &lt;sstream&gt;
#include &lt;unordered_map&gt;
#include &lt;cmath&gt;
#include &lt;stdexcept&gt;

using namespace std;

enum DataType { INT, FLOAT };

struct Variable {
    DataType type;
    union {
        int intValue;
        float floatValue;
    } value;
};

unordered_map&lt;string, Variable&gt; variables;

float to_float(const Variable&amp; var) {
    return var.type == INT ? var.value.intValue : var.value.floatValue;
}

int to_int(const Variable&amp; var) {
    if (var.type == FLOAT) throw runtime_error("Cannot convert float to int");
    return var.value.intValue;
}

Variable parse_value(const string&amp; 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&amp; func, const Variable&amp; 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) {
  • 5 ноября 2024 г. 13:53
Ответы на вопрос 2
Ваш код на C++ выглядит очень хорошо структурированным, но, судя по вашему описанию проблемы, вы, вероятно, столкнулись с несколькими возможными ошибками, связанными с обработкой функции `sqrt`. Давайте рассмотрим несколько аспектов, которые могут быть проблемными:

1. **Тип аргумента для математических функций**: В функции `apply_math_function` у вас есть проверка на то, что аргумент должен быть типа `FLOAT`. Однако у вас есть функция `parse_value`, которая допускает создание переменных типа `INT`. Вам нужно убедиться, что преобразование `INT` в `FLOAT` выполняется правильно. Вы можете изменить логику в `apply_math_function`, чтобы принимать `Variable`, независимо от его типа, и приводить его к `float` внутри функции.

2. **Обработка переменной `z`**: Вы нигде не показали, как происходит конкретно присваивание результата `sqrt(x)` в `z`. Вам необходимо удостовериться, что вы правильно присваиваете значение возвращаемого результата из `apply_math_function`.

3. **Проблемы с синтаксисом и структурой**: Обратите внимание на наличие незавершённой функции `perform_operation`. Это может привести к ошибкам при обработке операций, если вы планируете использовать её в коде. Убедитесь, что эта функция завершена (включая возвращение значения и логику работы с различными операциями).

4. **Управление исключениями**: Если происходит ошибка (например, использование функции `sqrt` с отрицательным числом), вы должны иметь механизм для обработки исключений, чтобы избежать падений программы.

Вот пример исправленного кода для функции `apply_math_function`, которая будет работать с переменными типа `INT` и `FLOAT`, а также возможность присвоения значения переменной:

```cpp
Variable apply_math_function(const string& func, const Variable& arg) {
    float argValue = to_float(arg); // Приводим аргумент к float, даже если он INT
    Variable result;
    result.type = FLOAT;

    if (func == "sqrt") {
        if (argValue < 0) throw invalid_argument("Cannot compute sqrt of negative value");
        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;
}
```

Для использования этой функции вам необходимо обеспечить правильную логику для присваивания значения переменной `z` результату вычисления:

```cpp
int main() {
    // Пример кода для инициализации переменной x
    variables["x"] = parse_value("4.0"); // дописываем float значение 4.0 в переменную x

    // Применение функции sqrt к переменной x
    Variable result = apply_math_function("sqrt", variables["x"]);
    
    // Присваивание результата переменной z
    variables["z"] = result;

    cout << "z = " << variables["z"].value.floatValue << endl;
    return 0;
}
```

С этими изменениями ваш код должен корректно обрабатывать вызовы функции `sqrt` и присваивать результат переменной `z`. Убедитесь, что вы обработали все возможные исключения и необходимо проводить тесты на различных входных данных.
Отладчик есть? Или хотя бы отладочный вывод добавьте. Выводите все переменные там, где они меняются. Мне кажется, что вы из строк все пробелы удаляете и у вас segment получается "sqrt(x);". Ведь stringstream будет читать одно слово целиком до пробельного символа, а их там тупо нет. И потом проверка segment == "sqrt" не срабатывает. Но мне лень ваш код запускать, перепроверьте эту гипотезу сами. 

Вообще у вас тут этап токенизации пропущен. Надо сначала разбить входную строку на токены - имена переменных, числа, функции, операторы, скобки, точки с запятой - вот все сущности, что у вас есть в программе. Уже по этому потом разбирать. Вы же пытаетесь и разбор выражения и токенизацию вперемешку сделать и у вас то тут то там что-то ломается.
Похожие вопросы