Balancing of parentheses

Asked

Viewed 1,574 times

1

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

In the lisp.c, I must make my program receive from the user the amount of characters, a number to know which level is given character and the sentence, having as answer if the sentence is balanced between parentheses. If yes, say which level is the character in the sentence. If it is not balanced, just say it is not. For example:

(((a)(b)c))

7 characters

Character 2

Program response: Sentence is balanced and 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 a lot of problems. Initially I’m not able to compile, but I’d like to know where I can be improving the algorithm.

  • This question has two votes to close. One of these votes as "too wide" and the other as "is not clear enough". I disagree with these closing votes and voted for "leave open". Someone who is in favor of closing I would like to explain further?

1 answer

1

  1. A lot of your compilation mistakes is that now you use Pilha and now uses Pilha *. Always use Pilha *.

  2. See its function of creating batteries:

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

    The use of -> serves to access pointers, then p should be a pointer. Also, you should return a pointer (as said in item 1). If p is not a pointer, it will be allocated to the stack and out of focus when the function is finished, so you have to allocate it to the heap with malloc. You should do it then:

    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;
        }
    
  3. Its function push is void, but she has a return 0; and a return 1; inside. Let’s make return int.

  4. In his job push we have it:

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

    That one char in front of you is no use. Remove it.

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

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

    They get like this:

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

With these changes, your code should already compile. But still there are other errors:

  1. See its function size:

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

    About the * before the p, I told you before. But look at the line tam = p->topo; + 1; - there is an extra semicolon there! Also, you don’t need this variable if you will already return immediately. So you can simplify it all like this:

    int size(Pilha *p) {
        return p->topo + 1;
    }
    
  2. Let’s see your function isEmpty:

    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. Therefore, if the result of the comparison is 1, it must return 1, if it is 0, it must return 0. Therefore, it is simpler to just return the result of the comparison directly:

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

    The same can be done in your job isFull.

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

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

    Is equivalent to that:

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

    With that in mind, you can simplify your function push by eliminating the else hers.

  4. The case of the variable charlvl is curious. This is an array of 10 positions, but you only use position 1. Therefore, it is better to declare this as a char. Besides, 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 sought character, we will have to charlvl[1] will be Fr[idx - 1]. Therefore, it is better to change this variable to the type char and assign Fr[idx - 1] to her before the for.

  5. You keep decreasing the idx until when it is 1, you perform the lvl = size(lisp);. The idx will have value 1 only when i == lvl - 1. So it’s easier for you to put that condition on if, do not change the variable lvl never and get rid of else.

  6. You ask to check characters at a certain level. In fact, what you look at is at a certain position in the sentence. Accordingly, the corresponding message in printf shall be amended. The variable idx is the position of the character in the sentence.

  7. A very important thing in programming is to give suitable names to variables. Especially if you are in college, why sometimes some teachers pick up and even take a point if the program has variables with inappropriate or non-standard names. So I suggest you rename Fr for frase, QtCar for quantidade, idx for posicao, lvl for nivel and charlvl for procurado.

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

  9. You don’t need stdio.h inside pilha.c nor pilha.h. And you don’t need stdlib.h inside lisp.c.

This is what your programme looks like:

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: Once the only thing you stack are parentheses, so you can remove the stack and exchange it for a counter. This shows that this exercise does not actually need to use a stack to check if the parentheses are balanced and a simpler solution exists. This also means that your teacher should devise another battery exercise that cannot be solved without using them. Here’s what your program would look like without using 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");
    }
}

Browser other questions tagged

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