Error in conversion from infix to posixed notation

Asked

Viewed 247 times

0

When inserting (3+7) the result of the operation is 37+ and when placing only 3+7 without the relatives of the segmentation error and when I place (3+7)-(2+7) of the error also and I am not finding the error. I’d like a little help.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 50

/*estrutura pilha*/
struct pilha{
    double valor;
    struct pilha *proximo;
};
typedef struct pilha pilha;

/*outras funções*/
int bemFormada (char string[]);
char *infixaParaPosfixa (char infixa[]);
void trocaPorParenteses (char *string);
double calculo (char* posfixa);

/*funcoes da pilha*/
pilha * criaElemento(double valor);
void empilha(pilha ** p, pilha* e);
double desempilha(pilha ** p);
void mostrarPilha(pilha* p);

int main (){

    char infixa[MAX];
    char *posfixa;

    printf("================================================================================\n");
    printf("====================================Calculadora=================================\n");
    printf("================================================================================\n");

    /*entrada de dados*/
    printf("\n\n\nEntre com a expressao que desejada calcular: \n");
    gets(infixa);
    fflush(stdin);

    /*testa se bem formada, se for, realiza outras funções, se não, fecha o programa*/
    if (bemFormada (infixa)){
        printf ("\nExpressao bem-Formada! \n");
        trocaPorParenteses(infixa);
        posfixa = infixaParaPosfixa(infixa);
        printf("\nExpressao posfixa equivalente: %s\n\n", posfixa);
        printf("\nResultado da expressao: %.10f\n\n\n", calculo(posfixa));
    }
    else
        printf ("\nERRO: expressao mal-formada!\n\n\n");
    return 0;
}

int bemFormada (char string[]){
    char * p;
    int t, n, i;

    n = strlen (string);
    p = (char *) malloc (sizeof (char) * n);
    t = 0;

    for (i = 0; i < n; i++){
        if (string[i] == '(' || string[i] == '{' || string[i]=='['){
            p[t++] = string[i];
        }
        else if (string[i] == ')'){
            if (t != 0 && p[t - 1] == '('){
                t--;
            }
            else{
                free (p);
                return 0;
            }
        }
        else if (string[i] == ']'){
            if (t != 0 && p[t - 1] == '['){
                t--;
            }
            else{
                free (p);
                return 0;
            }
        }
        else if (string[i] == '}'){
            if (t != 0 && p[t - 1] == '{'){
                t--;
            }
            else{
                free (p);
                return 0;
            }
        }
    }
    free (p);
    if (t == 0)
        return 1;
    else return 0;
}

void trocaPorParenteses(char *string){
    int tam = strlen(string);
    int i = 0;
    for(i=0; i<tam; i++){
        if(string[i] == '(' || string[i] == '{' || string[i] == '['){
            string[i] = '(';
        }
        else if(string[i] == ')' || string[i] == '}' || string[i] == ']'){
            string[i] = ')';
        }
    }
}

char *infixaParaPosfixa(char infixa[]){
    int t;
    int n, i, j;
    char *posf;
    char *pi;

    n = strlen(infixa);
    posf = malloc( n * sizeof (char));
    pi = malloc( n * sizeof (char));
    t = 0;

    pi[t++] = infixa[0];
    for (j = 0, i = 1; infixa[i] != '\0'; ++i){
        switch (infixa[i]){
            char x;
        case '(':   pi[t++] = infixa[i];
                    break;
        case ')':   while (1){
                        x = pi[--t];
                        if (x == '(') break;
                        posf[j++] = x;
                    } break;
        case '+':   while (1){
                        x = pi[t-1];
                        if (x == '(') break;
                        --t;
                        posf[j++] = x;
                    }
                    pi[t++] = infixa[i];
                    break;
        case '-':   if(infixa[(i+1)] == ' '){
                        while (1){
                            x = pi[t-1];
                            if (x == '(') break;
                            --t;
                            posf[j++] = x;
                        }
                        pi[t++] = infixa[i];
                        break;
                    }
                    else{
                        posf[j++] = '-';
                        break;
                    }
        case '*':
        case '/':   while (1){
                        x = pi[t-1];
                        if (x == '(' || x == '+' || x == '-') break;
                        --t;
                        posf[j++] = x;
                    }
                    pi[t++] = infixa[i];
                    break;
        default:    posf[j++] = infixa[i];
        }
    }
    free( pi);
    posf[j] = '\0';
    return posf;
}

