Jump to content
JonnyC

Dúvida

Recommended Posts

JonnyC

Boa noite,

Tenho uma pequena dúvida numa situação que é a seguinte, vi num código de um colega meu uma maneira a meu ver um pouco esquisito de programar c... Vou colocar o código e depois já me explico melhor...

 menu:

    system("cls");
    printf("Voce possui %d contatos e %d eventos em sua agenda.\n___________________________________________________\n\n",contcad,conteve);
    printf("%s","[1] Agenda Telefonica\n\n[2] Agenda de eventos\n\n[3] Salvar alteracoes\n\n[4] Sair\n\nDigite sua opcao:");
    fflush(stdin);
    scanf("%i",&opcao);

    switch(opcao) {
        case 1:      // agenda telefonica
            system("cls");
            printf("%s","Agenda Telefonica\n___________________________________________________\n\n");

            printf("%s","[1] Cadastrar nome\n\n[2] Buscar nome\n\n[3] Buscar apelido\n\n[4] Voltar\n\nDigite sua opcao:");
            scanf("%i",&opcao);
   switch(opcao) {
                case 1:   //novo contato
                    listacad[contcad] = agendatcad();
                    system("cls");
                    printf("Novo cadastro realizado com sucesso.\n\n");
                    contcad++;
                    alterado = 1;
                    system("pause");
                    system("cls");
                    goto menu;

   

Prontos aqui está um excerto do código a minha dúvida é aquele menu: pois ele não está declarado em lado nenhum e eu fiquei um bocado confuso como ele fez aquilo, e o caso de chamar goto menu; em vez do return...

Desde já agradeço a disponibilidade.

Cumprimentos

Share this post


Link to post
Share on other sites
daj

Em C, no contexto de uma função, podes definir símbolos e saltar incondicionalmente para eles. Nesse código índicado existe o símbolo "menu" na primeira linha e um salto para esse símbolo com o "goto menu;". Significa que o código, depois de executar

...
contcad++;
alterado = 1;
system("pause");
system("cls");

continua a execução nas instruções a seguir a "menu:"

system("cls");
printf("Voce possui %d contatos e %d eventos em sua agenda.\n___________________________________________________\n\n",contcad,conteve);
...

Se experimentares o seguinte programa:

#include <stdio.h>

int main() {
  int i = 0;
a:
  printf("%d\n", i);
  ++i;
  goto a;
  return 0;
}

verificas que a execução não termina porque o "goto a" faz com que a execução passe para as instruções a seguir ao "a:"

Share this post


Link to post
Share on other sites
JonnyC

Boas, desde já obrigado pela rápida resposta, continuei sem perceber muito bem... Pelo que me disse o menu: é um símbolo e esse símbolo necessita alguma coisa especial? ou simplesmente por ter menu: é um símbolo, quando digo especial estou-me a referir nos termos de uma função ou algo do género... Também fiquei com uma pequena sensação que esse menu: pode de certa forma ser comu um ciclo visto que cada vez que fazemos goto menu: ele volta ao início.  :wallbash:

Share this post


Link to post
Share on other sites
daj

Não é necessário mais nada. O "<nome>:" declara a existência do símbolo <nome> (que tem que ser único dentro da função). Esse nome serve para marcar um ponto para o qual se pode saltar com uma instrução goto.

Eu diria ao contrário, um ciclo é que pode ser visto como um goto. ;-) O goto não tem que voltar ao início. Pode ser algo como:

void func(int i) {
  if (i > 10) goto b;
  a: printf("A");
  b: printf("B");
}

(Edit: embora defina o símbolo (inglês: label) "a", nunca o utilizo. Se calhar significa que não é a melhor hora do dia para arranjar exemplos :-))

que mostra "AB" para argumentos <= 10 e "B" para > 10. Pode ser ainda mais desorganizado e daí se dizer que o uso do goto deve ser moderado.

Share this post


Link to post
Share on other sites
Diutsu

Boas, desde já obrigado pela rápida resposta, continuei sem perceber muito bem... Pelo que me disse o menu: é um símbolo e esse símbolo necessita alguma coisa especial? ou simplesmente por ter menu: é um símbolo, quando digo especial estou-me a referir nos termos de uma função ou algo do género... Também fiquei com uma pequena sensação que esse menu: pode de certa forma ser comu um ciclo visto que cada vez que fazemos goto menu: ele volta ao início.  :wallbash:

