Análisis de string de símbolos a expresión

Dada una expresión como una string str que consta de números y operadores aritméticos básicos (+, -, *, /), la tarea es resolver la expresión. Tenga en cuenta que los números utilizados en este programa son números de un solo dígito y no se permiten paréntesis.
Ejemplos: 
 

Entrada: str = “3/3+4*6-9” 
Salida: 16 
Dado que (3/3) = 1 y (4 * 6) = 24. 
Entonces la expresión general se convierte en (1 + 24 – 9) = 16
Entrada : string = “9*5-4*5+9” 
Salida: 16 
 

Enfoque: se crea una clase Stack para almacenar números y operadores (ambos como caracteres). La pila es un mecanismo de almacenamiento útil porque, al analizar expresiones, es necesario acceder con frecuencia al último elemento almacenado; y una pila es un contenedor de último en entrar, primero en salir (LIFO).
Además de la clase Stack, también se crea una clase llamada express (abreviatura de expresión), que representa una expresión aritmética completa. Las funciones miembro de esta clase permiten al usuario inicializar un objeto con una expresión en forma de string, analizar la expresión y devolver el valor aritmético resultante.
Así es como se analiza una expresión aritmética. 
un punterose inicia a la izquierda y se itera para observar cada carácter. Puede ser un número (siempre un carácter de un solo dígito entre 0 y 9) o un operador (los caracteres +, -, * y /).
Si el carácter es un número, se coloca en la pila. El primer operador encontrado también se empuja a la pila. El truco es que se manejan los operadores posteriores. Tenga en cuenta que el operador actual no se puede ejecutar porque el número que le sigue aún no se ha leído. Encontrar un operador es simplemente la señal de que podemos ejecutar el operador anterior, que se almacena en la pila. Es decir, si la secuencia 2+3 está en la pila, esperamos a encontrar otro operador antes de realizar la suma.
Así, siempre que el carácter actual sea un operador (excepto el primero), el número anterior (3 en el ejemplo anterior) y el operador anterior (+) se sacan de la pila, colocándolos en las variables lastval y lasttop. Finalmente, se saca el primer número (2) y se realiza la operación aritmética sobre los dos números (obteniendo 5). 
Sin embargo, cuando se encuentran * y / que tienen mayor precedencia que + y –, la expresión no se puede ejecutar. En la expresión 3+4/2, el + no se puede ejecutar hasta que se realice la división. Entonces, el 2 y el + se vuelven a poner en la pila hasta que se realiza la división.
Por otro lado, si el operador actual es un + o -, se puede ejecutar el operador anterior. Es entonces cuando se encuentra el + en la expresión 4-5+6, está bien ejecutar el -, y cuando se encuentra el – en 6/2-3, está bien hacer la división. La tabla 10.1 muestra las cuatro posibilidades.
 

Operador anterior Operador actual Ejemplo Acción
+ o – * o / 3+4/ Empuje el operador anterior y el número anterior (+, 4)
* o / * o / 9/3* Ejecutar operador anterior, empujar resultado (3)
+ o – + o – 6+3+ Ejecutar operador anterior, empujar resultado (9)
* o / + o – 8/2- Ejecutar operador anterior, empujar resultado (4)

A continuación se muestra la implementación del enfoque anterior:
 

CPP

// C++ implementation of the approach
#include <cstring>
#include <iostream>
using namespace std;
 
// Length of expressions in characters
const int LEN = 80;
 
// Size of the stack
const int MAX = 40;
 
class Stack {
private:
    // Stack: array of characters
    char st[MAX];
 
    // Number at top of the stack
    int top;
 
public:
    Stack()
    {
        top = 0;
    }
 
    // Function to put a character in stack
    void push(char var)
    {
        st[++top] = var;
    }
 
    // Function to return a character off stack
    char pop()
    {
        return st[top--];
    }
 
    // Function to get the top of the stack
    int gettop()
    {
        return top;
    }
};
 
// Expression class
class Express {
private:
    // Stack for analysis
    Stack s;
 
    // Pointer to input string
    char* pStr;
 
    // Length of the input string
    int len;
 
public:
    Express(char* ptr)
    {
        pStr = ptr;
        len = strlen(pStr);
    }
 
    // Parse the input string
    void parse();
 
    // Evaluate the stack
    int solve();
};
 
void Express::parse()
{
 
    // Character from the input string
    char ch;
 
    // Last value
    char lastval;
 
    // Last operator
    char lastop;
 
    // For each input character
    for (int j = 0; j < len; j++) {
        ch = pStr[j];
 
        // If it's a digit then save
        // the numerical value
        if (ch >= '0' && ch <= '9')
            s.push(ch - '0');
 
        // If it's an operator
        else if (ch == '+' || ch == '-'
                 || ch == '*' || ch == '/') {
 
            // If it is the first operator
            // then put it in the stack
            if (s.gettop() == 1)
 
                s.push(ch);
 
            // Not the first operator
            else {
                lastval = s.pop();
                lastop = s.pop();
 
                // If it is either '*' or '/' and the
                // last operator was either '+' or '-'
                if ((ch == '*' || ch == '/')
                    && (lastop == '+' || lastop == '-')) {
 
                    // Restore the last two pops
                    s.push(lastop);
                    s.push(lastval);
                }
 
                // In all the other cases
                else {
 
                    // Perform the last operation
                    switch (lastop) {
 
                    // Push the result in the stack
                    case '+':
                        s.push(s.pop() + lastval);
                        break;
                    case '-':
                        s.push(s.pop() - lastval);
                        break;
                    case '*':
                        s.push(s.pop() * lastval);
                        break;
                    case '/':
                        s.push(s.pop() / lastval);
                        break;
                    default:
                        cout << "\nUnknown oper";
                        exit(1);
                    }
                }
                s.push(ch);
            }
        }
        else {
            cout << "\nUnknown input character";
            exit(1);
        }
    }
}
 
int Express::solve()
{
    // Remove the items from stack
    char lastval;
    while (s.gettop() > 1) {
        lastval = s.pop();
        switch (s.pop()) {
 
        // Perform operation, push answer
        case '+':
            s.push(s.pop() + lastval);
            break;
        case '-':
            s.push(s.pop() - lastval);
            break;
        case '*':
            s.push(s.pop() * lastval);
            break;
        case '/':
            s.push(s.pop() / lastval);
            break;
        default:
            cout << "\nUnknown operator";
            exit(1);
        }
    }
    return int(s.pop());
}
 
// Driver code
int main()
{
 
    char string[LEN] = "2+3*4/3-2";
 
    // Make expression
    Express* eptr = new Express(string);
 
    // Parse it
    eptr->parse();
 
    // Solve the expression
    cout << eptr->solve();
 
    return 0;
}
Producción: 

4

 

Complejidad temporal : O(N).
Espacio Auxiliar : O(N). 

Publicación traducida automáticamente

Artículo escrito por mdmusibul y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *