Olá!
Hoje vamos retomar nossa série de artigos sobre lógica de programação (ficou parada por muito tempo!!!) falando um pouco sobre estruturas de decisão.
É sempre bom avisar: essa é uma série de artigos para quem está começando a programar agora e teve pouco ou nenhum contato com outras linguagens de programação.
Assim como fizemos nos artigos anteriores, utilizaremos a linguagem AdvPL para demonstrar os exemplos.
Estruturas de Decisão
As estruturas de decisão compõe uma parte extremamente importante nos nossos algoritmos. São elas que definem fluxos diferentes de processamentos das informações, dependendo de uma ou mais condições. O ponto de decisão (duh!) sempre vai ser uma expressão booleana (verdadeiro ou falso), independente da quantidade de operadores necessários para isso.
Vamos começar analisando um código-fonte simples:
#INCLUDE "PROTHEUS.CH" /* ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ ±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±± ±±ÉÍÍÍÍÍÍÍÍÍÍÑÍÍÍÍÍÍÍÍÍÍÍÍËÍÍÍÍÍÍÍÑÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍËÍÍÍÍÍÍÑÍÍÍÍÍÍÍÍÍÍÍÍÍ»±± ±±ºPrograma ³XTSTIF ºAutor ³V. Gregório º Data ³ 13/04/14 º±± ±±ÌÍÍÍÍÍÍÍÍÍÍØÍÍÍÍÍÍÍÍÍÍÍÍÊÍÍÍÍÍÍÍÏÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÊÍÍÍÍÍÍÏÍÍÍÍÍÍÍÍÍÍÍÍ͹±± ±±ºDesc. ³ Dialog para exemplificar estruturas de decisão º±± ±±ÌÍÍÍÍÍÍÍÍÍÍØÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ͹±± ±±ºUso ³ AcademiaERP º±± ±±ÈÍÍÍÍÍÍÍÍÍÍÏÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍŒ±± ±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±± ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß */ User Function XTSTIF() //ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ //³Declaração de variáveis³ //ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ Local nRetorno := 0 Local oDlg, oGroup, oButton, oCombo, cCombo Local nPosPadrao := 1 Local aOpcoes := {"Sim","Não"} Local cTitDialog := "Estruturas de Decisão" Local cTitGroup := "Escolha um dos itens" DEFAULT nPosPadrao := 1 cCombo := aOpcoes[nPosPadrao] //ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ //³Dialog principal. Na ativação ela é centralizada.³ //ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ DEFINE MSDIALOG oDlg FROM 0,0 TO 100,230 PIXEL TITLE cTitDialog oGroup:= TGroup():New(05,05,oDlg:nClientHeight/4,(oDlg:nClientWidth/2)-5,cTitGroup,oDlg,,,.T.) oCombo:= tComboBox():New(oDlg:nClientHeight/8,10,{|u|if(PCount()>0,cCombo:=u,cCombo)},; aOpcoes,100,20,oDlg,,{||/*onChange*/},,,,.T.,,,,,,,,,aOpcoes[nPosPadrao]) //ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ //³Botão para o controle de fechamento da janela³ //ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ oButton:=tButton():New((oDlg:nClientHeight/4)+3,10,"OK",oDlg,{||oDlg:End()},100,10,,,,.T.) ACTIVATE MSDIALOG oDlg CENTERED //ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ //³Define o retorno com base na posição do combo³ //ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ nRetorno := aScan(aOpcoes,cCombo) //ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ //³***********************************************³ //³Com base na escolha do usuário, vamos ³ //³mudar o comportamento da rotina ³ //³***********************************************³ //ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ If nRetorno == 1 MsgInfo("O usuário escolheu a opção: Sim") Else MsgInfo("O usuário escolheu a opção: Não") EndIf Return nRetorno
Já utilizamos esse fonte anteriormente no artigo de posicionamento dinâmico de tela para o Protheus. Porém, com algumas alterações, ele vai nos servir em diversos exemplos.
Caso não entenda alguma função ou trechos do código, não se preocupe. Você aprenderá sobre eles em outros artigos. Vamos focar no seguinte trecho de código:
If nRetorno == 1 MsgInfo("O usuário escolheu a opção: Sim") Else MsgInfo("O usuário escolheu a opção: Não") EndIf
A rotina exibe uma tela simples para o usuário com um combo com dois itens: Sim e Não. Nesse caso, delegamos para o usuário uma escolha e, dependendo do que ele decidir, o programa irá seguir por um fluxo diferente (onde a posição no array aOpcoes é 1=Sim, 2=Não).
Repare que, o desenvolvedor poderia colocar diversos comandos dentro de cada opção (dentro do IF ou do ELSE). Nesse caso, colocamos somente um alerta com a opção escolhida.
Outra possibilidade ainda para o IF/ELSE é o fato de podermos encadear mais de uma opção. Veja o exemplo abaixo:
If nRetorno == 1 MsgInfo("O usuário escolheu a opção: Sim") ElseIf nRetorno == 2 MsgInfo("O usuário escolheu a opção: Não") Else MsgInfo("Supondo que existisse outra opção") EndIf
Para entender melhor como funcionam as estruturas de decisão, precisamos nos familiarizar com os operadores e ligações (ou conjunções) que compõe essas linhas:
Operadores
:= : Esse operador serve para a definição do valor de uma variável, ou seja, quando colocamos cVariavel := “Texto”, estamos atribuindo a string “Texto” para a variável cVariavel. Uma atribuição retorna .T. quando ela é bem sucedida.
== : Comparação de valores. Esse operador permite comparar o valor de duas variáveis ou expressões e, caso sejam iguais, retorna .T. Exemplo: “Texto” == “Texto” -> .T. , “texto” == “Texto” -> .F.
<> ou != : Diferente de… Verifica se o valor de duas variáveis ou expressões são diferentes. É o contrário de ==. Exemplo: “Texto” <> “Texto” -> .F. , “texto” <> “Texto” -> .T.
$ : Contido. Verifica se um determinado conteúdo está contido dentro de outro conjunto de conteúdos. Confuso não?!
Exemplo:
Local cNumeros := "1234567890" Local cTeste := "1" If cTeste $ cNumeros //vai entrar no if pq o texto "1" está dentro da cadeia de caracteres armazenada na variável cNumeros EndIf
() : os parânteses são utilizados para delimitar o processamento de uma expressão. Exatamente como funciona em expressões algébricas (lembra disso certo?), os parênteses internos são resolvidos antes dos parânteses externos. Exemplo: nValor := ((55*30)/100) -> 16,5
Ligações
As estruturas de decisão podem ser compostas por uma ou mais expressões booleanas. Ou seja, existem formas de unir expressões e o resultado dessa união é que determina o resultado da estrutura.
.and. : Em tradução livre: e.
If cCor == "amarelo" .and. cFormato <> "triangulo" EndIf
No exemplo acima, o IF só será .T. se a variável cCor estive preenchida com “amarelo” e se a variável cFormato não estiver preenchida com “triangulo”.
.or. : Em tradução livre: ou.
If cCor == "amarelo" .or. cFormato <> "triangulo" EndIf
No exemplo acima, o IF só será .T. caso ou cCor esteja preenchida com “amarelo” ou cFormato seja diferente de “triangulo”. Caso qualquer uma dessas afirmações seja verdadeira, a condição geral será atendida.
.xor. : Bom, esse não tem “tradução livre”….. .xor. é o código para eXclusive Or. Veja:
If cCor == "amarelo" .xor. cFormato <> "triangulo" EndIf
A expressão desse IF só será verdadeira em uma dessas situações:
- cCor está com o valor “amarelo” E cFormato é igual a “triangulo”;
- cFormato não é igual a “triangulo” e cCor não é igual a “amarelo”;
Ou seja, o .XOR. só retorna verdadeiro se apenas uma das condições for verdadeira (obrigatóriamente a(s) outra(s) tem que ser falsas). Bizarro e raramente você vai irá encontrar isso em fontes mas, se encontrar, já não precisa se assustar 😉
.not. ou ! : Esses itens servem pra negar a expressão seguinte. Basicamente, a condição será verdadeira caso o resultado seja o oposto da expressão. Exemplos:
If .not. cCor == "amarelo" EndIf If !(cCor == "amarelo") EndIf
Em ambos os exemplos o resultado será .T. se cCor estiver preenchido com qualquer valor, exceto “amarelo”.
DO CASE
A estrutura DO CASE permite que o programa analise diversas condições para a decisão no código. Vamos ao exemplo:
#INCLUDE "PROTHEUS.CH" /* ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ ±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±± ±±ÉÍÍÍÍÍÍÍÍÍÍÑÍÍÍÍÍÍÍÍÍÍÍÍËÍÍÍÍÍÍÍÑÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍËÍÍÍÍÍÍÑÍÍÍÍÍÍÍÍÍÍÍÍÍ»±± ±±ºPrograma ³XTSTCASE ºAutor ³V. Gregório º Data ³ 13/04/14 º±± ±±ÌÍÍÍÍÍÍÍÍÍÍØÍÍÍÍÍÍÍÍÍÍÍÍÊÍÍÍÍÍÍÍÏÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÊÍÍÍÍÍÍÏÍÍÍÍÍÍÍÍÍÍÍÍ͹±± ±±ºDesc. ³ Dialog para exemplificar estruturas de decisão º±± ±±ÌÍÍÍÍÍÍÍÍÍÍØÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ͹±± ±±ºUso ³ AcademiaERP º±± ±±ÈÍÍÍÍÍÍÍÍÍÍÏÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍŒ±± ±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±± ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß */ User Function XTSTCASE() //ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ //³Declaração de variáveis³ //ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ Local nRetorno := 0 Local oDlg, oGroup, oButton, oCombo, cCombo Local nPosPadrao := 1 Local aOpcoes := {"Sim","Não","Talvez","Quem sabe..."} Local cTitDialog := "Estruturas de Decisão" Local cTitGroup := "Escolha um dos itens" DEFAULT nPosPadrao := 1 cCombo := aOpcoes[nPosPadrao] //ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ //³Dialog principal. Na ativação ela é centralizada.³ //ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ DEFINE MSDIALOG oDlg FROM 0,0 TO 100,230 PIXEL TITLE cTitDialog oGroup:= TGroup():New(05,05,oDlg:nClientHeight/4,(oDlg:nClientWidth/2)-5,cTitGroup,oDlg,,,.T.) oCombo:= tComboBox():New(oDlg:nClientHeight/8,10,{|u|if(PCount()>0,cCombo:=u,cCombo)},; aOpcoes,100,20,oDlg,,{||/*onChange*/},,,,.T.,,,,,,,,,aOpcoes[nPosPadrao]) //ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ //³Botão para o controle de fechamento da janela³ //ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ oButton:=tButton():New((oDlg:nClientHeight/4)+3,10,"OK",oDlg,{||oDlg:End()},100,10,,,,.T.) ACTIVATE MSDIALOG oDlg CENTERED //ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ //³Define o retorno com base na posição do combo³ //ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ nRetorno := aScan(aOpcoes,cCombo) //ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ //³***********************************************³ //³Com base na escolha do usuário, vamos ³ //³mudar o comportamento da rotina ³ //³***********************************************³ //ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ Do Case Case nRetorno == 1 // Sim MsgInfo("O usuário escolheu a opção: Sim") Case nRetorno == 2 // Não MsgInfo("O usuário escolheu a opção: Não") Case nRetorno == 3 // Talvez MsgInfo("O usuário escolheu a opção: Talvez") Case nRetorno == 4 // Quem sabe... MsgInfo("O usuário escolheu a opção: Quem sabe...") EndCase Return nRetorno
A estrutura que nos interessa no código é o Do Case no final. Como podem ver, sua estrutura é bem robusta e indicativa das condições dos respectivos trechos de código.
Conclusão
Chegamos ao final de mais um artigo e, depois de assimilado todo o conteúdo, já nos preparamos para o próximo. Nele, vamos estudar como funcionam as estruturas de repetição (FOR e WHILE) no AdvPL… Abraços e até lá!