How to perform an algebraic expression on a string in C [duplicate]

3

My program has the following purpose:

Given a function, my program replaces the 'X (s)' of the function with any number.

The code below exemplifies what was said.

//funcao a ser trabalhada
char funcao[150]  = "(x^2)*5";
int tamanho = strlen(funcao);

//Substitui o x da funcao por um valor dado
    for(int i = 0; i < tamanho; i++) {
        if(funcao[i] == 'x')
            funcao[i] = '2';
    }

The result of this procedure returns me the string "(2 ^ 2) * 5".

How to calculate this equation?

    
asked by anonymous 25.09.2015 / 00:30

2 answers

4

If you are not limited to the basic standard and you can use POSIX (which describes the popen () ), then passes the string to an external calculator, for example bc .

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int calculo(const char *expression) {
    FILE *bc;
    char command[1000];
    char result[1000];

    snprintf(command, sizeof command, "echo '%s' | bc", expression);
    bc = popen(command, "r");
    if (!bc) return -1;
    if (!fgets(result, sizeof result, bc)) return -1;
    pclose(bc);
    return strtol(result, NULL, 10);
}

int main(void) {
    // funcao a ser trabalhada
    char funcao[150] = "(x^2)*5";
    int tamanho = strlen(funcao);

    // Substitui o x da funcao por um valor dado
    int i;
    for (i = 0; i < tamanho; i++) {
        if (funcao[i] == 'x') funcao[i] = '2';
    }
    int valor = calculo(funcao);
    printf("%s ==> %d\n", funcao, valor);
    return 0;
}

On my machine, the result of the executable is

% ./a.out
(2^2)*5 ==> 20
    
25.09.2015 / 10:56
6

The usual ways to resolve this problem is by typing a parser (like suggested by bigown ; a simple example - in JavaScript - here ) that generates an abstract representation of the data, or perhaps converting the expression to # in a simpler parsing process and then evaluating it (here is a PDF with instructions, in Pascal - I do not know the source well, I found it in Google).

The first form is more flexible (in the related question, the result was used to solve simple equations of the second degree), but the second one is simpler. I'm going to give a simplified explanation explanation here (since implementing C is a little chatty, especially for me that I have little experience) along with links to implementation references, so you can study them further .

  • The goal of postfix notation is to pass all operators to the end - and not to the middle - of their operands. For example the expression:

      

    1 + 2 * 3

    It would look like this in the postfix notation:

    1 2 3 * +
    

    Now the expression:

      

    (1 + 2) * 3

    It would look like this:

    1 2 + 3 *
    

    Etc. To interpret these expressions, consider that each operator applies to the last two operands read, removing them from the list and replacing all by the result of the operation. The next operator does the same, and the process continues until only on a single number in the list (details below).

    One advantage of this notation is that parentheses are unnecessary - any expression can be represented in a way that the calculation occurs in the correct order you want.

    • The conversion between the infix and postfix formats can be done through the shunting-yard algorithm . p>

      To understand this, consider that each operator has both a precedence and a associativity : times apply first, for example, and both join on the left. A - B - C is applied as (A - B) - C and not as A - (B - C) , but A^B^C applies as A^(B^C) and not vice versa. Sub-expressions in parentheses apply before the rest.

      The algorithm works by reading each token (number, operator, parentheses, or parentheses) of the input and then placing it either on output or on a stack. Numbers always go out. Operators go to the stack, but rather they pull out any stack whose precedence is less or less-or equal to it (depending on associativity). Open brackets go to the stack, and closes parentheses by scrolling all the way to the corresponding parentheses and throws the output.

      1 + 2 * 3     []
      _ + 2 * 3     []       1
        _ 2 * 3     [+]      1
          _ * 3     [+]      1 2
            _ 3     [+, *]   1 2
              _     [+, *]   1 2 3
                    [+]      1 2 3 *
                    []       1 2 3 * +
      
      (1 + 2) * 3   []
      _1 + 2) * 3   [(]
       _ + 2) * 3   [(]      1
         _ 2) * 3   [(, +]   1
           _) * 3   [(, +]   1 2
            _ * 3   []       1 2 +
              _ 3   [*]      1 2 +
                _   [*]      1 2 + 3
                    []       1 2 + 3 *
      
      1 + 2*3 / (4 ^ (5+6) )   []
      _ + 2*3 / (4 ^ (5+6) )   []                   1
        _ 2*3 / (4 ^ (5+6) )   [+]                  1
          _*3 / (4 ^ (5+6) )   [+]                  1 2
           _3 / (4 ^ (5+6) )   [+, *]               1 2
            _ / (4 ^ (5+6) )   [+, *]               1 2 3
              _ (4 ^ (5+6) )   [+, /]               1 2 3 *
                _4 ^ (5+6) )   [+, /, (]            1 2 3 *
                 _ ^ (5+6) )   [+, /, (]            1 2 3 * 4
                   _ (5+6) )   [+, /, (, ^]         1 2 3 * 4
                     _5+6) )   [+, /, (, ^, (]      1 2 3 * 4
                      _+6) )   [+, /, (, ^, (]      1 2 3 * 4 5
                       _6) )   [+, /, (, ^, (, +]   1 2 3 * 4 5
                        _) )   [+, /, (, ^, (, +]   1 2 3 * 4 5 6
                         _ )   [+, /, (, ^]         1 2 3 * 4 5 6 +
                           _   [+, /]               1 2 3 * 4 5 6 + ^
                               [+]                  1 2 3 * 4 5 6 + ^ /
                               []                   1 2 3 * 4 5 6 + ^ / +
      

      C-Sample in rosettacode .

  • To evaluate an expression in postfix notation, you need to use a stack. Each read element is stacked, if it is a number, and if it is an operator it pops up two numbers and applies the operator on it:

    1 2 3 * +    []
    _ 2 3 * +    [1]
      _ 3 * +    [1, 2]
        _ * +    [1, 2, 3]
          _ +    [1, (2*3)] -> [1, 6]
            _    [(1+6)]    -> [7]
    
    1 2 + 3 *    []
    _ 2 + 3 *    [1]
      _ + 3 *    [1, 2]
        _ 3 *    [(1+2)] -> [3]
          _ *    [3, 3]
            _    [(3*3)] -> [9]
    
    1 2 3 * 4 5 6 + ^ / +   []
    _ 2 3 * 4 5 6 + ^ / +   [1]
      _ 3 * 4 5 6 + ^ / +   [1, 2]
        _ * 4 5 6 + ^ / +   [1, 2, 3]
          _ 4 5 6 + ^ / +   [1, (2*3)] -> [1, 6]
            _ 5 6 + ^ / +   [1, 6, 4]
              _ 6 + ^ / +   [1, 6, 4, 5]
                _ + ^ / +   [1, 6, 4, 5, 6]
                  _ ^ / +   [1, 6, 4, (5+6)] -> [1, 6, 4, 11]
                    _ / +   [1, 6, (4^11)] -> [1, 6, 4194304]
                      _ +   [1, (6/4194304)] -> [1, 0.00000143]
                        _   [(1+0.00000143)] -> [1.00000143]
    

    C-Sample in rosettacode .

  • 25.09.2015 / 02:37