preview
Do básico ao intermediário: Comandos BREAK e CONTINUE

Do básico ao intermediário: Comandos BREAK e CONTINUE

MetaTrader 5Exemplos | 28 agosto 2024, 10:36
126 0
CODE X
CODE X

Introdução

O conteúdo exposto aqui, visa e tem como objetivo, pura e simplesmente a didática. De modo algum deve ser encarado como uma aplicação final, onde o objetivo não seja o estudo dos conceitos aqui mostrados.

No artigo anterior Do básico ao intermediário: Comando WHILE e DO WHILE, começamos a falar sobre laços. Assim sendo o pré-requisito para que você consiga acompanhar e compreender de maneira adequada o que será visto neste artigo. É justamente ter compreendido o que foi mostrado e explicado no artigo anterior.

Sei que muitos programadores iniciantes, tem muita dificuldade em compreender de maneira adequada o funcionamento de comandos que geram laços. Porém, laços são importantes e fazem parte de quase todo programa que você vier a construir no decorrer de sua vida. Mesmo que você venha a criar programas somente como HOBBY. Entender e saber trabalhar com comando de que geram laços é muito importante.

Existe um outro tipo de laço, que não faz uso dos comandos convencionais. Mas isto será visto em um outro momento. No entanto, existem três comandos que aparecem com alguma frequência dentro de um laço. Apesar de serem três, dois deles podem vir a aparecer fora de um laço. Porém, um deles somente existirá dentro de um laço. Mas nunca, pelo menos sem uma justificativa muito forte, irá ser visto de maneira isolada dentro de um laço.

Aqui iremos tratar destes comandos. Mas principalmente de dois deles. Que aparecem justamente no título do artigo. Ou seja, chegou a hora de entender como se controla o laço do lado de dentro. Neste ponto quero pedir a você toda atenção ao que será explicado, meu caro leitor. Pois se você não entender o que este artigo irá demonstrar. Definitivamente você irá ficar em maus lenções em algum momento de usa vida, isto como programador.


Uma possível resposta

Bem, antes de começarmos, deixei um pequeno desafio para você, no artigo anterior. O desafio era transformar o código visto abaixo, em um código que utilizasse um laço.

01. //+------------------------------------------------------------------+
02. #property copyright "Daniel Jose"
03. //+------------------------------------------------------------------+
04. void OnStart(void)
05. {
06.     Factorial();
07.     Factorial();
08.     Factorial();
09.     Factorial();
10.     Factorial();
11. }
12. //+------------------------------------------------------------------+
13. void Factorial(void)
14. {
15.     static uchar counter = 0;
16.     static ulong value = 1;
17. 
18.     Print("Factorial of ", counter, " => ", value);    
19.     counter = counter + 1;
20.     value = value * counter;
21. }
22. //+------------------------------------------------------------------+

Código 01

Ok, se você não conseguir bolar uma maneira de fazer isto. Tudo bem, faz parte. Isto neste início de aprendizagem. Porém não deixe o material se acumular para começar a estudar o mesmo. Já que as coisas vão se acumular de maneira muito rápida, conforme iremos avançando em direção a um nível, que considero ser intermediário.

Existem diversas formas de transformar, ou melhor dizendo, utilizar um laço no código 01, a fim de tornar ele mais agradável. Uma desta forma, já podemos fazer. Isto devido ao que foi apresentado no artigo anterior. E também ligando o conhecimento que foi repassado nos artigos anteriores.

Em termos gerais e de maneira bem simples, você poderia simplesmente usar o que seria uma modificação do código 07 visto no artigo anterior. Isto a fim de gerar o mesmo resultado que seria visto, se você executasse este código 01. Como? Simplesmente utilizando o código 02 logo abaixo.

01. //+------------------------------------------------------------------+
02. #property copyright "Daniel Jose"
03. //+------------------------------------------------------------------+
04. void OnStart(void)
05. {
06.     uchar counter = 0;
07. 
08.     while (counter < 5)
09.         Factorial(counter);
10. }
11. //+------------------------------------------------------------------+
12. void Factorial(uchar &counter)
13. {
14.     static ulong value = 1;
15. 
16.     Print("Factorial of ", counter, " => ", value);    
17.     counter = counter + 1;
18.     value = value * counter;
19. }
20. //+------------------------------------------------------------------+

