4 - Estruturas Condicionais

As estruturas condicionais permitem determinar qual é a ação a ser tomada com base no resultado de uma expressão condicional. Por exemplo, deseja-se imprimir na tela de um sistema congratulações às mulheres caso seja o Dia Internacional da Mulher. O comando se no seguinte algoritmo

Se o sexo é feminino e o dia é 8 e o mês é 3, então
    Imprima "Parabéns, mulher, pelo seu dia!"

determina se o teste condicional "sexo é feminino e o dia é 8 e o mês é 3" é verdadeiro ou falso. Se a condição for verdadeira, então é impresso "Parabéns, mulher, pelo seu dia!" e o próximo comando na sequência é executado. Se a condição for falsa, o comando de impressão é ignorado e o próximo comando na sequência é executado.

fluxograma_estrutura_condicional_simples.png

Seja um outro exemplo: suponha que a média para um aluno passar direto em uma disciplina de um curso de Engenharia da Computação seja 60. Caso não obtenha no mínimo 60, deverá realizar um exame. Assim, o comando se/senão no seguinte algoritmo

Se média é maior ou igual a 60, então
    Imprima "Aprovado!"
senão
    Imprima "Exame!"

imprime "Aprovado!" se a média é no mínimo 60 e imprime "Exame!" caso a média seja menor que 60. Independente do resultado, o próximo comando na sequência é executado. Assim, a estrutura se/senão permite especificar que uma ação deve ser executada quando a condição é verdadeira e uma ação diferente quando a condição é falsa.

fluxograma_estrutura_condicional_composta.png

A linguagem C/C++ oferece três estruturas condicionais:

  1. if: estrutura condicional simples;
  2. if/else: estrutura condicional composta;
  3. switch: alternativa de estrutura condicional composta, mas possui algumas limitações em relação à estrutura if e else.

4.1 Estrutura Condicional Simples — if

O uso de uma estrutura condicional simples na linguagem C/C++ possui a sintaxe representada na Figura a seguir.

estrutura_condicional_simples(1).png

Percebe-se que há duas formas de estrutura condicional simples:

  1. sem chaves: uma única instrução é executada se a condição resultar em verdadeira;
  2. com chaves: mais de uma instrução é executada se a condição resultar em verdadeira.

Exemplo 1

Na estrutura condicional simples sem chaves, cuja forma geral é apresentada a seguir, a instrução no corpo do if só será executada se o teste condicional resultar em um valor verdadeiro. Um teste condicional é uma comparação que possui dois valores possíveis: verdadeiro ou falso.

// Forma geral da estrutura condicional simples com apenas 1 instrução 
// a ser executada se o teste condicional resultar em verdadeiro
if (Teste Condicional)
  instrução; // corpo do if

O trecho seguinte de um programa em C/C++ implementa o problema: "Suponha que se deseje parabenizar as mulheres pelo seu dia (8 de março). Caso não seja o dia das mulheres ou o usuário seja homem, não emite mensagem".

if(sexo_usuario=='f' && dia==8 && mes==3)
  cout << "Parabens, mulher, pelo seu dia!";

No programa descrito anteriormente o teste é realizado e, caso seu resultado seja um valor verdadeiro é impressa uma mensagem. Note que existe apenas uma instrução a ser executada caso o resultado do teste seja verdadeiro. Para imprimir a frase de congratulações, o sexo deverá ser 'f', o dia 8 e o mês 3, resultando em verdadeiro o teste condicional.

Exemplo 2

Em C/C++ é obrigatória a utilização de chaves quando houver mais de uma instrução a ser executada quando a expressão condicional for verdadeira. A forma geral da estrutura condicional simples com chaves é apresentada a seguir.

// Forma geral da estrutura condicional simples com chaves 
// a ser executada se o teste condicional resultar em verdadeiro
if (Teste Condicional)
{
  instrução1; // corpo do if: instrução1 à instruçãon
  instrução2;
  instruçãon;
}

