Prévia do material em texto
Linguagem da Programação I 5º Aula Estruturas de decisão Objetivos de aprendizagem Ao término desta aula, vocês serão capazes de: • realizar testes lógicos; • criar comparações com as estruturas if else; • criar condições lógicas com switch case. Prezados(as) alunos(as): Nesta aula trataremos do conceito de estruturas de decisão em linguagem C/C++ com o objetivo de conhecer os operadores lógicos e relacionais da linguagem C/C++. Conhecer a estrutura de decisão if...else. Conhecer a estrutura de decisão switch. Criar programas em linguagem C/C++ utilizando estruturas de decisão. Primeiramente veremos as expressões lógicas que são expressões formadas a partir do uso de variáveis e constantes, operadores relacionais e operadores lógicos. As expressões lógicas são avaliadas e retornam sempre um valor lógico: verdadeiro ou falso. Boa aula! Bons estudos! 31 Seções de estudo 1 - Operadores Lógicos 1 - Operadores Lógicos 2 - Expressões simples e compostas 3 - A Declaração Switch Os operadores aritméticos são símbolos que representam operações aritméticas, ou seja, as operações matemáticas básicas. A maior parte dos operadores aritméticos do C/C++ são os mesmos que vimos em Portugol. Conforme podemos ver no Quadro abaixo, apenas acrescentamos o incremento unário (++) e o decremento unário (--): Operadores aritméticos da linguagem C /C++ Operador Operação matemática + Adição - Subtração * Multiplicação / Divisão -- Decremento Unário ++ Incremento unário % Resto da divisão inteira O operador de incremento unário (++) incrementa de 1 o seu operando. Ou seja, se eu quiser aumentar em 1 o valor de uma variável x, posso fazer x=x+1; ou escrever simplesmente x++;. De forma análoga, o operador de decremento unário (--) decrementa de 1 o seu operando. Ou seja, se eu quiser diminuir de 1 o valor de uma variável x, posso fazer x=x-1; ou escrever simplesmente x--;. Devemos evitar a utilização de operadores unários em expressões aritméticas, pois seu uso pode dificultar o entendimento da expressão. Assim, recomendo a utilização desses operadores apenas em ocasiões em que se deseja incrementar ou decrementar o operando; nunca utilizá-los em meio a expressões. A ordem de precedência entre os operadores em expressões aritméticas é a mesma já estudada, ou seja, primeiro as multiplicações e divisões e só depois as somas e subtrações. Em C também podemos utilizar os parênteses em expressões aritméticas, como fizemos em Portugol. Verifique o exemplo abaixo: //declarações de variáveis float número 1, número 2, resultado; número 1 = 22; número 2 = 22; //acrescenta 1 Número 1++; //acrescenta 1 Número 2--; Resultado = numero1 + numero 2; cout<<”O valor do número 1 agora é “<<número1; cout<<”\nO valor do número 2 agora é “<<número2; cout<<”\nA soma dos dois é”<<resultado; No código é realizada a declaração de três variáveis do tipo float, assim como em portugol é possível definir mais de uma variável na declaração do mesmo tipo. Logo em seguida os valores são inicializados e depois o primeiro recebe o incremento unário e o segundo o decremento. Na próxima linha a variável resultado recebe a soma dos dois números. Por fim acontece a impressão dos valores 23, 21 e 44. Nas linguagens de programações esse termo é utilizado para incremento ou decremento de 1 a 1, ou seja, se imprimirmos o resultado aparecerá o valor 44. Desafio: fazer a subtração, multiplicação, divisão e imprimir o resultado. 1.1 - Operadores Lógicos Os Operadores Lógicos, também chamados de Conectivos Lógicos formam, junto com os Operadores Relacionais, a base lógica da filosofia, matemática e programação. Por isso, esses conceitos são as ferramentas que utilizaremos na construção de todas as expressões lógicas. Compreender e saber aplicar ambos os conceitos, significa que temos domínio da lógica elementar e, por conseguinte, o entendimento da programação. Enquanto os Operadores Relacionais estabelecem as relações, os Conectivos irão ligar as Expressões Lógicas das relações, dando origem a novas expressões compostas por 2 ou mais sub expressões. Por fim, temos que programar e dizer ao computador o que deve ser feito e, os Conectivos Lógicos e os Operadores Relacionais serão os responsáveis por decidirem, ao analisar os valores, quais blocos de códigos deverão ser executados. CONECTIVOS LÓGICOS Os Operadores Lógicos unem duas ou mais expressões, dando origem a uma nova expressão que será avaliada independentemente. O resultado lógico será a avaliação de cada subexpressão. Toda expressão lógica avaliada resulta num valor chamado de valor lógico (Filho, 2015). Com os operadores relacionais verificamos relações entre o operando a esquerda com o operando a direita do operador relacional. Como resposta a cada expressão avaliada, teremos um valor Booleano, isto é, verdadeiro (True) ou falso (False) (Filho, 2015). Os conectivos lógicos permitem a união de duas ou mais expressões, e assim, temos uma nova expressão e seu valor lógico será o resultado das subexpressões juntas. 1.2 - Valor Lógico O valor lógico é a base de toda a computação. Há dois valores lógicos possíveis: verdadeiro ou falso, também chamados de ligado ou desligado. Os dois valores lógicos possíveis são representados matematicamente pelos números 0 (falso) e 1 (true) (FILHO, 2015). Toda expressão avaliada na computação de maneira geral, resulta num valor lógico, isto é, ou a expressão é verdadeira, ou a expressão é falsa. CONECTIVOS LÓGICOS As linguagens de programação utilizam os Conectivos 32Linguagem da Programação I Lógicos da lógica formal, ou melhor, da lógica Aristotélica para a construção de expressões. Existem dois conectivos e, mesmo que não os conheçamos formalmente, fazemos uso dos conectivos lógicos constantemente. 1. Conectivo de conjunção 2. Conectivo de disjunção Expressão Português C# conjunção E && disjunção OU || Por exemplo, a simples frase A e B são caracteres iguais e implicam numa expressão lógica que foi representada textualmente. Porém, esta pode ser facilmente escrita matematicamente, ou então, com o uso de qualquer linguagem de programação. É por isso que temos que olhar para as Linguagens de Programação como sendo formas ou estilos de Notação que utilizamos para representar e em seguida executar expressões numa sequência determinada (FILHO, 2015). A notação matemática não é diferente, porém, ela é comumente utilizada para representar sentenças matemáticas, logo, é uma notação que possui um objetivo diferente e que tem um propósito diferente. A linguagem C# não permite, não contempla a notação matemática, por isso, temos que utilizar a notação aqui estudada (FILHO, 2015). Por fim, os conectivos lógicos devem ser entendidos como ferramentas de notação utilizadas para unir expressões. AVALIAÇÃO DE EXPRESSÕES O compilador avalia cada proposição (expressão) isoladamente e atribui a esta um dos 2 valores lógicos. Por padrão, todas as expressões são avaliadas se são ou não verdadeiras. TABELA DE VALORES LÓGICOS A Tabela de Valores Lógicos é uma tabela que mostra o resultado da avaliação de dois valores lógicos. É importante observar que essa tabela NÃO é uma convenção, mas sim, o resultado da dedução lógica e que você pode facilmente comprovar cada resultado através da análise de cada proposição (NORTON, 1994). TABELA COM O CONECTIVO DE CONJUNÇÃO E Na tabela a seguir estão sendo comparado dois valores lógicos unidos pelo conectivo E. Devemos ler cada linha da seguinte maneira: O valor lógico de (X e Y) é Z. Expressão Resultado True E True True True E False False False E True False 1.3 - O Conectivo de Conjunção E O Conectivo Lógico de Conjunção || une a expressão a sua esquerda com a expressão a sua direita. Expressões com o uso do Conectivo de Conjunção dão origem a frases em Português, mais ou menos assim: X é verdadeiro e Y é verdadeiro? Nas situações em que A for verdadeiro e B também, o resultado, segundo a tabela lógica, serátambém verdadeiro. int x = 1; cout<<((X>0)&&(X<100)); No exemplo acima, temos uma expressão lógica composta constituída por duas expressões lógicas simples e ligadas pelo conectivo de conjunção. Primeira expressão simples: (var1 == 0) Segunda expressão simples: (var1 == 0) Conectivo lógico de conjunção: && Para analisarmos uma expressão lógica composta, precisamos antes, analisar suas expressões lógicas simples. A primeira expressão está perguntando se o valor da variável x é maior do que zero. A variável x está declarada na linha acima e inicializada com o valor 1, por isso, a primeira expressão é verdadeira. A segunda expressão, pergunta se o valor da variável x é menor do que 100. O valor da variável x é igual a 1 e por isso é menor do que 100. Analisado as duas expressões, acabamos por ter uma nova expressão, como pode ser visto abaixo. (true) && (true) No código acima, temos a mesma expressão do exemplo anterior, se substituirmos as duas expressões lógicas simples pelos seus respectivos valores lógicos, isto é, o valor decorrente da análise lógica. A expressão (True) && (True) se comparada com a Tabela Lógica de Valores, tem-se que o valor decorrente dessa segunda análise, constituída por dois valores lógicos ligados pelo conectivo de ligação E, será o valor lógico true. 1.4 - CONECTIVO (OU) O conectivo lógico de disjunção OU liga a expressão a sua esquerda a expressão a sua direita. Expressões com o uso do conectivo de disjunção dão origem a frases em Português, mais ou menos assim: X é verdadeiro ou Y é verdadeiro? O operador lógico OU sempre precisará que uma das 2 expressões simples avaliadas sejam verdadeiras para que avaliação seja verdadeira. No caso onde ambas as expressões simples forem verdadeiras, o resultado também será verdadeiro, porém, se ambas as expressões forem falsas, o resultado lógico será falso. int x = 1; (x > 10) || (x < 100) A expressão lógica composta que temos no código acima será desmembrada como estudado anteriormente. E, agora, para que a avaliação seja verdadeira, uma das duas expressões precisam ser verdadeiras. A primeira expressão verifica se (x > 10). A variável “x” está declarada na linha acima e inicializada com o valor igual a 1, logo, essa expressão é falsa, até porque, o valor de x não é maior do que 10. A segunda expressão (x < 100) está perguntando se o valor da variável x é menor do que o número 100. Essa expressão é verdadeira, até porque, o número 1 é menor do que o número 100. 33 No código a seguir, temos a expressão que será originada a partir do código anterior. (false) && (true). Agora, temos que o primeiro valor lógico é falso, enquanto o segundo é verdadeiro. Esses valores estão ligados pelo conectivo de disjunção utilizado para avaliar se uma das expressões é verdadeira. Como o segundo valor lógico é verdadeiro, o valor decorrente dessa análise lógica será verdadeiro. 2 - Expressões Simples e Compostas Os operadores relacionais obtém a relação entre os operandos e, por isso, podemos chamar esse tipo de expressão como sendo, expressões simples. As expressões compostas, por sua vez, são a união de duas ou mais expressões simples e ligadas por um conectivo lógico. A seguir, temos um exemplo utilizando o conectivo lógico de conjunção unindo assim, duas expressões e dando origem a uma nova expressão lógica. Como podemos ver, nos dois exemplos, estamos unindo dois membros, mas não estamos perguntando nada. Porém, a frase correta e que é utilizada pela grande maioria das linguagens de programação, senão todas, é a seguinte: “A” é verdadeiro e “B” é verdadeiro. Chamamos isso de expressão lógica, ou melhor, expressão lógica composta até porque, a expressão se origina de duas outras expressões. // EXEMPLO (isso) E (isso) // A EXPRESSAO ACIMA ORIGINOU: x E y 2.1 - Condições ou Expressões Lógicas A condição na linguagem C é definida como uma expressão que pode ser verdadeira ou falsa. A esse tipo de expressão dá-se o nome de expressão lógica. Por exemplo, (3 > 2) é uma expressão lógica que possui valor verdadeiro. Por outro lado, (4 < 1) é uma expressão lógica que possui valor falso. Os operadores (< e >) usados nos exemplos acima são chamados de operadores relacionais, pois possibilitam saber qual a relação existente entre seus dois operandos. Além desses dois, existem mais quatro operadores relacionais, que podem ser vistos na tabela seguir: Operadores Relacionais == Igual a != Diferente >= Maior ou igual > Maior que < Menor que <= Maior ou igual || OU lógico && E lógico ! Negação Além dos operadores relacionais, existem os chamados operadores lógicos ou “conectivos lógicos”. Estes servem para conectar duas expressões relacionais. Os operadores lógicos da linguagem C são apresentados na tabela a seguir: Operadores Lógicos Esses operadores OU e E devem ser sempre usados entre duas expressões relacionais como, por exemplo: ((2 > 1) || (3 < 7)): resultado VERDADEIRO ((3 < 2) && (2 == 2)): resultado FALSO ((5 ! = 0) || (1 < 2)): resultado VERDADEIRO O operador de Negação deve ser usado antes de uma expressão relacional como, por exemplo: !(2 > 1): resultado VERDADEIRO !(1 < 0): resultado FALSO Precedência de Operadores ! Operador de negação Executado Antes- menos unário (sinal) * / % Operadores Multiplicativos + - Operadores aditivos < > <= >= == != Relacionais && AND lógico Executado Depois|| OR lógico 2.2 - Estruturas de Controle de Fluxo Estruturas de controle de fluxo são comandos utilizados em uma linguagem de programação para determinar qual a ordem e quais comandos devem ser executados pelo programa em uma dada condição. C++ oferece várias opções de estrutura de controle de fluxo, todas elas herdadas da linguagem C. Neste módulo iremos ver como funcionam cada uma dessas estruturas em detalhe (CARVALHO, 2008). Geralmente, as estruturas de controle utilizam expressões condicionais. Caso a expressão retorne 0, dizemos que ela é falsa. Caso ela retorne qualquer outro valor, dizemos que ela é verdadeira. Nesse contexto, qualquer expressão pode ser utilizada desde que retorne um valor zero ou não zero. Podemos utilizar operadores aritméticos, relacionais, lógicos, desde que no final a expressão nos retorne um valor que possa ser testado. Também é possível testar várias condições ao mesmo tempo, unindo as expressões com o auxílio dos operadores AND e OR (CARVALHO, 2008). 2.2.1 - A declaração if Utilizamos a declaração if quando desejamos que o programa teste uma ou mais condições e execute um ou outro comando de acordo com o resultado desse teste. A sintaxe de if é a seguinte: if (condição) { //comandos; } else 34Linguagem da Programação I { //comandos; } A declaração if testará a condição expressa entre parênteses. Caso a condição seja verdadeira, os comandos declarados entre as chaves serão executados. A declaração else é opcional: podemos utilizá-la para determinar um conjunto de comandos que serão executados caso a condição testada seja falsa. Note que somente um dos conjuntos de comandos será executado, nunca os dois: caso a condição seja verdadeira, o bloco pertencente a if será executado; caso a condição falhe, o bloco pertencente a else será executado. O programa abaixo ilustra de maneira simples o uso da declaração if-else, obtendo um número do usuário e verificando se este valor é maior ou igual a 50. #include <iostream> using namespace std; int main() { int teste; cout<<”Digite um número qualquer:\n”; cin>> teste; if (teste > 50) { cout<<”O número que você digitou é maior que 50”; } else { cout<<”O número que você digitou é menor que 50”; } System (“PAUSE > null”); return 0; } É possível também aninhar ifs, ou seja, fazer uma declaração if dentro de outra declaração if anterior. Esse é um método muito útil em programação, mas é preciso tomar cuidado ao utilizá-lo para saber qual bloco else pertence a qual if. Em C++, o else é ligado ao if mais próximo dentro do mesmo bloco de códigoque já não tenha uma declaração else associada a ele. Para se certificar de que estamos aninhando os ifs e elses corretamente, utilizamos chaves para delimitar os diferentes blocos, como pode ser visto no código abaixo: if (x > 10) { if (x == 17) { cout<< “x é maior que 10 e igual a 17”; } else { cout<< “x é maior que 10 mas não é igual a 17”; } } else { cout << “x é menor do que 10”; } Note que a segunda declaração if está totalmente contida pelas chaves da primeira declaração if. Utilizou-se chaves em todas os blocos de comando, para melhor separar as condições dos blocos de comandos. Além disso, note o uso da tabulação para separar visualmente os diferentes blocos e declarações: poderíamos escrever todo o código sem usar tabulação, alinhando todas as linhas à esquerda, mas isso dificultaria a identificação das diferentes declarações (JAMSA, 1999). 2.2.2 – O Encadeamento If – Else if Utilizamos a variação “If – Else If ” quando desejamos que o programa teste várias condições em sequência, até encontrar uma que seja verdadeira. Sua sintaxe é muito parecida com a declaração if simples: if (condição) { //comandos; } else if (condição) { //comandos; } else if (condição) { //comandos; } else { //comandos; } Cada bloco “else if ” deverá testar uma condição diferente. O programa testará todas as condições na sequência, de cima para baixo, até encontrar uma condição verdadeira. Quando isso acontece, os comandos pertencentes ao bloco “verdadeiro” serão executados enquanto todos os outros blocos do encadeamento são ignorados. Caso nenhuma condição “else if ” seja verdadeira, executa-se o bloco de comandos pertencente ao else final. Note que o else é opcional: se o else final não estiver presente e todas as outras condições forem falsas, então nenhuma ação será realizada (JAMSA, 1999). Utilizando esse encadeamento, ampliaremos o programa anterior para que ele teste várias condições sobre um número enviado pelo usuário, até encontrar uma condição verdadeira. #include <iostream> using namespace std; int main() { int teste; cout<<”Digite um número qualquer:\n”; cin>> teste; if (teste <= 50) { cout<<”O número que você digitou é menor que 50\n”; } else if (teste > 50 && teste <= 100) { cout<<”O número digitado é maior que 50 e menor ou 35 igual a 100\n”; } else if (teste > 100 && teste <= 200) { cout<<”O número digitado é maior que 100 e menor ou igual a 200\n”; } else { cout<<”O número digitado é maior que 200\n”; } System (“PAUSE > null”); return 0; } 3 - Expressões Simples e Compostas A declaração switch é uma maneira fácil e elegante de se fazer uma tomada de decisão com múltiplas escolhas. Na declaração switch, a variável é sucessivamente testada contra uma lista de inteiros ou constantes caracteres. Quando uma associação é encontrada, o conjunto de comandos associado com a constante é executado. Veja a sintaxe de switch abaixo: switch (variável) { case valor1: //comandos; break; case valor2: //comandos; break; ... case valorx; //comandos; break; default: //comandos; } A declaração switch testa o valor de uma única variável. Note que existem vários “case”, cada um associado a um determinado valor. A declaração comparará o valor da variável com o valor de cada um dos “case”: quando uma associação é encontrada, os comandos pertencentes ao “case” relacionado são executados. Se nenhuma associação for encontrada, a declaração switch executará os comandos pertencentes ao bloco default (note que o bloco default é opcional: caso ele não exista, caso nenhuma associação seja encontrada, a declaração switch termina sem que nenhum comando seja executado) (JAMSA, 1999). O exemplo abaixo demonstra uma utilização da declaração switch. #include <iostream> using namespace std; int main() { int option; cout<<”Digite a Opção desejada:\n”; cout<<”1. Opção 1\n”; cout<<”2. Opção 2\n”; cout<<”3. Opção 3\n”; option = 0; cin>> option; switch (option) { case 1: cout<<”Você escolheu a primeira Opção\n”; break; case 2: cout<<”Você escolheu a segunda Opção\n”; break; case 3: cout<<”Você escolheu a terceira Opção\n”; break; default: cout<<”Você escolheu uma Opção inválida!\n”; } System (“PAUSE > null”); return 0; } Após o fim de cada bloco de comandos “case”, é comum utilizar o comando “break;”. Esse comando interrompe a execução do laço em que o programa se encontra, fazendo com que o programa prossiga para o próximo comando imediatamente após o laço. No caso de switch, o comando break assegura que a execução da declaração switch termine, forçando o programa a voltar para sua execução normal. Caso omitíssemos os comandos break; no fim de cada bloco, a declaração switch executaria os comandos presentes no “case” em que a associação foi encontrada, e continuaria a executar todos os comandos presentes em todos os “case” na sequência (incluindo o bloco default) até o término da declaração switch. Note que esse comportamento pode ser útil em alguns programas como, por exemplo, uma sequência de operações matemáticas onde utilizamos a declaração switch para escolher o ponto de partida da sequência (JAMSA, 1999). Retomando a aula Parece que estamos indo bem. Então, para encerrar essa aula, vamos recordar: Nesta aula, vimos que o computador não é uma máquina pensante, e sim uma máquina que executa passos e muitas vezes é preciso tomar algumas decisões nesses passos. Para isso, toda linguagem de programação desde o início tiveram preocupação com esses aspectos. Nas linguagens de alto nível como C/C++ temos as estruturas if, eles e case, que nos permitem fazer com que o computador tome decisões e assim simule ser uma máquina pensante. Pudemos aprender também como declarar e utilizar essa estrutura e como elas 36Linguagem da Programação I estão ligadas diretamente à lógica que conhecemos. Pois, no nosso dia a dia, sempre temos que tomar decisões, desde o momento que vamos atravessar uma rua até decisões mais complexas. CARVALHO, Victorio Albani de; Lógica: de programação; e-tec Brasil Colatina-es 2009. MIZRAHI, Viviane Victorine Mizrahi; Treinamento em Linguagem C++ - Modulo 2; Pearson; Edição: 2; 2005. Vale a pena Vale a pena ler Disponível em: <https://pt.wikibooks.org/wiki/ Wikilivros:P%C3%A1gina_principal>. Acesso em: 25 de nov. 2017. Disponível em: <http://www.dicasdeprogramacao. com.br/estrutura-de-decisao-se-entao-senao/>. Acesso em: 25 de nov. 2017. Vale a pena acessar Lógica: conectivos lógicos. Disponível em: <https://www. youtube.com/watch?v=i8jbzEWEOYk>. Acesso em: 25 de nov. 2017. Lógica de Programação. Disponível em: <https://www. youtube.com/watch?v=20eHzjHtaXo>. Acesso em: 25 de nov. 2017. Vale a pena assistir Minhas anotações