Código 02

Esta é apenas UMA maneira de resolver o problema. Existem outras, mais ou menos elaboradas. Mas com o que até o momento foi explicado. Esta seria uma boa solução. Agora se você não entende o que este código 02 está de fato fazendo. Mas principalmente por que ele consegue obter a mesma resposta do código 01. Pare imediatamente de ler este artigo. E volte aos artigos anteriores. Isto a fim de compreender este código 02. Somente depois que você já estiver conseguindo compreender este código 02. É que você estará apto a continuar, neste e nos próximos artigos.

Bem, dado o alerta, podemos começar com o que será o primeiro comando a ser visto neste artigo. Vamos começar como o que seria o comando mais simples, que pode estar presente dentro de um laço. Mas para começarmos a falar sobre ele, vamos iniciar um novo tópico.


Comando RETURN

Eu sei, que muitos de vocês, que já teve algum contato e tem uma experiência mínima, com a programação em MQL5, irá me dizer: Mas este comando não tem nada a ver com laços. Ele tem mais haver com funções. De fato, meu caro leitor, o comando RETURN tem muito mais haver com funções do que com laços. Porém, apesar de ser um comando obrigatório em uma função, ele é opcional em procedimentos. Justamente por conta do efeito que ele tem em procedimentos, onde ele aparece, é que ele é um dos comandos que pode vir a surgir dentro de um laço.

Agora preste atenção. O comando RETURN, tem como objetivo, devolver, ou retornar, o fluxo de execução, ao chamador da função ou procedimento. Porém, e é aqui onde muitos iniciantes costumam sofrer para entender. Se você está, dentro de um procedimento ou função principal de sua aplicação. Que pode ser OnInit ou OnStart, dependendo do caso. O comando RETURN quando for executa irá finalizar sua aplicação. Fazendo com que o MetaTrader 5, a remova do gráfico. Isto por que, em última instância, qualquer aplicação, é uma função ou procedimento que o sistema operacional estará executando. Entendendo as coisas desta maneira fica bem mais simples entender por que um comando RETURN colocado em OnInit ou OnStart, pode fazer sua aplicação finalizar de maneira prematura.

Ok, no caso de RETURN aparecer em OnInit, a aplicação poderá ou não ser finalizada. Isto dependendo do valor que estaremos retornando para o MetaTrader 5. Porém no caso de RETURN, aparecer e ser executada dentro do procedimento OnStart, de fato a aplicação será finalizada.

Para compreender isto, começar vendo um pequeno e simples exemplo. Esta é mostrado logo abaixo.

01. //+------------------------------------------------------------------+
02. #property copyright "Daniel Jose"
03. //+------------------------------------------------------------------+
04. void OnStart(void)
05. {
06.     Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway...");
07. 
08.     return;
09. 
10.     Print(__FUNCTION__, " ", __LINE__, " This line will never be executed...");
11. }
12. //+------------------------------------------------------------------+

Código 03

O resultado da execução deste código pode ser visto logo abaixo.


Imagem 01

A parte que você precisa entender é a de que RETURN, que se encontra presente na linha oito, está dentro de um procedimento. Logicamente por ser um procedimento ela NÃO DEVERÁ ter nenhum valor relacionado a ela. Isto para evitar conflitos com o compilador durante a criação do executável. Porém se RETURN estivesse presente em uma função, seria obrigatório associar um valor ao comando. Isto para informar ao chamador qual o valor de retorno da função. Já vimos isto sendo aplicado anteriormente, quando falamos sobre variáveis.

Porém o interesse aqui e neste momento é outro. Sendo este o de podermos sair de um laço de maneira antecipada. Isto por que, muitas vezes é interessante e até mesmo desejável, sair de um laço antes que ele termine. Devido justamente a alguma condição especial. Um exemplo simples em que isto poderia ser aplicado é mostrado logo abaixo.

01. //+------------------------------------------------------------------+
02. #property copyright "Daniel Jose"
03. //+------------------------------------------------------------------+
04. void OnStart(void)
05. {
06.     Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway...");
07. 
08.     Procedure_Loop();
09. 
10.     Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway...");
11. }
12. //+------------------------------------------------------------------+
13. void Procedure_Loop(void)
14. {
15.     char info = 10;
16. 
17.     Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway...");
18.     
19.     while (info)
20.     {
21.         info = info - 3;
22.         
23.         Print("Loop : ", info);
24.         
25.         if (info < -5) return;
26.     }
27.     
28.     Print(__FUNCTION__, " ", __LINE__, " This line will never be executed...");
29. }
30. //+------------------------------------------------------------------+