As instruções entre as chaves que fazem parte da estrutura condicional if só serão executadas se o teste condicional for verdadeiro. A chave de abertura indica início do bloco de instruções que será executado se o teste condicional for verdadeiro. A outra chave indica o fim do bloco de instruções. Esse bloco de instruções que se situa entre as chaves é chamado de corpo da estrutura condicional. Considerando o enunciado anterior, acrescido de contar o número de mulheres que executaram o programa, o trecho seria modificado como segue:

if(sexo_usuario=='f' && dia==8 && mes==3)
{
  cout << "Parabéns, mulher, pelo seu dia!" << endl;
  cout << "Você é a " << cont + 1 << "a. mulher a acessar o sistema hoje." << endl;
  cont++; // ou cont = cont + 1. Inicialmente, cont receberá o valor 0.
}

Verifique que há três instruções no corpo da estrutura condicional simples if: dois cout e um incremento de uma variável que conta o número de mulheres. Assim, as chaves devem ser utilizadas para que as instruções sejam executadas em sequência.

Uma variável que tem o propósito de contar coisas é denominada de variável contadora. Seu valor inicial, normalmente, é igual a zero e seu conteúdo é incrementado, geralmente, em 1.

Exemplo 3

Suponha que se deseje verificar quantas notas de um total de 4 são maiores que 90.

cont = 0;
if (n1 > 90)
  cont++;
if (n2 > 90)
  cont++;
if (n3 > 0)
  cont++;
if (n4 > 90)
  cont++;
 
cout << "A quantidade de notas maior que 90 é: " << cont;

Verifique que há a necessidade de se verificar cada uma das notas que, sendo maior que 90, incrementa-se a variável contadora.

4.2 Estrutura Condicional Composta — if/else

Na linguagem de programação C/C++, o problema da impressão de Aprovado ou Exame seria resolvido utilizando-se a estrutura condicional composta:

if(media >= 60)
  cout << "Aprovado!";
else
  cout << "Exame!";

O uso de uma estrutura condicional composta na linguagem C/C++ possui a sintaxe representada na Figura a seguir.

estrutura_condicional_composta(1).png

Percebe-se que há quatro formas de estrutura condicional composta:

  1. corpo do if e do else com apenas uma instrução;
  2. corpo do if e do else com mais de uma instrução;
  3. corpo do if com apenas uma instrução e corpo do else com mais de uma instrução;
  4. corpo do if com mais de uma instrução e corpo do else com apenas uma instrução.

Exemplo

Considere o seguinte programa que faz a divisão de dois números inteiros passados pelo usuário. Lembre-se que é impossível fazer divisão por zero. Emita uma mensagem caso isso ocorra.

#include <iostream>
using namespace std;
 
int main()
{
  int dividendo, divisor;
  float quociente;
 
  cout << "Entre com o dividendo e o divisor, respectivamente: ";
  cin >> dividendo >> divisor;
 
  if (divisor != 0)
  {
    quociente = (float) dividendo / divisor;
    cout << "O quociente é: " << quociente << endl;
  }
  else
    cout << "Impossível fazer a divisão. O divisor é igual a zero." << endl;
 
  return 0;
}

Neste exemplo, deve-se verificar se o divisor é diferente de zero, pois só assim é possível fazer a divisão. Um dado importante é que o quociente da divisão entre números inteiros pode ser um número real. Assim, mesmo declarando a variável quociente como float, é necessário que se converta o valor do dividendo ou do divisor para um número real. Isso é feito colocando-se o tipo float entre parênteses antes da variável, neste caso dividendo. Este tipo de conversão é denominado Casting ou Transformação Explícita de dados.

Note que há duas instruções (nas linhas 14 e 15) que serão executadas caso o divisor seja diferente de zero. Assim, as chaves devem ser utilizadas.

Teste de mesa do programa de divisão utilizando dividendo igual à 21 e divisor igual à 0 (zero)

Variáveis Comparação Saída
Linha dividendo divisor quociente divisor != 0
6 lixo lixo
7 lixo lixo lixo
9 lixo lixo lixo "Entre com o dividendo e o divisor, respectivamente:"
10 21 0 lixo
12 21 0 lixo 0 (Falso)
18 21 0 lixo "Impossível fazer a divisão. O divisor é igual a zero."

