TBTuesday? Abertura e Fechamento de Parenteses

24 views
Skip to first unread message

Fabio Mazzarino

unread,
Jan 7, 2025, 7:54:41 AMJan 7
to ccppbrasil
Essa já é clássica em entrevistas.

Como verificar se os parênteses, colchetes e chaves foram devidamente abertos e fechados na ordem certa?

Eu propus uma solução neste post antigo do Lab C++, mas tb propus verificar as aspas das strings. E pra fechar tem uma proposta de um exercício adicional.

Fabrício Cabral

unread,
Jan 7, 2025, 7:59:27 AMJan 7
to ccppb...@googlegroups.com
Fabio,

Está muito bacana seus posts! Parabéns!!

At.te.

--
http://ccppbrasil.github.io/
https://twitter.com/ccppbrasil
 
[&] C & C++ Brasil - http://www.ccppbrasil.org/
Para sair dessa lista, envie um e-mail para ccppbrasil-...@googlegroups.com
---
Você recebeu essa mensagem porque está inscrito no grupo "ccppbrasil" dos Grupos do Google.
Para cancelar inscrição nesse grupo e parar de receber e-mails dele, envie um e-mail para ccppbrasil+...@googlegroups.com.
Para ver esta conversa, acesse https://groups.google.com/d/msgid/ccppbrasil/c0a39c82-3d79-452f-b2b9-b0d9278610b3n%40googlegroups.com.


--
--fx

Thiago Adams

unread,
Jan 7, 2025, 9:11:18 AMJan 7
to ccppbrasil
Em C

----

#include
<stdio.h>

struct input {
    const char * current;
    const char * original;
};

void expression(struct input * input);

void open(struct input * input)
{
    const char * open = input->current;
    char close = *open == '[' ? ']' : *open == '{' ? '}' : ')';

    input->current++;
    expression(input);

    if (*input->current == close)
    {
        input->current++;
        return;
    }

    printf("%s\n", input->original);
    const char * p = input->original;
    while (*p)
    {
        if (p >= open && p < input->current)
        {
            printf("~");
        }
        else if (p == input->current)
        {
            printf("^");
            break;
        }
        else
            printf(" ");
        p++;
    }
    printf("\n");
    printf("missing '%c'\n", close);
}

void expression(struct input * input)
{
    while (*input->current)
    {
        if (*input->current == '(' || *input->current == '[' || *input->current == '{')
        {
            open(input);
        }
        else if (*input->current == ')' || *input->current == ']' || *input->current == '}')
        {
            break;
        }
        else
            input->current++;
    }
}

int main()
{
    struct input expr = { 0 };
    expr.current = "x = a[0] * (a[1] + a[2];";
    expr.original = expr.current;
    expression(&expr);
}


https://godbolt.org/z/4zsG56Tr8

Augusto Rodrigues

unread,
Jan 7, 2025, 10:07:53 AMJan 7
to ccppb...@googlegroups.com
Thiago Adams,

O bom de analisar os seus algoritmos é verificar os seus links que mostram outras ferramentas interessantes que existem na internet. 

Parece ser bacana esse site que você usou para demonstrar/ilustrar a sua solução. Vou ver com mais paciencia esse site

Mas ficou uma dúvida: Não apareceu o símbolo ' ^ ' para mostrar a posição que falta fechar o parênteses, mesmo clicando no link que 
você forneceu.

Seria erro de formatação do output gerado pelo site ou algum erro no algoritmo que você forneceu como resposta ?

Outra dúvida:
Seria válido na sua opinião encerrar o processamento do algoritmo quando encontra o caractere ";" ao invés de encerrar apenas quando 
encontra o "\0"

Suponha que seja passado a string abaixo:
"x = a[0] * (a[1] + a[2];)";

O seu algoritmo iria encontrar o parênteses que foi aberto após o caractere de multiplicação. Certo? Mas acho que a expressão em si estaria errada porque o 
ponto e vírgula indica fim de instrução.

De qualquer forma é interessante essa abordagem usando funções recursivas. Para avaliação de pequenas cadeias de expressão, realmente é uma boa abordagem.

Sinceramente pensei num primeiro momento na abordagem usada pelo Fábio, que usa o conceito de pilha e um loop central. Como boa parte da minha experiência vem
de sistemas embutidos, fui orientado a nunca usar funções recursivas devido ao consumo de pilha gerado pela execução de chamadas recursivas.

Mas no geral ambas soluções, a do Fábio como a do Thiago, são boas.

Fui





--
http://ccppbrasil.github.io/
https://twitter.com/ccppbrasil
 
[&] C & C++ Brasil - http://www.ccppbrasil.org/
Para sair dessa lista, envie um e-mail para ccppbrasil-...@googlegroups.com
---
Você recebeu essa mensagem porque está inscrito no grupo "ccppbrasil" dos Grupos do Google.
Para cancelar inscrição nesse grupo e parar de receber e-mails dele, envie um e-mail para ccppbrasil+...@googlegroups.com.

Thiago Adams

unread,
Jan 7, 2025, 11:41:55 AMJan 7
to ccppb...@googlegroups.com
On Tue, 7 Jan 2025 at 12:07, Augusto Rodrigues <guto.rodr...@gmail.com> wrote:
Thiago Adams,

O bom de analisar os seus algoritmos é verificar os seus links que mostram outras ferramentas interessantes que existem na internet. 

Parece ser bacana esse site que você usou para demonstrar/ilustrar a sua solução. Vou ver com mais paciencia esse site

Mas ficou uma dúvida: Não apareceu o símbolo ' ^ ' para mostrar a posição que falta fechar o parênteses, mesmo clicando no link que 
você forneceu.


Quando chegava no "EOF" ele não mostrava o ^. Se quiser mostrar basta adicionar

    if (*p == 0)  //isso
      printf("^"); //isso

    printf("\n");
    printf("missing '%c'\n", close);
}


 
Seria erro de formatação do output gerado pelo site ou algum erro no algoritmo que você forneceu como resposta ?

Outra dúvida:
Seria válido na sua opinião encerrar o processamento do algoritmo quando encontra o caractere ";" ao invés de encerrar apenas quando 
encontra o "\0"


É uma opção.

 
Suponha que seja passado a string abaixo:
"x = a[0] * (a[1] + a[2];)";

O seu algoritmo iria encontrar o parênteses que foi aberto após o caractere de multiplicação. Certo? Mas acho que a expressão em si estaria errada porque o 
ponto e vírgula indica fim de instrução.

De qualquer forma é interessante essa abordagem usando funções recursivas. Para avaliação de pequenas cadeias de expressão, realmente é uma boa abordagem.

Dá para fazer algo completo. Vai aumentando as linhas. Meu objetivo era tentar fazer algo pequeno.

Fabio Mazzarino

unread,
Jan 7, 2025, 6:34:48 PMJan 7
to ccppbrasil
Fabrício:

Isso faz parte de algo com q me comprometi com o grupo há um ou dois meses atrás, pra tentar aumentar o movimentação de posts gerando assunto baseado nos posts do Lab C++.

Aparentemente está funcionando, temos threads originárias de outras pessoas, inclusive.
Reply all
Reply to author
Forward
0 new messages