Error in conversion from infographic notation to postfix

0

By inserting (3 + 7) the result of the operation is 37+ and by putting only 3 + 7 without the relatives of the segmentation error and when I put (3 + 7) - (2 + 7) I'm finding the mistake. I would 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] != '
#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] != '%pre%'; ++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] = '%pre%';
    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] != '%pre%'
                    && posfixa[i] != '+'
                    && posfixa[i] != '*'
                    && posfixa[i] != '/') i++;
            j = i;
            t = 0;
            /* pega digitos do numero*/
            while(posfixa[j] != ' ' && posfixa[j] != '%pre%'
                    && 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;
    }
}
'; ++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] = '%pre%'; 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] != '%pre%' && posfixa[i] != '+' && posfixa[i] != '*' && posfixa[i] != '/') i++; j = i; t = 0; /* pega digitos do numero*/ while(posfixa[j] != ' ' && posfixa[j] != '%pre%' && 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; } }
    
asked by anonymous 25.09.2016 / 22:28

1 answer

2

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

For example, for the expression "3 + 7", with this change below, the segmentation error does not occur.

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

But there are likely to be other such errors in your program.

Other things you can do better.

Get name of structures in uppercase:

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

Use "static" for function declarations:

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

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

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

    
25.09.2016 / 23:13