Teste de mesa do programa de divisão utilizando dividendo igual à 21 e divisor igual à 4

Variáveis Comparação Saída
Linha dividendo divisor quociente divisor != 0
6 lixo lixo
7 lixo lixo lixo
9 lixo lixo lixo "Entre com o dividendo e o divisor, respectivamente:"
10 21 4 lixo
12 21 4 lixo 1 (Verdadeiro)
14 21 4 5.25
15 21 4 5.25 "O quociente é: 5.25"

4.3 Estruturas condicionais aninhadas

Uma estrutura condicional está aninhada quando é utilizada dentro de outra estrutura condicional.

Exemplo 1

Dados 3 números inteiros distintos passados pelo usuário, verificar o maior deles.

#include <iostream>
using namespace std;
 
int main()
{
  int n1, n2, n3;
 
  cout << "Entre com 3 numeros inteiros: ";
  cin >> n1 >> n2 >> n3;
 
  if (n1 > n2)
    if (n1 > n3)
      cout << "O maior é: " << n1;
    else
      cout << "O maior é: " << n3;
  else
    if (n2 > n3)
      cout << "O maior é: " << n2;
    else
      cout << "O maior é: " << n3;
 
  return 0;
}

Verifique que caso n1 seja maior que n2 será executada uma estrutura condicional composta (linhas 12 a 15). Similarmente, caso n1 não seja maior que n2, será executada uma estrutura condicional composta (linhas 17 a 20). Verifique, também, que o else da linha 16 refere-se ao if mais próximo sem else, no caso o if da linha 11. Já o else da linha 14 refere-se ao if da linha 12.

Neste exemplo não foram utilizadas chaves, pois cada estrutura condicional composta equivale a uma instrução. O código a seguir equivale ao anterior, com a diferença do uso das chaves.

#include <iostream>
using namespace std;
 
int main()
{
  int n1, n2, n3;
 
  cout << "Entre com 3 numeros inteiros: ";
  cin >> n1 >> n2 >> n3;
 
  if (n1 > n2)
  {
    if (n1 > n3)
      cout << "O maior é: " << n1;
    else
      cout << "O maior é: " << n3;
  }
  else
  {
    if (n2 > n3)
      cout << "O maior é: " << n2;
    else
      cout << "O maior é: " << n3;
  }
 
  return 0;
}

Exemplo 2

Seja uma calculadora de 4 operações aritméticas: adição, subtração, multiplicação e divisão. A entrada segue o seguinte formato: operando operador operando. Exemplo: se o usuário digitar $5 * 7$ será impresso "O resultado da multiplicação é: 35". Caso o operador seja inválido, emita uma mensagem.

#include <iostream>
using namespace std;
 
int main()
{
  float n1, n2, res;
  char op;
 
  cout << "Digite NUMERO OPERADOR NUMERO: ";
  cin >> n1 >> op >> n2;
 
  if (op == '+')
  {
    res = n1 + n2;     
    cout << "O resultado da soma é: " << res;
  }
  else 
    if (op == '-')
    { 
      res = n1 - n2; 
      cout << "O resultado da subtração é: " << res;
    }
    else 
      if (op == '/')
      {
        res = n1 / n2;
        cout << "O resultado da divisão é: " << res;
      }
      else 
        if (op == '*')
        {
           res = n1 * n2;
           cout << "O resultado da multiplicação é: " << res;
        }
        else
          cout << "Operador inválido!";
 
  cout << endl;
  return 0;
} // fim main

Verifique que a instrução a ser executada quando op é diferente do caracter '+' é uma estrutura condicional composta, ou seja, existe uma estrutura condicional dentro (aninhada) de outra. O mesmo ocorre quando op é diferente de '-' e de '/'.

Entretanto, existem várias expressões condicionais que, a partir do momento em que uma é verdadeira, não há a necessidade de se verificar as demais, pois a variável op só pode ser um dos operadores aritméticos ou um operador inválido (diferente dos demais). Assim, uma sintaxe mais enxuta ao invés do uso da identação, é colocar o comando if na mesma linha do else, evitando-se muitos espaçamentos e quebras de linhas, conforme o código a seguir.