Código 04

Este código 04 quando executado irá gerar o resultado que pode ser visto na imagem abaixo.


Imagem 02

Aqui temos algo que pode parecer um tanto quanto estranho para você meu caro leitor. Isto por que, se queremos que o laço seja encerrado quando temos um valor de info, mais negativo que menos cinco. Por que não colocar isto diretamente na expressão de teste do laço? O motivo para não se fazer isto, é que as vezes queremos de o laço não venha a atingir um determinado valor. Mas se ele atingir um outro valor, queremos que todo o restante, seja da rotina ou procedimento, onde o laço se encontra, venha a ser ignorado.

Por conta, justamente deste simples detalhe, é que a linha 28 jamais será executada dentro do que é o código 04. Visto que o valor de info, não atingirá o valor zero, antes que a expressão de teste em IF dispare a execução do comando RETURN. Justamente por conta disto que temos a imagem 02, imprimindo valores que vão de sete até oito negativo.

Muito bem, mas por que a aplicação não está sendo finalizada, no momento que a linha 25 é executada? Permitindo que a linha 10 venha a ser executada. Diferente do que aconteceu no código 03? O motivo para isto, meu caro leitor, é justamente o fato de que OnStart é o procedimento, ou função inicial, que é chamada pelo MetaTrader 5. Mas Procedure_Loop é chamada por OnStart. Sendo assim, quando o comando RETURN é executado ele irá retornar para quem chamou o procedimento ou função onde ele se encontra. No caso OnStart.

Esta questão de qual função o MetaTrader 5 chama, será melhor explicado em outro oportunidade. Mas basicamente o MetaTrader 5, chama duas funções: OnStart e OnInit. Somente nestes casos o comando RETURN irá, ou poderá fazer com que sua aplicação seja finalizada. Fora isto, o uso do comando RETURN, não irá finalizar a aplicação.

Perfeito. Acredito que tenha dado para compreender como return pode ser utilizado dentro de um laço. Qualquer coisa, pratique um pouco com estes exemplos mais simples, para compreender melhor. Assim sendo, podemos passar para o próximo comando a ser visto neste artigo.


Comando BREAK

Este comando break é um comando bastante interessante. Porém você precisa tomar alguns cuidados e estudar este comando BREAK com calma. Isto por que, no começo não é raro de que você venha a se complicar ao usar este comando. Não em laços simples, mas sim em laços um pouco mais elaborados.

Um dos erros mais comuns ao usar o comando break é o de achar que o comando break associado a um laço, irá influenciar em um outro laço ou mesmo em um outro comando de controle de fluxo. Isto por que BREAK não é somente usado para laços, ele também serve para ser utilizado em um outro controle que veremos futuramente. Porém neste momento, não se preocupe com isto. Vamos focar apenas na questão dos laços.

Ok, dentro desta questão de laços, você precisa entender uma questão que muitos se esquecem, ou ignoram. O comando BREAK segue um princípio muito similar ao comando RETURN. Ou seja, ele não estará jogado dentro do laço. Normalmente ele será a rotina de um comando IF. Então podemos usar o mesmo código 04, visto no tópico anterior. E no lugar de colocar um comando RETURN colocar um comando BREAK. Assim o código fica como mostrado logo abaixo.

01. //+------------------------------------------------------------------+
02. #property copyright "Daniel Jose"
03. //+------------------------------------------------------------------+
04. void OnStart(void)
05. {
06.     Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway...");
07. 
08.     Procedure_Loop();
09. 
10.     Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway...");
11. }
12. //+------------------------------------------------------------------+
13. void Procedure_Loop(void)
14. {
15.     char info = 10;
16. 
17.     Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway...");
18.     
19.     while (info)
20.     {
21.         info = info - 3;
22.         
23.         Print("Loop : ", info);
24.         
25.         if (info < -5) break;
26.     }
27.     
28.     Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway...");
29. }
30. //+------------------------------------------------------------------+

Código 05

Ao executar este código 05, o resultado mostrado no terminal do MetaTrader 5, é o que vemos logo abaixo.


