Lab_09_Estruturas_de_Controle

Author

Henrique Alvarenga

Published

11 de setembro de 2024

Aula: Estruturas de Controle em R

Estruturas de controle, também conhecidas como estruturas de fluxo, são um componente fundamental em qualquer linguagem de programação, incluindo R. Elas são responsáveis por controlar a ordem em que as instruções em um programa são executadas. Sem essas estruturas, um programa seguiria uma execução linear, do início ao fim, sem a capacidade de tomar decisões, repetir operações, ou reagir a diferentes condições que possam surgir durante sua execução.

Tipos de Estruturas de Controle

As estruturas de controle podem ser divididas em três categorias principais:

  1. Condicionais:
    • As condicionais, como if, else, e switch, permitem que o programa tome decisões com base em certas condições. Por exemplo, você pode querer que uma operação seja realizada apenas se um determinado critério for atendido (por exemplo, um valor ser maior que outro). Isso é essencial para criar programas que podem responder dinamicamente a diferentes tipos de entrada ou estados do sistema.
  2. Loops ou Estruturas de Repetição:
    • Loops, como for, while, e repeat, permitem que o programa repita uma sequência de instruções várias vezes. Isso é particularmente útil quando você precisa executar a mesma operação em um grande conjunto de dados ou continuar a repetir uma ação até que uma condição específica seja atendida. Por exemplo, processar todos os itens de uma lista, ou continuar pedindo ao usuário para fornecer uma entrada válida até que ele o faça.
  3. Controle de Fluxo de Execução:
    • Além das condicionais e loops, R oferece comandos como break, next, e return, que permitem controlar como e quando sair de loops, pular iterações ou retornar valores de funções. Esses comandos são cruciais para controlar de forma precisa a execução do código, tornando-o mais eficiente e robusto.

Importância das Estruturas de Controle

Estruturas de controle são a espinha dorsal da lógica de programação. Elas permitem que um programa se adapte a diferentes situações, tome decisões e execute tarefas repetitivas de forma automatizada. Sem essas estruturas, criar programas complexos, interativos, ou que possam lidar com grandes volumes de dados de maneira eficiente seria praticamente impossível. Elas permitem que o programador escreva código que é não apenas funcional, mas também eficiente, claro e fácil de manter. Em resumo, as estruturas de controle são o que transformam um conjunto simples de instruções em um programa poderoso e flexível.

Estruturas Condicionais: if, else, e ifelse()

Estrutura if e else

A estrutura if permite que o código execute determinadas instruções somente se uma condição for verdadeira. Podemos adicionar um bloco else para especificar o que deve acontecer se a condição for falsa.

Exemplo:

Code
x <- 10

if (x > 5) {
  print("x é maior que 5")
} else {
  print("x é menor ou igual a 5")
}
[1] "x é maior que 5"

Explicação: - x > 5 é a condição. Se for verdadeira, R executa o código dentro do bloco if. - Se for falsa, o bloco else é executado.

1.2. Função ifelse()

ifelse() é uma versão vetorizada do if que pode ser aplicada a vetores inteiros.

Exemplo:

Code
x <- c(1, 2, 3, 4, 5)
resultado <- ifelse(x %% 2 == 0, "Par", "Ímpar")
print(resultado)
[1] "Ímpar" "Par"   "Ímpar" "Par"   "Ímpar"

Entendendo o Código

  1. Operador de Módulo (%%):
    • O operador %% é conhecido como operador de módulo ou resto da divisão. Ele calcula o resto da divisão inteira de um número por outro. Por exemplo, 7 %% 3 resulta em 1, porque 7 dividido por 3 é igual a 2 com um resto de 1.
  2. Dividindo por 2 (x %% 2):
    • Quando usamos x %% 2, estamos dividindo o valor de x por 2 e obtendo o resto dessa divisão. Para qualquer número inteiro, se o resto da divisão por 2 for 0, isso significa que o número é par. Se o resto for 1, o número é ímpar.
  3. Comparação com 0 (x %% 2 == 0):
    • O operador == é um operador de comparação que verifica se duas expressões são iguais. No caso de x %% 2 == 0, estamos verificando se o resto da divisão de x por 2 é igual a 0.
    • Se x %% 2 resultar em 0, isso significa que x é um número par (pois números pares não têm resto quando divididos por 2). Se resultar em 1, significa que x é ímpar.

Aplicação na Função ifelse()