#include <iostream>
using namespace std;
 
int main()
{
  float n1, n2, res;
  char op;
 
  cout << "Digite NUMERO OPERADOR NUMERO: ";
  cin >> n1 >> op >> n2;
 
  if (op == '+')
  {
    res = n1 + n2;     
    cout << "O resultado da soma é: " << res;
  }
  else if (op == '-')
  { 
    res = n1 - n2; 
    cout << "O resultado da subtração é: " << res;
  }
  else if (op == '/')
  {
    res = n1 / n2;
    cout << "O resultado da divisão é: " << res;
  }
  else if (op == '*')
  {
    res = n1 * n2;
    cout << "O resultado da multiplicação é: " << res;
  }
  else
    cout << "Operador inválido!";
  cout << endl;
  return 0;
} // fim main

Assim, a construção mais adequada para a resolução deste problema é o uso de estruturas condicionais compostas encadeadas if/else. Por exemplo, se op é o caracter '#', a expressão condicional da linha 12 resulta em falsa. Daí a execução vai para a linha 17, na qual é verificada outra expressão condicional, que também resulta em falsa. Como '#' não é igual aos caracteres '/' e '*', chega-se ao último else, no qual é impressa a mensagem "Operador inválido!".

Considere na Tabela seguinte o Teste de Mesa para uma entrada: "15 # 6" (sem aspas).

Variáveis Comparações Saída
Linha n1 n2 res op op == '+' op == '-' op == '/' op == '*'
6 lixo lixo lixo
7 lixo lixo lixo lixo
9 lixo lixo lixo lixo Digite NUMERO OPERADOR NUMERO:
10 15 6 lixo '#'
12 15 6 lixo '#' Falso
17 15 6 lixo '#' Falso
22 15 6 lixo '#' Falso
27 15 6 lixo '#' Falso
33 15 6 lixo '#' Operador inválido!

Agora considere na Tabela seguinte o Teste de Mesa para uma entrada: "15 - 6" (sem aspas). Caso op seja o caracter ‘-’, a expressão condicional da linha 12 resulta em falsa. Daí a execução vai para a instrução de linha 17, na qual resulta em verdadeira. Assim, como as demais instruções possuem else, a execução do programa vai para a próxima instrução após eles, o cout « endl;, que está na \textit{linha 34}.

Variáveis Comparações Saída
Linha n1 n2 res op op == '+' op == '-' op == '/' op == '*'
6 lixo lixo lixo
7 lixo lixo lixo lixo
9 lixo lixo lixo lixo Digite NUMERO OPERADOR NUMERO:
10 15 6 lixo '-'
12 15 6 lixo '-' Falso
17 15 6 lixo '-' Verdadeiro
19 15 6 9 '-'
20 15 6 9 '-' O resultado da subtração é: 9

4.4 Alternativa de Estrutura Condicional Composta — switch-case

Embora construções if - else possam executar testes para escolha de uma entre várias alternativas, muitas vezes são deselegantes. O comando switch tem um formato limpo e claro. Sua forma geral é:

switch (nome da variável)
{    
   case constante1:
      instrução1;
      instrução2;
      ...
      break;
   case constante2:
      instrução3;
      instrução4;
      ...
      break;
   default:
      instrução5;
      instrução6;
      ...
}

O comando switch possui as seguintes regras:

  • O corpo de um switch deve estar entre chaves;
  • Pode haver nenhuma, uma ou mais instruções seguindo cada caso. Geralmente, a última instrução de um caso é break, que causa a saída imediata de todo o corpo do switch. Na falta dele, todas as instruções após o caso escolhido serão executadas, mesmo as que pertencem aos casos seguintes;
  • switch testa a variável que deve ser do tipo int ou char;
  • Não se pode usar uma variável ou expressão lógica como rótulo de caso (que vem após o case). É apenas permitido constantes do tipo int ou char;
  • Cada um dos cases pode ser considerado um if;
  • Um caso default é opcional. Pode ser encarado como o else de todos os ifs. Ou seja, se nenhum caso for satisfeito e existir um caso default, a execução começará nele.

Exemplo 1

Resolução da calculadora utilizando switch.