Imagem 03

Hum, interessante. Desta vez temos uma informação que não era mostrada antes. Curioso, então parece ser bem simples trabalhar com laços. Agora já estou preparado para mexer com códigos mais elaborados. (RISOS). Calma meu caro leitor, calma, estamos apenas começando. Existe uma pegadinha, se bem que na verdade é um mal entendimento que novos programadores têm sobre estes comandos. Por isto peço que você pratique usando pequenas variações destes códigos mostrados aqui.

O primeiro mal entendido tem a ver com o uso do comando BREAK em laços aninhados. Sim, da mesma forma que podemos aninhar vários comandos IF. Também podemos aninhar vários laços um dentro do outro. Isto é muito comum em trabalhos com arrays multidimensionais, onde não queremos ficar fazendo cálculos de índice. Mas vamos ver um exemplo simples de laço aninhado, para que você possa compreender, como o comando BREAK irá se comportar neste caso. Um exemplo simples é mostrado no código a seguir.

01. //+------------------------------------------------------------------+
02. #property copyright "Daniel Jose"
03. //+------------------------------------------------------------------+
04. void OnStart(void)
05. {
06.     Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway...");
07. 
08.     Procedure_Loop();
09. 
10.     Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway...");
11. }
12. //+------------------------------------------------------------------+
13. void Procedure_Loop(void)
14. {
15.     char    info = 10,
16.             limit = 5;
17. 
18.     do
19.     {
20.         Print(__FUNCTION__, "  ", __LINE__, " : Info (", info, ")  Limit (", limit, ")");
21. 
22.         while (info > limit)
23.         {
24.             if (limit < 0) break;
25. 
26.             info = info - 3;
27. 
28.             Print(__FUNCTION__, "  ", __LINE__, " : Info (", info, ")  Limit (", limit, ")");
29.         }
30.         info = info + limit;
31.         limit = limit - 2;
32. 
33.         Print(__FUNCTION__, "  ", __LINE__, " : Info (", info, ")  Limit (", limit, ")");
34. 
35.     }while (info > 0);
36. 
37.     Print(__FUNCTION__, "  ", __LINE__, " : Info (", info, ")  Limit (", limit, ")");
38. }
39. //+------------------------------------------------------------------+

Código 06

Apesar de parecer complicado, devido a quantidade de mensagens que estamos imprimindo. Este código 06, de fato é bem simples, e serve para ilustrar perfeitamente bem a questão do comando BREAK dentro de laços aninhados. Quando você executar este código 06, o resultado é de fato bem interessante. Podendo ser observado na imagem abaixo.


Imagem 04

Agora preste atenção a uma coisa aqui meu caro leitor. Dentro do laço que começa na linha 18, temos um outro laço. Este se inicia na linha 22. Dentro deste novo laço, temos um teste na linha 24. É aqui que as coisas ficam interessantes. Isto por que você pode experimentar depois, trocar este comando BREAK por um comando RETURN. Isto a fim de observar o que irá ocorrer no código. Mas vamos focar no que está acontecendo, quando usamos o comando BREAK.

É fato que teremos uma contagem acontecendo aqui. Mas como ela estará sendo controlada? Esta é a grande questão. Muitas vezes precisamos contabilizar certos valores. Porém é um tanto quanto dispendioso, analisar a saída de um conjunto de laços aninhados. O que muitas vezes acontece é que criamos uma expressão, ou formula matemática que nos diz como o cálculo precisa ser efetuado. Uma vez com esta formula em mãos, entramos e criamos a expressão matemática em forma de código.

Ao fazermos isto, precisamos confiar na nossa capacidade de transformar expressões e fórmulas matemáticas em código. Isto por que, se a quantidade de valores, ou a forma como os valores serão criados, forem um tanto quanto complicadas, ou grande. Não iremos analisar um por um. Fazemos isto por amostragem. Ou seja, sabemos quais os valores iremos ter dentro de um dado limite, e analisamos apenas este limite. Por isto é importante, que você domine muito bem cada comando e como cada operação funciona.

