Parenthesis balancing [closed]

1

I'm doing a C programming activity involving TAD and CELL. The purpose of my activity is to make a library ( pilha.c ) using only the pilha.h functions.

In lisp.c , I want my program to receive the number of characters from the user, a number to know which level is determined by the character and the phrase, with the result being a balanced sentence between parentheses. If yes, tell which level is the character in the sentence. If it is not balanced, just report that it is not. For example:

  

(((a) (b) (c))

     

7 characters

     

Character 2

     

Program response: The sentence is balanced and the character b is at level 3.

lisp.c :

#include <stdlib.h>
#include <stdio.h>
#include "pilha.h"

int main(){
    int QtCar, idx, lvl;
    char charlvl[10];

    printf("Quantidade de caracteres:\n");
    scanf("%d",&QtCar);

    char Fr[QtCar];
    printf("Frase:\n");
    scanf("%s",Fr);

    printf("Verificar caracter no nivel?\n");
    scanf("%d",&idx);

    Pilha lisp = create();

    for(int i=0; i<QtCar;i++){
        if (Fr[i] == '(')
            push(&lisp, Fr[i]);
        if (Fr[i] == ')'){
            if (isEmpty(lisp)){
                printf ("A lista nao esta balanceada");
                break;
            }
            else
                pop(&lisp);
        }
        if (idx == 1){
            lvl = size(lisp);
            charlvl[1] = Fr[i];
        }
        else
            idx--;
    }
    if (isEmpty(lisp))
        printf ("A lista está balanceada! %s está no lvl %d",charlvl[1],lvl);
    else
        printf ("A lista nao esta balanceada");
}

pilha.c :

#include <stdio.h>
#include <stdlib.h>
#include "pilha.h"

Pilha create(){
    Pilha p;
    p->topo = -1;
    p->elementos[MAX];
}

int isFull(Pilha p){
    if (p->topo == MAX-1)
        return 1;
    else
        return 0;
}

char pop(Pilha *p){
    char c = p->elementos[p->topo];
    p->topo--;
    return c;
}

void push(Pilha *p, char c){
    if (isFull(p))
        return 0;
    else{
        p->topo++;
        char p->elementos[p->topo] = c;
        return 1;
    }
}
int isEmpty(Pilha p){
    if (p->topo == -1)
        return 1;
    else
        return 0;

}

int size(Pilha p){
    int tam;
    tam = p->topo; + 1;
    return tam;
}

pilha.h :

#ifndef PILHA_H_
#define PILHA_H_

#include <stdio.h>

#define MAX 100

typedef struct pilha {
    char elementos[MAX];
    int topo;
} Pilha;

Pilha create(); //cria pilha
char pop(Pilha *p); //desempilha
void push(Pilha *p, char c); //empilha
int isEmpty(Pilha p); //verifica pilha vazia
int isFull(Pilha p); //verifica pilha cheia
int size(Pilha p); //verifica tamanho da pilha

#endif

So, I'm having several problems. Initially I am not able to compile, but would like to know where I can be improving the algorithm.

    
asked by anonymous 08.09.2017 / 03:43

1 answer

1
  • Most of your compile errors are that sometimes you use Pilha and sometimes use Pilha * . Always use Pilha * .

  • See your battery-building function:

    Pilha create() {
        Pilha p;
        p->topo = -1;
        p->elementos[MAX];
    }
    

    The use of -> is used to access pointers, so p should be a pointer. In addition, you should return a pointer (as stated in item 1). If p is not a pointer, it will be allocated on the stack and deallocated when the function finishes, so you have to allocate it in the heap with malloc . You should then do this:

    Pilha *create() {
        Pilha *p = (Pilha *) malloc(sizeof(Pilha));
        p->topo = -1;
        p->elementos[MAX];
        return p;
    }
    

    However, this p->elementos[MAX]; does nothing. What you wanted in your place was this:

        for (int i = 0; i < MAX; i++) {
            p->elementos[i] = 0;
        }
    
  • Its function push is void , but it has return 0; and return 1; inside. Let's return int .

  • In your function push we have this:

    char p->elementos[p->topo] = c;
    

    This char up front is useless. Take it out.

  • With the above changes, in the file lisp.c , these lines:

    Pilha lisp = create();
    push(&lisp, Fr[i]);
    pop(&lisp);
    

    They start to look like this:

    Pilha *lisp = create();
    push(lisp, Fr[i]);
    pop(lisp);
    
  • With these changes, your code should already compile. But there are still other errors:

  • See your size function:

    int size(Pilha p) {
        int tam;
        tam = p->topo; + 1;
        return tam;
    }
    

    About * before p , I've spoken before. But look at the tam = p->topo; + 1; line - there's an extra semicolon in there! Also, you do not need this variable if you're already going to return immediately. So you can simplify it all like this:

    int size(Pilha *p) {
        return p->topo + 1;
    }
    
  • Let's see its isEmpty function:

    int isEmpty(Pilha p){
        if (p->topo == -1)
            return 1;
        else
            return 0;
    
    }
    

    The result of a comparison with == is always 1 when it is true and 0 when it is not. So, if the result of the comparison is 1, one should return 1, if it is 0, one should return 0. Therefore, it is simpler just to return the comparison result directly:

    int isEmpty(Pilha *p) {
        return p->topo == -1;
    }
    

    The same can be done in your isFull function.

  • If you have a if that always ends with a return , else is unnecessary. For example:

    if (condição) {
        return alguma_coisa;
    } else {
        blablabla
    }
    

    It's equivalent to this:

    if (condição) {
        return alguma_coisa;
    }
    blablabla
    

    With this in mind, you can simplify your push function by deleting else from it.

  • The case of the charlvl variable is curious. This is a 10-position array, but you only use position 1. Therefore, it is best to declare this as a char . In addition, there is a printf where you print charlvl[1] using %s . You should use %c . Also, unless the list empties before it reaches the position of the searched character, we will have charlvl[1] will Fr[idx - 1] . Therefore, it is best to change this variable to type char and assign Fr[idx - 1] to it before for .

  • You are decreasing idx until when it is 1, you run lvl = size(lisp); . The idx will have the value 1 only when i == lvl - 1 . Therefore, it is easier for you to put this condition in if , not change the variable lvl never and get rid of else .

  • You are asked to check characters at a certain level. In fact, what you look at is in a certain position in the sentence. Therefore, the corresponding message in printf must be changed. The variable idx is the position of the character in the sentence.

  • A very important thing in programming is to give appropriate names to variables. Especially if you're in college, why sometimes from time to time some teachers get on their feet and even score points if the program has variables with inappropriate or unmanned names. So I suggest you rename Fr to frase , QtCar to quantidade , idx to posicao , lvl to nivel and charlvl to procurado .

  • The printf("A lista nao esta balanceada"); within for of main should not be there. It already tells you whether or not the list is balanced at the end. However, the point here is to interrupt the whole analysis. So an auxiliary variable that indicates whether or not the analysis was aborted at this point becomes necessary.

  • You do not need stdio.h within pilha.c nor pilha.h . It also does not need stdlib.h within lisp.c .

  • Here's how your program looks:

    pilha.h :

    #ifndef PILHA_H_
    #define PILHA_H_
    
    #define MAX 100
    
    typedef struct pilha {
        char elementos[MAX];
        int topo;
    } Pilha;
    
    Pilha *create(); //cria pilha
    char pop(Pilha *p); //desempilha
    int push(Pilha *p, char c); //empilha
    int isEmpty(Pilha *p); //verifica pilha vazia
    int isFull(Pilha *p); //verifica pilha cheia
    int size(Pilha *p); //verifica tamanho da pilha
    
    #endif
    

    pilha.c :

    #include "pilha.h"
    #include <stdlib.h>
    
    Pilha *create() {
        Pilha *p = (Pilha *) malloc(sizeof(Pilha));
        p->topo = -1;
        for (int i = 0; i < MAX; i++) {
            p->elementos[i] = 0;
        }
        return p;
    }
    
    int isFull(Pilha *p) {
        return p->topo == MAX - 1;
    }
    
    char pop(Pilha *p) {
        char c = p->elementos[p->topo];
        p->topo--;
        return c;
    }
    
    int push(Pilha *p, char c) {
        if (isFull(p)) {
            return 0;
        }
        p->topo++;
        p->elementos[p->topo] = c;
        return 1;
    }
    
    int isEmpty(Pilha *p) {
        return p->topo == -1;
    }
    
    int size(Pilha *p) {
        return p->topo + 1;
    }
    

    lisp.c :

    #include <stdio.h>
    #include "pilha.h"
    
    int main() {
        int quantidade, posicao, nivel;
    
        printf("Quantidade de caracteres:\n");
        scanf("%d", &quantidade);
    
        char frase[quantidade];
        printf("Frase:\n");
        scanf("%s", frase);
    
        printf("Verificar caracter na posicao?\n");
        scanf("%d", &posicao);
        char procurado = frase[posicao - 1];
    
        int abortado = 0;
        Pilha *lisp = create();
    
        for (int i = 0; i < quantidade; i++) {
            if (frase[i] == '(') {
                push(lisp, frase[i]);
            }
            if (frase[i] == ')') {
                if (isEmpty(lisp)) {
                    abortado = 1;
                    break;
                } else {
                    pop(lisp);
                }
            }
            if (i == posicao - 1) {
                nivel = size(lisp);
            }
        }
        if (!abortado && isEmpty(lisp)) {
            printf("A lista esta balanceada! %c está no nivel %d", procurado, nivel);
        } else {
            printf("A lista nao esta balanceada");
        }
    }
    

    Your program should then work like this.

    However, there is still a little secret: Since the only thing you stack up is parenthesis, you can then delete the stack and swap it for a counter. This shows that this exercise does not really need to use a stack to check if the parentheses are balanced and a simpler solution exists. This also means that your teacher should brainstorm another exercise for piles that could not be solved without using them. Here's what your program looks like without batteries:

    #include <stdio.h>
    
    int main() {
        int quantidade, posicao, nivel;
    
        printf("Quantidade de caracteres:\n");
        scanf("%d", &quantidade);
    
        char frase[quantidade];
        printf("Frase:\n");
        scanf("%s", frase);
    
        printf("Verificar caracter na posicao?\n");
        scanf("%d", &posicao);
        char procurado = frase[posicao - 1];
    
        int abortado = 0;
        int abertos = 0;
    
        for (int i = 0; i < quantidade; i++) {
            if (frase[i] == '(') {
                abertos++;
            }
            if (frase[i] == ')') {
                if (abertos == 0) {
                    abortado = 1;
                    break;
                } else {
                    abertos--;
                }
            }
            if (i == posicao - 1) {
                nivel = abertos;
            }
        }
        if (!abortado && abertos == 0) {
            printf("A lista esta balanceada! %c está no nivel %d", procurado, nivel);
        } else {
            printf("A lista nao esta balanceada");
        }
    }
    
        
    08.09.2017 / 20:09