sim é isso, no entanto é uma má prática de programação usar gotos em C, principalmente para quem está a aprender. Todos os casos em que poderias usar goto podes usar ciclos, o que torna o código mais simples e fácil de ler.


XX SINFO - Semana Informática

Share this post


Link to post
Share on other sites
JonnyC

Muito obrigado desde já pelas dicas, você diz que os goto deviam ser substitui-los por ciclos, mas para substituir por ciclos também teria que alterar o símbolo menu: certo? Será que me poderia dar um exemplo de como ficaria o código só para eu ficar esclarecido.

Cumprimentos

Share this post


Link to post
Share on other sites
daj

"menu:" só faz sentido existir se houverem "goto"s para ele. Caso contrário pode ser removido. Uma estrutura possível para o menu poderá ser:

int ler_escolha() {
   int esc;

   printf("Escolha: ");
   scanf("%d", &esc);
   /* TODO: validar input */
   return esc;
}

void fazer_coisa_1() { /* ... */ }
void fazer_coisa_2() { /* ... */ }
void fazer_coisa_3() { /* ... */ }

int main() {
   int sair = 0;
   do {
      printf("1: Fazer Coisa 1\n2: Fazer Coisa 2\n3: Fazer Coisa 3\n4: Sair");
      switch(ler_escolha()) {
         case 1: fazer_coisa_1(); break;
         case 2: fazer_coisa_2(); break;
         case 3: fazer_coisa_3(); break;
         case 4: sair = 1; break;
         default: printf("Opção inválida.\n");
      }
   } while (sair == 0);
}

Algures no código dentro do do-while, na opção de sair, é atribuído o valor 1 à variável sair. Até lá, o ciclo não termina.

Share this post


Link to post
Share on other sites
daj

Vê lá se te ajuda o exemplo com um pouco mais de detalhe, como está na minha mensagem anterior.

Se repararmos num código como o seguinte (que não deve ser muito diferente do código do teu colega),

int main() {
   menu:
   printf("1: Fazer Coisa 1\n2: Fazer Coisa 2\n3: Fazer Coisa 3\n4: Sair");
   switch(ler_escolha()) {
      case 1: fazer_coisa_1(); goto menu;
      case 2: fazer_coisa_2(); goto menu;
      case 3: fazer_coisa_3(); goto menu;
      case 4: goto sair;
      default: printf("Opção inválida.\n"); goto menu;
   }
   sair:
   return 0;
}

temos lá um ciclo escondido, feito à custa de "goto"s. O corpo do ciclo é o código que está entre os símbolos "menu:" e "sair:" e a condição de paragem é que a escolha do utilizador seja 4, porque é apenas neste caso que não se volta para "menu:".

No código seguinte

int main() {
   int sair = 0;
   do {
      printf("1: Fazer Coisa 1\n2: Fazer Coisa 2\n3: Fazer Coisa 3\n4: Sair");
      switch(ler_escolha()) {
         case 1: fazer_coisa_1(); break;
         case 2: fazer_coisa_2(); break;
         case 3: fazer_coisa_3(); break;
         case 4: sair = 1; break;
         default: printf("Opção inválida.\n");
      }
   } while (sair == 0);
   return 0;
}

temos de novo o mesmo ciclo e a mesma condição de paragem, mas agora de forma explícita.

Share this post


Link to post
Share on other sites
Diutsu

com os goto's a coisa funcionava assim: tinhas a tag menu: que marca uma posição no código, durante a execução passas por essa tag sem acontecer nada de especial, no código que se segue irás encontrar um goto menu, em que caso esta linha seja executada a execução do código passa para linha imediatamente a seguir à tag menu, isto comporta-se como um ciclo, terás também de ter um caminho alternativo que te permita evitar executar a linha "goto menu", para poderes prosseguir com a execução normal do programa (usando condições).

usando ciclos, no código colocado é um do { <instruções>} while(<condição>) em que que está dentro do ciclo <instruções> é executado garantidamente uma vez, após a qual é avaliada a condição, se a condição for verdadeira, o ciclo é novamente executado, caso contrário, ou seja a condição é falsa, o programa sai do ciclo. No código do daj, é declarada e inicializada uma nova variável sair que serve de flag, ou seja serve para controlo da execução do menu. Inicialmente a flag é colocada a 0, para que o ciclo se esteja sempre a repetir e caso ela mude de valor o programa sai do ciclo. O único caso em que a flag muda de valor é quando tu dizes ao programa para sair.


XX SINFO - Semana Informática

Share this post


Link to post
Share on other sites
Guest id194