Ok, voltando ao código, você pode notar que na imagem 04, temos apenas alguns pontos, onde de fato a linha 28 estará sendo impressa. Mesmo que a expressão do laço 22 indique que seriam mais vezes. Isto de termos uma quantidade menor da linha 28 sendo executada. Se deve justamente ao fato de que o comando BREAK faz com que o laço interno seja finalizado antes da expressão indica que ele deve ser finalizado. Porém o fato de o laço interno ser finalizado, não indica, neste caso do uso do comando BREAK, que o laço externo também será finalizado. Por isto é importante que você experimente usar o comando RETURN aqui também, para ver o que irá ocorrer. Pois existe diferença no resultado final que será visto no terminal.

Basicamente se você acompanhar o fluxo de execução irá compreender isto de maneira muito simples. Como o fluxo de execução do comando WHILE e do casal DO WHILE, assim como do comando IF, foram mostrados nos artigos anteriores. Você conseguirá desenhar os mesmos aqui. No entanto, ainda não foi mostrado como seria o fluxo no caso de se encontrar um comando BREAK. Mas este pode ser visto logo abaixo.


Imagem 05

Aqui LOOP indica qualquer comando que permita a criação de laços. Porém o comando BREAK está sendo colocado aqui, como se ele estivesse jogado solto no código. Mas neste ponto precisamos abrir um parêntese. Isto por que se fossemos colocar todo o conjunto que seria necessário para que o comando BREAK de fato fosse implementado corretamente. Seria necessário adicionar neste exato local o fluxo do comando IF. E quando a expressão de teste do comando IF fosse verdadeira, aí sim entraria o comando BREAK e o fluxo iria seguir o que está sendo mostrado na imagem. Note também que o comando BREAK pode vir antes, durante ou depois que a rotina do laço tenha sido executada. Normalmente ele estará ou antes ou depois. Quando está no meio, significa na verdade que dividimos a rotina em duas. Mas para simplicidade, do fluxo de execução, não estou incluindo este tipo de operação.

No entanto, acredito que você tenha conseguido entender o conceito a ser aplicado aqui. Mas lembre-se de uma coisa. O comando BREAK, também está ligado a um outro tipo de comando de controle de fluxo. Entretanto, por hora, vamos deixar as coisas assim. E daremos um passo de cada vez.

Agora podemos ver um outro comando, que é o último comando que poderá aparecer em um laço. No entanto, diferente dos demais comandos visto até este momento. O próximo comando somente existe dentro de laços. Sendo necessário um cuidado extra com ele.


Comando CONTINUE

Este comando CONTINUE e essencialmente perigoso quando usado dentro de um laço. Principalmente um que venha a utiliza o comando WHILE ou o casal DO WHILE. Isto por que, é muito, mas muito comum mesmo, criamos laços infinitos, quando este comando aparece dentro de um laço. Porém, mesmo em um o laço FOR será explicado depois, que aparentemente seria mais resistente a se tornar um laço infinito. Pode sim acontecer, de termos um laço infinito sendo criado. Somente por conta de uma breve distração, durante a fase de implementação, que exigiu a utilização de um comando CONTINUE. Assim fique de sobre aviso e acenda o alerta amarelo, sempre que tiver de usar, ou vir a notar este comando CONTINUE em algum trecho do código. Sendo que ele estará sempre vinculado a algum laço. Mas redobre a sua atenção especialmente em laços WHILE e laços DO WHILE.

Como este comando é extremamente arriscado, se for mal utilizado. Vamos fazer as coisas de uma maneira um pouco diferente, neste caso específico. Vamos começar primeiro entendo o fluxo de execução, quando este comando ocorre. Para tal coisa, vamos fazer uso da imagem logo abaixo.


Imagem 06

O mesmo recado que foi dado para os demais comandos, BREAK e RETURN, valem aqui também. Porém aqui, e neste caso específico, aquele recado de se utilizar o comando, seja ele, o comando BREAK ou RETURN, como sendo uma ROTINA dentro do comando IF. É ainda mais reforçado. Isto por que como você pode notar na imagem 06, nada que estiver dentro, do que seria a rotina do laço, será executado. E diferente dos demais comandos que fazem o laço ser encerrado. Este comando CONTINUE, faz com que o fluxo de controle passe imediatamente para o começo do laço.

Sendo assim, se não existir algum tipo de condição, ligada a algum evento, que faça a expressão do laço ser falsa. O laço irá inevitavelmente entrar em um loop infinito. Por isto é necessário um cuidado extra ao utilizar este comando CONTINUE. Muitas linguagens de programação, não utilizam, ou implementam o comando GOTO, justamente por conta deste tipo de problema em potencial. Porém se bem utilizado, e implementado da maneira correta, este comando CONTINUE, é de fato muito útil em diversas situações. Mas tenha calma e bastante atenção quando for usar o mesmo.