#include <iostream>
using namespace std;
 
int main()
{
  float n1, n2, res;
  char op;
 
  cout << "Digite NUMERO OPERADOR NUMERO: ";
  cin >> n1 >> op >> n2;
 
  switch (op)
  {
    case '+': 
      res = n1 + n2;     
      cout << "O resultado da soma é: " << res;
      break;
    case '-':
      res = n1 - n2; 
      cout << "O resultado da subtração é: " << res;
      break;
    case '/':
      res = n1 / n2;
      cout << "O resultado da divisão é: " << res;
      break;
    case '*':
      res = n1 * n2;
      cout << "O resultado da multiplicação é: " << res;
      break;
    default:
      cout << "Operador inválido!";
  } // fim switch
 
  return 0;
} // fim main

Os operadores são caracteres, por isso estão entre apóstrofos. Se a variável a ser analisada fosse do tipo inteiro, não seria correto colocar apóstrofos entre as constantes. Verifique o comando break após cada caso. Verifique também o default como última alternativa, ou seja, caso op não seja igual a nenhum dos caracteres anteriores.

Exemplo 2

Suponha que se deseje permitir que o usuário do programa da calculadora utilize o sinal * ou x para indicar multiplicação e o sinal / ou \ para indicar divisão. Neste exemplo, alguns casos devem executar as mesmas instruções, daí a construção de casos sem break (linhas 22 e 27).

#include <iostream>
using namespace std;
 
int main()
{
  float n1, n2, res;
  char op;
 
  cout << "Digite NUMERO OPERADOR NUMERO: ";
  cin >> n1 >> op >> n2;
 
  switch (op)
  {
    case '+': 
      res = n1 + n2;     
      cout << "O resultado da soma é: " << res;
      break;
    case '-':
      res = n1 - n2; 
      cout << "O resultado da subtração é: " << res;
      break;
    case '\\':
    case '/':
      res = n1 / n2;
      cout << "O resultado da divisão é: " << res;
      break;
    case 'x':
    case '*':
      res = n1 * n2;
      cout << "O resultado da multiplicação é: " << res;
      break;
    default:
      cout << "Operador inválido!";
  } // fim switch
 
  return 0;
} // fim main

4.5 Exercícios

  1. Em uma empresa brasileira, um funcionário é bem remunerado se ganha até R$5.000,00 e mal remunerado se ganha abaixo disso. Assim, faça um programa que verifique se um funcionário é bem ou mal remunerado. Faça o teste de mesa para verificar o resultado.
  2. Uma família brasileira possui cinco pessoas que trabalham fora e ajudam nos gastos domésticos. Faça um programa que verifique quantas pessoas dessa família ganham mais que o salário mínimo. Faça o teste de mesa para verificar o resultado.
  3. Faça um programa que, a partir de um mês fornecido (número inteiro de 1 a 12), apresente o nome dele por extenso ou uma mensagem de mês inválido. Faça o teste de mesa para verificar o resultado.
  4. Faça um programa que calcule as raízes da equação de segundo grau a partir de seus coeficientes $a$, $b$ e $c$: $ax^2+bx+c=0$. Para calcular a raiz quadrada, utilize a função sqrt(número) da biblioteca cmath. Faça o teste de mesa para verificar o resultado.
  5. Faça um programa que, dados 3 números inteiros, imprime-os em ordem crescente. Faça o teste de mesa para verificar o resultado.
  6. A nota final de uma disciplina é calculada a partir de três notas atribuídas, respectivamente, a uma avaliação teórica, a uma avaliação prática e à entrega de exercícios. A média das três notas mencionadas anteriormente obedece aos pesos a seguir, respectivamente: 7, 2 e 1. Faça um programa que receba as três notas, calcule e mostre a média ponderada e o conceito que segue a tabela abaixo. Atenção: utilize corretamente as estruturas condicionais de forma que se evitem comparações desnecessárias. Faça o teste de mesa para verificar o resultado.
Média Conceito
De 85 a 100 A
Abaixo de 85 até 70 B
Abaixo de 70 até 60 C
Abaixo de 60 até 50 D
Abaixo de 50 E
Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License