Есть ли функция C, которая может вычислить строковое выражение, определенное в стандартной библиотеке? - PullRequest
2 голосов
/ 16 февраля 2020

Я ищу функцию, которая может преобразовать строковое выражение в целое число, например, fe:

10/2+4*3-(12+5); //Equals 0

в объект типа int со значением 0.

Функция для сложной операции была бы предпочтительнее, даже если час не нужен:

2^(1/2)-99

Есть ли такое определение в стандартной библиотеке C (C89, C90?) , если он скомпилирован)?

Существует ли какая-либо нестандартная библиотека с такой функцией?

Чем больше символов поддерживает выражение, тем лучше.

Но Операция даже basi c, как +, -, *, /, () будет делать.

Ответы [ 3 ]

4 голосов
/ 16 февраля 2020

Есть ли такое определение, определенное в стандартной библиотеке C (C89, C90, если она скомпилирована)?

Нет, даже в более новых стандартных библиотеках C11 или С18.

Есть ли какая-нибудь нестандартная библиотека, в которой есть такая функция?

Я тоже не смог ее найти. Вы должны написать свою собственную функцию для выполнения sh.

Возможно, на первом шаге отсканируйте строку и сохраните каждое значение в ней в отдельной строке.

Как я уже говорил в комментариях, strtol используется для преобразования целочисленного значения, например 11 в строке со значением типа int. Возможно, вам придется использовать это. В библиотеках также есть функция atoi для преобразования целочисленного значения внутри строки в int, но эта функция более восприимчива к ошибкам и не должна использоваться.

Арифмети c операторы также должны храниться в отдельных строках, но позже они будут оцениваться самодельной программой.

Но хорошие примеры и рекомендации можно найти здесь, где пользователю задали аналогичный (если не тот же) вопрос :

C: преобразовать строку математического выражения в целое с результатом

3 голосов
/ 16 февраля 2020

В стандартной библиотеке C нет функции для вычисления арифметических c выражений. Вот быстрая и грязная реализация функции evald для результата double. Он поддерживает 5 классических двоичных операций +, -, *, /, % и возведение в степень с ^, обрабатывает любые глубины скобок, но требует больше работы для унарных + и -.

Легко преобразовать в целое число только арифмети c.

Вот код:

#include <ctype.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>

double evald(const char *s, char **endp) {
    struct operand {
        double val;
        int op, prec;
    } stack[4], *sp, x;
    char *p;

    for (sp = stack;;) {
        if (*s == '(') {
            x.val = evald(s + 1, &p);
            s = p;
            if (*s == ')')
                s++;
        } else {
            x.val = strtod(s, &p);
            s = p;
        }
        while (isspace((unsigned char)*s))
            s++;
        switch (x.op = *s++) {
        case '^': x.prec = 3; break;
        case '*':
        case '/':
        case '%': x.prec = 2; break;
        case '+':
        case '-': x.prec = 1; break;
        default:  x.prec = 0; x.op = 0; s--; break;
        }
        while (sp > stack && x.prec <= sp[-1].prec) {
            switch ((--sp)->op) {
            case '^': x.val = pow(sp->val, x.val); break;
            case '*': x.val = sp->val * x.val; break;
            case '/': x.val = sp->val / x.val; break;
            case '%': x.val = fmod(sp->val, x.val); break;
            case '+': x.val = sp->val + x.val; break;
            case '-': x.val = sp->val - x.val; break;
            }
        }
        if (!x.op) break;
        *sp++ = x;
    }
    if (endp) *endp = (char *)s;
    return x.val;
}

int main(int argc, char *argv[]) {
    if (argc > 1) {
        for (int i = 1; i < argc; i++) {
            printf("%s -> %.17g\n", argv[i], evald(argv[i], NULL));
        }
    } else {
        char buf[100];
        for (;;) {
            printf("eval> ");
            fflush(stdout);
            if (!fgets(buf, sizeof buf, stdin) || (buf[0] == 'q' && buf[1] == '\n'))
                break;
            printf(" -> %.17g\n", evald(buf, NULL));
        }
    }
    return 0;
}
1 голос
/ 17 февраля 2020

Существует ли какая-либо нестандартная библиотека с такой функцией?

GNU bison имеет такой пример. bison - это генератор синтаксических анализаторов и бесплатное программное обеспечение инструмент, генерирующий C файлов.

Вы также можете использовать и вставлять Lua в вашем приложении. Это с открытым исходным кодом , поэтому вы должны изучить его исходный код. Lua в основном кодируется в стандарте C99.

Вы можете написать свой собственный синтаксический анализатор рекурсивного спуска , довольно просто сделать.

Вы можете рассмотреть встраивание GNU Guile или Python в вашем приложении.

Конечно, вы должны использовать лучшую операционную систему, чем устаревшая MS-DOS (или ее альтернатива FreeDOS ). Debian приходит на ум.

Вы можете использовать tiny cc, у него есть библиотека (libtcc), аналогичная вашим потребностям, и вы можете изучить ее источник code.

Вам необходимо прочитать учебники по разбору и компиляции. Книга Дракона приходит на ум. Или, по крайней мере, прочитайте страницу Википедии о разборе и о lexing .

...