Para demonstrar o potencial risco de uma implementação descuidada. Onde este comando aparece. Vamos criar um código, que propositalmente só será encerrado devido a algum evento externo. Para isto vamos utilizar o que é visto logo abaixo.

01. //+------------------------------------------------------------------+
02. #property copyright "Daniel Jose"
03. //+------------------------------------------------------------------+
04. void OnStart(void)
05. {
06.     Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway...");
07. 
08.     Procedure_Loop();
09. 
10.     Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway...");
11. }
12. //+------------------------------------------------------------------+
13. void Procedure_Loop(void)
14. {
15.     char info = 10;
16. 
17.     Print(__FUNCTION__, "  ", __LINE__, " : Info (", info, ")");
18.     
19.     while ((info) && (!TerminalInfoInteger(TERMINAL_KEYSTATE_ESCAPE)) && (!IsStopped()))
20.     {
21.         if (info) continue;
22. 
23.         info = info - 3;
24.                
25.         Print(__FUNCTION__, "  ", __LINE__, " : Info (", info, ")");
26. 
27.         if (info < -5) return;
28.     }
29.     Print(__FUNCTION__, "  ", __LINE__, " : Info (", info, ")");
30. }
31. //+------------------------------------------------------------------+

Código 07

Antes de falarmos o que está ocorrendo aqui neste código 07, vamos ver o resultado da execução do mesmo. Como se trata de um código que irá entrar em um loop infinito, esperando que algum evento ocorra. Não usaremos uma imagem estática. Mas sim uma animação onde podemos ver como fiz para encerrar a execução da aplicação. Esta animação pode ser vista logo abaixo.


Animação 01

Agora preste atenção meu caro leitor. Isto daqui só aconteceu, porque implementei uma maneira de sair do laço infinito que estamos criando. Sem que tal implementação fosse feita, ficaríamos presos ali para sempre. Ou até alguém decidir remover a aplicação na marra. Removendo-a de maneira forçada do MetaTrader 5. Em nenhuma outra situação ela seria encerrada. Dado este aviso e alerta, vamos ver o que está acontecendo aqui no código 07.

Como este código é uma variação dos demais códigos que estamos utilizando neste artigo. Podemos focar a explicação nas partes realmente importantes. A primeira está no fato da variável da linha 15 está sendo declarada de modo a permitir que o laço WHILE seja executado. Como você pode observar na linha 19, onde o laço se inicia. A próxima coisa a ser observada é o fato de que temos três condições para poder encerrar o laço. A primeira é que a variável info se torne falsa. A segunda é que a tecla ESC seja pressionada. E a terceira é que você peça para encerrar o script. No caso desta terceira, sem que esta condição fosse adicionada. Assim que você pedisse para encerrar o script, o MetaTrader 5 iria tentar fazer isto, até conseguir. Quando conseguisse iria ser mostrada uma outra mensagem no terminal. Como você pode notar logo abaixo.


Imagem 07

Sendo este o pior dos cenários possíveis para encerramento do código. Porém vale ressaltar mais uma vez. Esta mensagem que aparece na imagem 07, somente ocorrerá se a terceira condição que é vista na linha 19 do código 07 não existisse. Como ela existe, o resultado final seria o mesmo que você pode observar na animação. Dando assim a impressão de que o código foi finalizado de maneira adequada.

Mas o ponto aqui, é justamente a linha 21. Note que apesar da presença do comando IF a ponto de verificar se iriamos ou não mudar algo no laço. O fato de que a rotina dentro do comando IF ser somente um comando CONTINUE. Força todo o laço a entrar em um loop infinito. Isto por que nenhuma outra parte da rotina do comando WHILE seria executada.

No entanto, pequenas variações nestes mesmos códigos o tornam menos arriscado. Mesmo que ainda assim, as linhas 23 até 27, jamais venham a ser executadas. Um exemplo disto, seria modificar o código 07, para algo como visto no código 08, logo abaixo.