double calculo(char* posfixa){
    int i=0, j=0, k=0, t=0;
    double a, b, resultado = 0;
    int n = strlen(posfixa);
    char* pi = (char*)calloc(n, sizeof(char));
    pilha* p = NULL;
    if(!posfixa){
        return 0;
    }
    for(i=0; i < n; i++){
        switch(posfixa[i]){
        case '+':   b = desempilha(&p);
                    a = desempilha(&p);
                    resultado = a + b;
                    printf("\nSomando %.10f + %.10f = %.10f\n\n", a, b,resultado);
                    empilha(&p, criaElemento(resultado));
                    break;
        case '-':   if(posfixa[i+1] != ' '){
                        goto def;
                    }
                    defmenos:
                    b = desempilha(&p);
                    a = desempilha(&p);
                    resultado = a - b;
                    printf("\nSubtraindo %.10f - %.10f = %.10f\n\n", a, b,resultado);
                    empilha(&p, criaElemento(resultado));
                    break;
        case '*':   b = desempilha(&p);
                    a = desempilha(&p);
                    resultado = a * b;
                    printf("\nMultiplicando %.10f * %.10f = %.10f\n\n", a, b,resultado);
                    empilha(&p, criaElemento(resultado));
                    break;
        case '/':   b = desempilha(&p);
                    a = desempilha(&p);
                    resultado = a / b;
                    printf("\nDividindo %.10f / %.10f = %.10f\n\n", a, b,resultado);
                    empilha(&p, criaElemento(resultado));
                    break;
        case ' ':   continue;
        default:
            def:
            /* zera valores de pilha vetor para demais converter para double*/
            for(k=0; k<n; k++){
                pi[k] = 0;
            }
            /* encontra primeira posicao depois do espaco e antes do fim */
            while(posfixa[i] == ' ' && posfixa[i] != '\0'
                    && posfixa[i] != '+'
                    && posfixa[i] != '*'
                    && posfixa[i] != '/') i++;
            j = i;
            t = 0;
            /* pega digitos do numero*/
            while(posfixa[j] != ' ' && posfixa[j] != '\0'
                    && posfixa[j] != '+'
                    && posfixa[j] != '*'
                    && posfixa[j] != '/'){
                pi[t++] = posfixa[j++];
            }
            i = j;
            /* empilha */
            if(atof(pi) != 0){
               printf("Empilha: %s\n", pi);
                empilha(&p, criaElemento(atof(pi)));
            }
            else{
                goto defmenos;
            }
            break;
        }
      /*  mostrarPilha(p);*/
    }
    if(p){
        if(!p->proximo){
            resultado = p->valor;
        }
    }
    free(p);
    return resultado;
}


/* pilha funcoes */
pilha * criaElemento(double valor){
    pilha * e = (pilha*)malloc(sizeof(pilha));
    e->valor = valor;
    e->proximo = NULL;
    return e;
}

void empilha(pilha ** p, pilha* novo){
    if(*p){
        novo->proximo = *p;
        *p = novo;
    }else{
        *p = novo;
    }
}

double desempilha(pilha ** p){
    double valor = 0;
    pilha* aux = *p;
    *p = (*p)->proximo;
    valor = aux->valor;
    free(aux);
    return valor;
}

void mostrarPilha(pilha* p){
    int i = 0;
    pilha* aux = p;
    while(aux){
        printf("Elemento %d ->\t Valor: %.10f\n\n", i++, aux->valor);
        aux = aux->proximo;
    }
}

1 answer

2

Whenever you access the top of the stack you need to check if the top of the stack is valid.

For example, for the expression "3+7", with this change below there is no segmentation error.

case '+':
   while (t > 0)
   {
      x = pi[t-1];
      if (x == '(') break;
      --t;
      posf[j++] = x;
   }
   pi[t++] = infixa[i];
   break;

But it is very likely that there are other errors of this kind in your program.

Other things you can improve.

Start name structures in uppercase:

typedef struct
{
   double valor;
   struct pilha *proximo;
} Pilha;

Use "Static" for function statements:

static int bemFormada (char string[]);
// etc

Using "fgets" instead of "gets". Using "gets" is grounds for dismissal for just cause. :)

When you have multiple indices (i, j, t, etc.) document (at least succinctly) what each of these indices do, or else give meaningful names. After all, looking quickly, how will you know what "i" and "j" are used for? It gets difficult...

Browser other questions tagged

You are not signed in. Login or sign up in order to post.