Dentro da linha resultado <- ifelse(x %% 2 == 0, "Par", "Ímpar"), a função ifelse() avalia a condição x %% 2 == 0:

  • Se a condição for verdadeira (x %% 2 == 0): Ou seja, se x for par, ifelse() retorna "Par".
  • Se a condição for falsa (x %% 2 != 0): Ou seja, se x for ímpar, ifelse() retorna "Ímpar".

2. Estrutura switch()

switch() permite escolher entre várias opções com base no valor de uma expressão.

Exemplo:

Code
dia <- "terça"

mensagem <- switch(dia,
  "segunda" = "Hoje é segunda-feira",
  "terça" = "Hoje é terça-feira",
  "quarta" = "Hoje é quarta-feira",
  "Outro dia"
)

print(mensagem)
[1] "Hoje é terça-feira"

Explicação: - switch() verifica o valor de dia e retorna a mensagem correspondente. - Se o valor de dia não estiver listado, retorna “Outro dia”.

3. Estruturas de Repetição: for, while, e repeat

3.1. Estrutura for

for é usada para iterar sobre uma sequência ou vetor.

Exemplo:

Code
numeros <- c(1, 2, 3, 4, 5)

for (numero in numeros) {
  print(numero * 2)
}
[1] 2
[1] 4
[1] 6
[1] 8
[1] 10

Explicação: - O loop for itera sobre cada elemento de numeros e multiplica por 2, imprimindo o resultado.

3.2. Estrutura while

while executa um bloco de código repetidamente enquanto uma condição for verdadeira.

Exemplo:

Code
i <- 1

while (i <= 5) {
  print(i)
  i <- i + 1
}
[1] 1
[1] 2
[1] 3
[1] 4
[1] 5

Explicação: - O loop while continua a execução enquanto contador for menor ou igual a 5. - A cada iteração, contador é incrementado em 1.

3.3. Estrutura repeat

repeat executa um bloco de código indefinidamente até que uma condição de saída seja encontrada.

Exemplo:

Code
i <- 1

repeat {
  print(i)
  i <- i + 1
  if (i > 5) {
    break
  }
}
[1] 1
[1] 2
[1] 3
[1] 4
[1] 5

Explicação: - repeat continua a execução até que break seja encontrado, o que acontece quando contador excede 5.

4. Controle de Fluxo: break e next

4.1. Função break

break é usada para interromper a execução de um loop antes de sua conclusão natural.

Exemplo:

Code
for (i in 1:10) {
  if (i == 6) {
    break
  }
  print(i)
}
[1] 1
[1] 2
[1] 3
[1] 4
[1] 5

Explicação: - O loop é interrompido quando i é igual a 6.

4.2. Função next

next pula para a próxima iteração do loop sem terminar o loop atual.

Exemplo:

Code
for (i in 1:5) {
  if (i == 3) {
    next
  }
  print(i)
}
[1] 1
[1] 2
[1] 4
[1] 5

Explicação: - Quando i é 3, o loop pula para a próxima iteração, ignorando a impressão de 3.

5. Funções: return()

return() é usada para retornar um valor de uma função e finalizar sua execução.

Exemplo:

Code
soma <- function(a, b) {
  return(a + b)
}

resultado <- soma(2, 3)
print(resultado)
[1] 5

Explicação: - A função soma retorna a soma de a e b.

6. Tratamento de Erros: try e tryCatch()

6.1. Função try

try permite continuar a execução do código mesmo que ocorra um erro.

Exemplo:

Code
resultado <- try(sqrt("abc"))
Error in sqrt("abc") : non-numeric argument to mathematical function
Code
print("Continua a execução mesmo com erro")
[1] "Continua a execução mesmo com erro"

Explicação: - try captura o erro ao tentar calcular a raiz quadrada de uma string, permitindo que o script continue.

6.2. Função tryCatch()

tryCatch() oferece mais controle sobre a manipulação de erros.

Exemplo:

Code
resultado <- tryCatch({
  sqrt("abc")
}, warning = function(w) {
  print("Aviso: um erro ocorreu.")
}, error = function(e) {
  print("Erro: não é possível calcular a raiz quadrada de uma string.")
})
[1] "Erro: não é possível calcular a raiz quadrada de uma string."
Code
print("Continua a execução após o tratamento de erro")
[1] "Continua a execução após o tratamento de erro"

Explicação: - tryCatch() permite capturar erros e avisos separadamente, fornecendo uma mensagem apropriada para cada situação.