01. //+------------------------------------------------------------------+
02. #property copyright "Daniel Jose"
03. //+------------------------------------------------------------------+
04. void OnStart(void)
05. {
06.     Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway...");
07. 
08.     Procedure_Loop();
09. 
10.     Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway...");
11. }
12. //+------------------------------------------------------------------+
13. void Procedure_Loop(void)
14. {
15.     char info = 10;
16. 
17.     Print(__FUNCTION__, "  ", __LINE__, " : Info (", info, ")");
18.     
19.     while (((info = info - 3) > 0) && (!TerminalInfoInteger(TERMINAL_KEYSTATE_ESCAPE)) && (!IsStopped()))
20.     {
21.         if (info) continue;
22. 
23.         info = info - 3;
24.                
25.         Print(__FUNCTION__, "  ", __LINE__, " : Info (", info, ")");
26. 
27.         if (info < -5) return;
28.     }
29.     Print(__FUNCTION__, "  ", __LINE__, " : Info (", info, ")");
30. }
31. //+------------------------------------------------------------------+

Código 08

Neste caso, quando executamos o código 08. Iremos ver no terminal uma informação diferente do que havia sido visto na animação 01. Como você pode observar logo abaixo.


Imagem 08

Note que aqui temos valores diferentes para info. Mas como isto foi acontecer? Bem meu caro leitor. Isto se deve justamente a uma pequena mudança no código. Justamente na linha 19, na primeira condição presente na expressão do comando WHILE. Note que neste caso específico, já não temos mais um loop infinito sendo criado. Mas isto não tornar o restante da rotina dentro do laço, algo executável. Isto por que, bem lá no fundo, este procedimento Procedure_Loop, pode ser resumido como sendo algo mostrado no fragmento abaixo.

                   .
                   .
                   .
12//+------------------------------------------------------------------+
13void Procedure_Loop(void)
14{
15    char info = 10;
16
17    Print(__FUNCTION__, "  ", __LINE__, " : Info (", info, ")");
18    
19    while (((info = info - 3) > 0) && (!TerminalInfoInteger(TERMINAL_KEYSTATE_ESCAPE)) && (!IsStopped()));
20
21    Print(__FUNCTION__, " 29 : Info (", info, ")");
22}
23//+------------------------------------------------------------------+

Fragmento 01

Isto justamente por conta da presença do comando CONTINUE na linha 21, em um comando IF que o fará ser executado toda vez dentro do laço. Bem, isto foi interessante. Mas e se no lugar de usar o comando WHILE, tivéssemos, por qualquer motivo usar o comando DO WHILE. O que poderia ocorrer? Neste caso, meu caro leitor, definitivamente teríamos um cenário bastante interessante. E que para muitos será bem intrigante. Isto porque, dependendo de como você venha a implementar seu código, ele pode funcionar de uma maneira bem complexa.

Então, vamos experimentar uma versão bem simples, que tem como objetivo mostrar o que acontece no caso de usarmos um comando CONTINUE em um laço DO WHILE. Este exemplo pode ser visto no código 09 visto imediatamente abaixo.

01. //+------------------------------------------------------------------+
02. #property copyright "Daniel Jose"
03. //+------------------------------------------------------------------+
04. void OnStart(void)
05. {
06.     Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway...");
07. 
08.     Procedure_Loop();
09. 
10.     Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway...");
11. }
12. //+------------------------------------------------------------------+
13. void Procedure_Loop(void)
14. {
15.     char info = 10;
16.     ulong counter = 0;
17. 
18.     Print(__FUNCTION__, "  ", __LINE__, " : Info (", info, ")");
19.     
20.     do
21.     {
22.         Sleep(500);
23. 
24.         Print(__FUNCTION__, "  ", __LINE__, " : Counter (", counter = counter + 1, ")");
25. 
26.         if (info) continue;
27.               
28.         Print(__FUNCTION__, "  ", __LINE__, " : Info (", info, ")");
29. 
30.     }while ((info = info - 2) > 0);
31. 
32.     Print(__FUNCTION__, "  ", __LINE__, " : Info (", info, ")");
33. }
34. //+------------------------------------------------------------------+

Código 09

