Operadores relacionais

Exemplos

int i, j;
i = 2;
j = 4;
printf("%d\n", i > j);     // imprime 0
printf("%d\n", i < j);     // imprime 1
printf("%d\n", i*i == j);  // imprime 1
printf("%d\n", i*j >= 10); // imprime 0

Precedência e associatividade

Atenção

A expressão

   i < j < k 

é válida mas não testa se j está entre i e k:

A expressão correta usa a conjunção de duas condições:

   i < j && j < k   

Comparações de igualdade

int i, j;
i = 2;
j = 3;
printf("%d\n", i == j);   // imprime 0
printf("%d\n", i+1 == j); // imprime 1
printf("%d\n", i != j);   // imprime 1

Atenção

Não confundir atribuições com comparações:

i = j

modifica o lado esquerdo; resultado é o valor atribuido

i == j

compara o lados esquerdo e o direito; resultado é 0 ou 1

Instrução if

if ( line_num == MAX ) line_num = 0;
// continuação do programa
...

Instrução if

Exemplo

Podemos colocar numa só linha:

if (line_num == MAX) { line_num = 0; page_num ++; } 


Mas fica mais claro se partimos em várias linhas:

if (line_num == MAX)
{
   line_num = 0;
   page_num ++;
} 

Alternativa else

Exemplo:

if (i > j) max = i; else max = j;

Alternativa else

if (i > j)
   if (i > k)
      max = i;
   else
      max = k;
else
   if (j > k)
      max = j;
   else
      max = k;

Alternativa else

Podemos também acrescentar chavetas para auxiliar a compreensão:

if (i > j) {
   if (i > k)
      max = i;
   else
      max = k;
} else {
   if (j > k)
      max = j;
   else
      max = k;
}

Alternativa else

Há quem prefira colocar sempre chavetas:

if (i > j) {
   if (i > k) {
      max = i;
   } else {
      max = k;
   }
} else {
   if (j > k) {
      max = j;
   } else {
      max = k;
   }
}

Vantagens

Ao colocarmos sempre chavetas:

if em "cascata"

Para testar condições em sequência escrevemos múltiplas instruções if em "cascata".

Exemplo:

if (n < 0)
   printf("n negativo\n");
else
   if (n == 0)
      printf("n zero\n");
   else
      printf("n positivo\n");

if em "cascata"

Apesar do segundo if estar dentro do primeiro, é preferível alinhar os else em vez de indentar:

if (n < 0)
   printf("n negativo\n");
else if (n == 0)
   printf("n zero\n");
else
   printf("n positivo\n");

if em "cascata"

Desta forma evitamos a indentação exagerada quando temos muitas condições.

if (expressão)
  instrução
else if(expressão)
  instrução
...
else if(expressão)
  instrução
else
  instrução

Exemplo: calcular comissões

Montante Comissão
Até €2500 €30 + 1.7%
€2500-€6250 €56 + 0.66%
€6250-€20K €76 + 0.34%
€20K-€50K €100 + 0.22%
€50K-€500K €155 + 0.11%
Acima de €500K €255 + 0.09%

Exemplo: calcular comissões

Introduza o valor: EUR 30000
Comissão: EUR 166.00

/* corretor.c
   Calcular a comissão de uma transação
*/
#include <stdio.h>

int main(void)
{
  float valor, comissao;

  printf("Introduza o valor: EUR ");
  scanf("%f", &valor);

  if(valor < 2500.0)
    comissao = 30.0 + 0.017 * valor;
  else if(valor < 6250.0)
    comissao = 56.0 + 0.0066 * valor;

(continua no slide seguinte)


(continuação do slide anterior)

  else if(valor < 20e3)
    comissao = 76.0 + 0.0034 * valor;
  else if(valor < 50e3)
    comissao = 100.0 + 0.0022 * valor;
  else if(valor < 500e3)
    comissao = 155.0 + 0.0011 * valor;
  else
    comissao = 255.0 + 0.0009 * valor;

  if (comissao < 39.0)
    comissao = 39.0;

  printf("Comissão: EUR %.2f\n", comissao);
}

Operadores lógicos

Podemos construir condições complexas partindo de outras mais simples usando operadores lógicos.

conjunção (\(\land\)) &&
disjunção (\(\lor\)) ||
negação (\(\neg\)) !

Exemplos:

i>=0 && i<10 
i==j || i+j==0
!(i==0)

Operadores lógicos

Operadores lógicos

Resultados dos operadores lógicos

!\(expr\)

resultado 1 se \(expr\) tem valor 0

\(expr_1\) && \(expr_2\)

resultado 1 se \(expr_1\) e \(expr_2\) são ambos diferentes de 0

\(expr_1\) || \(expr_2\)

resultado 1 se \(expr_1\) é diferente de 0 ou \(expr_2\) é diferente de 0 (ou ambos são diferentes de 0)

Em todos os outros casos: o resultado é 0.

Ordem de avaliação

Ordem de avaliação — exemplo

   (i != 0) && (j/i > 0)
  1. Primeiro é avaliada a condição i != 0
  2. Se i for diferente de 0, então é avalia j/i > 0
  3. Se i for 0 então a conjução será sempre falsa e não avaliamos j/i > 0 (evitando a divisão por zero)

Precedência e associatividade

Exemplos:

i < j && k < m

é equivalente a (i < j) && (k < m)

i < j && j < k && k < l

é equivalente a ((i < j) && (j < k)) && (k < l)

!i == 0

não é equivalente a i != 0

Cuidados com if

Um erro comum é trocar == (igualdade) por = (atribuição)

if (i == 0) ...

testa se i é igual a 0

if (i = 0) ...

atribui 0 a i e depois testa se o resultado é diferente de 0 (o que é sempre falso)

Recomendação: o gcc avisa possíveis erros deste tipo compilando com a opção -Wall

Cuidados como o else

Ao colocarmos if dentro de outro, temos de ter o cuidado de "casar" corretamente os else:

if (y != 0)
   if (x != 0)
      result = x / y;
else
   printf("erro: y igual a 0\n");

Cuidados com o else

Uma versão corretamente indentada seria assim:

if (y != 0)
   if (x != 0)
      result = x / y;
   else
      printf("erro: y igual a 0\n");

Cuidados com o else

Para associar o else ao if exterior temos de delimitar o if interior usando chavetas:

if (y != 0) {
   if (x != 0)
      result = x / y;
} else
   printf("erro: y igual a 0\n");

Recomendação: para evitar estes problemas use sempre chavetas num if que contém outro if