Em vez de te explicar o que são, para que servem e como se usam gotos, digo-te assim: esquece-os, não os uses, são má prática.

Para não falar que provavelmente resolves qualquer problema sem precisares deles.

Share this post


Link to post
Share on other sites
Localhost
Em vez de te explicar o que são, para que servem e como se usam gotos, digo-te assim: esquece-os, não os uses, são má prática.

Típica maneira portuguesa de ensinar lol.


here since 2009

Share this post


Link to post
Share on other sites
bubulindo

Em vez de te explicar o que são, para que servem e como se usam gotos, digo-te assim: esquece-os, não os uses, são má prática.

Para não falar que provavelmente resolves qualquer problema sem precisares deles.

Isto, como o Localhost referiu está errado.

E se em vez de dizeres para ignorar esta funcionalidade da linguagem explicasses porque não a devemos usar? Porque é que esta funcionalidade deve ser usada com algum cuidado, mas que quando bem usada facilita a programacão e ajuda imenso na leitura do código?

Se quiseres aprender um pouco mais sobre o porquê de comentários como o anterior dá uma vista de olhos por este link:

http://en.wikipedia.org/wiki/Spaghetti_code

O exemplo é simplista, mas imagina um programa com umas mil linhas de gódigo e já vês os problemas que pode dar...

Um exemplo que fez circular alguma e-ink pela net foi quando notaram que no kernel do linux o goto era bastante usado.

http://kerneltrap.org/node/553/2131


include <ai se te avio>

Mãe () {

}

Share this post


Link to post
Share on other sites
daj

Pegando no comentário do bubulindo sobre o goto no Linux, complemento esta discussão com dois links, um para um troço de código no Linux e outro no OpenBSD:

http://lxr.linux.no/linux+v2.6.37.1/kernel/sched.c#L4067

Ver os gotos no final da função, nas linhas 4150 e 4154 e os símbolos no início.

http://fxr.watson.org/fxr/source/kern/kern_exec.c?v=OPENBSD#L111

Ver as linhas com o "goto bad1;" e "goto bad2;" ao longo da função e os símbolos no fim, nas linhas 212 e 220.

Diria que em ambos os casos são utilizações moderadas que mantêm o código legível.

Share this post


Link to post
Share on other sites
Guest id194

E se em vez de dizeres para ignorar esta funcionalidade da linguagem explicasses porque não a devemos usar?

Pointless.

Se te se sentes assim tão incomodado com a minha resposta, explica tu.

Share this post


Link to post
Share on other sites
bubulindo

Pointless.

Se te se sentes assim tão incomodado com a minha resposta, explica tu.

Sempre achei que o objectivo do fórum seria o da entreajuda... dizer para esquecer a dúvida que foi colocada é tudo menos ajuda.

Já agora, dizes que são má prática porque foi assim que te ensinaram? E nunca perguntaste porquê?

É que se é má prática, e a discussão do goto ser má prática já tem uns quantos anos, não seria de já ter sido banida da linguagem C? E no entanto, isso não aconteceu...

Espera... será que... os professores são preguicosos e também nunca perguntaram porque é que não se podia usar?


include <ai se te avio>

Mãe () {

}

Share this post


Link to post
Share on other sites
brunoais

Espera... será que... os professores são preguicosos e também nunca perguntaram porque é que não se podia usar?

Bullseye!


"[Os jovens da actual geração]não lêem porque não envolve um telecomando que dê para mirar e atirar, não falam porque a trapalhice é rainha e o calão é rei" autor: thoga31

Life is a genetically transmitted disease, induced by sex, with death rate of 100%.

Share this post


Link to post
Share on other sites
Scolpit

Eu tive a sorte de ter quem me explicasse o porquê de não usar os GoTos... lol

Num programa simples, não é um goto ou outro que vá fazer diferença. Quando o programa fica complexo aí pode ser grande dor de cabeça, principalmente se tivermos de pegar num código que não foi feito por nós. Esse tipo de programação não estruturada chama-se Programação em Esparguete. Felizmente um senhor quis acabar com isso nos anos 60 chamado Asher Opler, e conduziu-nos mais ou menos ao que conhecemos hoje por código estruturado. Não faz mal nenhum saber que os goto existem, e como funcionam, fora isso, como já disseram, é má pratica e não deve ser usado :) goto bed

bed:

Vou dormir!

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×
×
  • Create New...

Important Information

By using this site you accept our Terms of Use and Privacy Policy. We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.