Apesar de que você, muito provavelmente venha a imaginar que temos um laço infinito sendo criado aqui. Isto não irá ocorrer por conta de um detalhe simples que foi mostrado nos códigos anteriores dentro deste tópico. Porém, muitos programadores com menos experiência com o laço DO WHILE, logo imaginam que no momento que a linha 26 for executada, o laço irá voltar para a linha 20. No entanto, este tipo de pensamento surge justamente devido ao fato, de que o programador, desconhece o fluxo de execução do comando DO WHILE. Vimos no artigo anterior, qual seria o fluxo de execução. Portanto não iriei entrar em detalhes novamente aqui. Mas um fato, pode e será comprovado quando você estudar este código. O de que a linha 28, JAMAIS será executada dentro do que é visto no código 09. Isto justamente por conta da linha 26 e de como o fluxo de execução funciona no comando DO WHILE.

Para provar isto, ao invés de colocar uma imagem, achei melhor usar uma animação. Assim, ou meu ver, a didática fica muito melhor e você pode começar a pensar, no motivo que explica o fato do código 09 funcionar como ele funciona. A devida animação é vista logo a seguir. Então preste atenção a ela e tente entender como e por que ela acontece da maneira como acontece.


Animação 02


Considerações finais

Neste artigo, tentei ao máximo explicar da forma, que pudesse ser a mais didática e simples possível. Como trabalhar com os comandos RETURN, BREAK e CONTINUE. Isto quando estamos os usando em algum laço. Apesar de todo o conteúdo ter sido focado na utilização do laço WHILE e do casal DO WHILE. Este conteúdo demonstrado neste artigo, também se aplica ao comando FOR. Apesar de ele ainda não ter sido explicado.

Porém, é imprescindível que você, meu caro e estimado leitor. Procure estudar ao máximo e praticar bastante o que foi visto neste artigo. Isto por que, conforme formos progredindo em direção a um nível mais elevado de programação. Será exigido cada vez mais o perfeito entendimento do que está sendo mostrado aqui. Isto por que, assuntos e temas já mostrados não serão debatidos conforme as coisas forem se tornando mais complexas.

Sendo assim, aproveite ao máximo os códigos que irão estar disponíveis no anexo. E estude com bastante calma, atenção e tentando compreender como estes três comandos visto neste artigo, afetam o fluxo de código durante a execução de seus aplicativos. No demais, nos vemos no próximo artigo. Então até breve.


Arquivos anexados |
Anexo.zip (2.72 KB)
Agrupamento de séries temporais na inferência causal Agrupamento de séries temporais na inferência causal
Os algoritmos de agrupamento em aprendizado de máquina são ferramentas importantes de aprendizado não supervisionado que permitem dividir os dados brutos em grupos com características semelhantes. Com esses grupos, é possível, por exemplo, realizar análise de mercado para um cluster específico, identificar os clusters mais resilientes em novos conjuntos de dados e também realizar inferências causais. Este artigo apresenta um método original para o agrupamento de séries temporais, utilizando a linguagem Python.
Introdução ao MQL5 (Parte 6): Um Guia para Iniciantes sobre Funções de Array em MQL5 Introdução ao MQL5 (Parte 6): Um Guia para Iniciantes sobre Funções de Array em MQL5
Embarque na próxima fase da nossa jornada com MQL5. Neste artigo esclarecedor e amigável para iniciantes, exploraremos as funções restantes de arrays, desmistificando conceitos complexos para capacitá-lo a criar estratégias de negociação eficientes. Discutiremos as funções ArrayPrint, ArrayInsert, ArraySize, ArrayRange, ArrayRemove, ArraySwap, ArrayReverse e ArraySort. Eleve sua expertise em negociação algorítmica com essas funções essenciais de arrays. Junte-se a nós no caminho para a maestria em MQL5!
Negociação de Notícias Simplificada (Parte 1): Criando um Banco de Dados Negociação de Notícias Simplificada (Parte 1): Criando um Banco de Dados
A negociação de notícias pode ser complicada e esmagadora. Neste artigo, passaremos pelos passos para obter dados de notícias. Além disso, aprenderemos sobre o Calendário Econômico do MQL5 e o que ele tem a oferecer.
O Método de Agrupamento para Manipulação de Dados: Implementando o Algoritmo Iterativo Multicamadas em MQL5 O Método de Agrupamento para Manipulação de Dados: Implementando o Algoritmo Iterativo Multicamadas em MQL5
Neste artigo, descrevemos a implementação do Algoritmo Iterativo Multicamadas do Método de Agrupamento para Manipulação de Dados em MQL5.