Search buenodc

Nesta página
  1. Questionário
  2. Tarefa
  3. Gabarito

Lista de Exercícios - Etapa 8

Questionário

  • Questionário individual, de múltipla escolha, com uma resposta correta por questão.
  • Cobre a leitura do material e dos vídeos: passagem por valor, passagem por referência, e escopo de variáveis.
  • Prazo: [definir].

1. Numa função com parâmetro por valor, o que acontece com o argumento original quando a função altera o valor do parâmetro dentro do corpo?

a) O argumento original também é alterado, porque parâmetro e argumento são a mesma variável. b) O argumento original permanece inalterado, porque o parâmetro é uma cópia local, criada na chamada. c) O argumento original é apagado da memória. d) Depende do tipo de dado do parâmetro.

2. Qual símbolo, na definição de uma função, indica que um parâmetro é passado por referência?

a) &, logo depois do tipo do parâmetro, no cabeçalho da função. b) *, logo antes do nome do parâmetro. c) %, logo depois do nome da função. d) #, no início da linha do parâmetro.

3. Qual é a saída do trecho abaixo?

void trocar(int &a, int &b) {
    int temp = a;
    a = b;
    b = temp;
}

int main() {
    int x = 4, y = 9;
    trocar(x, y);
    cout << x << " " << y << endl;
    return 0;
}

a) 4 9 b) 0 0 c) 9 4 d) Erro de compilação

4. Se os parâmetros de trocar fossem declarados por valor, em vez de por referência (void trocar(int a, int b)), o que aconteceria quando ela fosse chamada com trocar(x, y)?

a) x e y seriam trocados normalmente, porque C++ troca por padrão. b) O programa não compilaria. c) x e y virariam zero. d) A troca ocorreria apenas dentro da função, sem afetar x e y no main.

5. Sobre misturar parâmetros por valor e por referência numa mesma função, é correto afirmar que:

a) Não é permitido em C++: todos os parâmetros de uma função devem usar o mesmo mecanismo. b) Cada parâmetro decide individualmente se é por valor ou por referência. c) Só o primeiro parâmetro pode ser por referência. d) Misturar os dois sempre causa erro de compilação.

6. Qual das situações abaixo é um bom motivo para usar passagem por referência num parâmetro?

a) A função precisa alterar, de verdade, a variável original de quem chamou ela. b) A função só precisa ler o valor do argumento, sem alterá-lo. c) O parâmetro é do tipo int. d) A função não tem valor de retorno.

7. O que é o escopo de uma variável?

a) O tipo de dado que ela armazena. b) O valor inicial atribuído a ela. c) A região do programa onde ela existe e pode ser usada. d) O nome que ela recebe na declaração.

8. Uma variável declarada dentro do corpo de uma função tem escopo:

a) Global. b) Estática. c) Indefinida. d) Local.

9. Considere uma função com uma variável local, que não é parâmetro, incrementada dentro do corpo. Se essa função for chamada três vezes seguidas, o que acontece com essa variável a cada chamada?

a) Ela mantém o valor da chamada anterior, sempre acumulando. b) Ela é criada do zero a cada chamada, sem nenhuma ligação com a anterior. c) Ela vira global automaticamente depois da segunda chamada. d) O programa não compila.

10. Por que, em geral, é recomendável evitar variáveis globais?

a) Porque qualquer função pode alterá-las sem aviso, dificultando rastrear onde um valor mudou. b) Porque C++ não permite mais de uma variável global por programa. c) Porque variáveis globais ocupam mais memória que variáveis locais. d) Porque variáveis globais só podem guardar números inteiros.

Tarefa

  • Cada exercício é um programa separado, em um arquivo .cpp com o nome exato indicado (letras minúsculas, sem espaço). O nome errado atrapalha a correção automática.
  • Todos os exercícios pedem uma função com a assinatura exata indicada, chamada a partir do main. Escreva a função sempre antes do main, como vimos nos vídeos.
  • Formato estilo juiz online: a entrada é só os valores pedidos, sem mensagem de prompt (nada de cout << "Digite..." antes do cin). A saída é só o valor esperado, sem nenhum texto de rótulo junto.
  • Entrada: os valores são lidos na ordem exata indicada em cada exercício, um cin por valor.
  • Compile e rode cada programa antes de entregar, testando com os valores de exemplo.
  • Entrega: envie todos os arquivos .cpp juntos aqui no Moodle. Prazo: [definir].

Tarefa 1 - Ordenando dois números

Arquivo: tarefa1.cpp

Escreva uma função void ordenar(int &a, int &b), por referência, que troca os valores de a e b se a for maior que b, deixando sempre o menor valor em a. No main, leia dois inteiros e mostre os dois, já ordenados, em ordem crescente.

Entrada: dois inteiros.

Saída (dois valores, em ordem crescente):

<menor>
<maior>

Exemplo: entrada

8
3

produz saída

3
8

Tarefa 2 - Dobrando por referência

Arquivo: tarefa2.cpp

Escreva uma função void dobrar(int &numero), por referência, que dobra o valor da variável recebida. No main, leia um inteiro, chame a função, e mostre o valor da variável depois da chamada.

Entrada: um inteiro.

Saída (um único valor):

<numero dobrado>

Exemplo: entrada

6

produz saída

12

Tarefa 3 - Aplicando desconto na própria variável

Arquivo: tarefa3.cpp

Escreva uma função void aplicarDesconto(double &preco, double percentual), em que preco é por referência e percentual é por valor. A função deve alterar preco diretamente, subtraindo o desconto. No main, leia o preço e o percentual, chame a função, e mostre o preço depois da chamada.

Entrada: dois números reais, preco e percentual.

Saída (um único valor):

<preco com desconto>

Exemplo: entrada

100
10

produz saída

90

Tarefa 4 - Contagem que recomeça

Arquivo: tarefa4.cpp

Escreva uma função void contarAte(int limite) que usa uma variável local para contar de 1 até limite, mostrando cada número numa linha. No main, leia dois inteiros e chame a função uma vez para cada um, mostrando que a contagem recomeça do 1 em cada chamada.

Entrada: dois inteiros, limite1 e limite2.

Saída (a contagem da primeira chamada, seguida da contagem da segunda):

<1 até limite1, um por linha>
<1 até limite2, um por linha>

Exemplo: entrada

3
2

produz saída

1
2
3
1
2

Tarefa 5 - Somando com variável global

Arquivo: tarefa5.cpp

Declare uma variável global int totalProcessado, inicializada com 0, fora de qualquer função. Escreva uma função void processarValor(int valor) que soma valor em totalProcessado. No main, leia três inteiros e chame processarValor uma vez para cada um. Ao final, mostre o valor de totalProcessado.

Entrada: três inteiros.

Saída (um único valor):

<soma total>

Exemplo: entrada

10
20
5

produz saída

35

Desafio (opcional) - Ordenando três valores

Arquivo: desafio.cpp

Escreva uma função void ordenarTres(double &a, double &b, double &c), com os três parâmetros por referência, que reordena os valores recebidos de forma que, ao final da função, a <= b <= c. Use apenas comparações e trocas, sem bibliotecas de ordenação prontas. No main, leia três números reais e chame a função, mostrando os três já ordenados.

Entrada: três números reais.

Saída (três valores, em ordem crescente):

<menor>
<meio>
<maior>

Exemplo: entrada

5
1
3

produz saída

1
3
5

Gabarito

Resolução de referência para consulta e correção.

Questionário

Resposta correta de cada questão, para conferência ou importação no Moodle.

QuestãoResposta
1b
2a
3c
4d
5b
6a
7c
8d
9b
10a

1. O parâmetro passado por valor é uma cópia local, criada no momento da chamada: alterá-la não afeta o argumento original.

2. O & aparece logo depois do tipo do parâmetro, no cabeçalho da função, transformando o parâmetro num apelido pra variável original.

3. Como a e b são referências, a troca dentro de trocar afeta diretamente x e y: depois da chamada, x vale 9 e y vale 4.

4. Com parâmetros por valor, a e b seriam cópias de x e y: a troca aconteceria só dentro da função, sem nenhum efeito nas variáveis do main.

5. Cada parâmetro é independente: uma função pode ter, ao mesmo tempo, parâmetros por valor e por referência, cada um decidindo o próprio mecanismo.

6. Passagem por referência só faz sentido quando a função precisa alterar, de fato, a variável original de quem chamou ela.

7. Escopo é justamente a região do programa em que uma variável existe e pode ser referenciada.

8. Toda variável declarada dentro do corpo de uma função, incluindo os parâmetros, tem escopo local.

9. Uma variável local é recriada a cada chamada da função: ela não guarda o valor de chamadas anteriores.

10. O risco de variáveis globais é justamente esse: qualquer função pode alterá-las livremente, o que dificulta rastrear a origem de um valor inesperado.

Tarefa

Soluções de referência, com o mesmo raciocínio esperado do aluno.

Tarefa 1:

#include <iostream>
using namespace std;

void ordenar(int &a, int &b) {
    if (a > b) {
        int temp = a;
        a = b;
        b = temp;
    }
}

int main() {
    int a, b;
    cin >> a >> b;
    ordenar(a, b);
    cout << a << endl;
    cout << b << endl;
    return 0;
}

Tarefa 2:

#include <iostream>
using namespace std;

void dobrar(int &numero) {
    numero = numero * 2;
}

int main() {
    int numero;
    cin >> numero;
    dobrar(numero);
    cout << numero << endl;
    return 0;
}

Tarefa 3:

#include <iostream>
using namespace std;

void aplicarDesconto(double &preco, double percentual) {
    preco = preco - (preco * percentual / 100);
}

int main() {
    double preco, percentual;
    cin >> preco >> percentual;
    aplicarDesconto(preco, percentual);
    cout << preco << endl;
    return 0;
}

Tarefa 4:

#include <iostream>
using namespace std;

void contarAte(int limite) {
    for (int i = 1; i <= limite; i++) {
        cout << i << endl;
    }
}

int main() {
    int limite1, limite2;
    cin >> limite1 >> limite2;
    contarAte(limite1);
    contarAte(limite2);
    return 0;
}

Tarefa 5:

#include <iostream>
using namespace std;

int totalProcessado = 0;

void processarValor(int valor) {
    totalProcessado = totalProcessado + valor;
}

int main() {
    int v1, v2, v3;
    cin >> v1 >> v2 >> v3;
    processarValor(v1);
    processarValor(v2);
    processarValor(v3);
    cout << totalProcessado << endl;
    return 0;
}

Desafio:

#include <iostream>
using namespace std;

void ordenarTres(double &a, double &b, double &c) {
    double temp;
    if (a > b) {
        temp = a;
        a = b;
        b = temp;
    }
    if (b > c) {
        temp = b;
        b = c;
        c = temp;
    }
    if (a > b) {
        temp = a;
        a = b;
        b = temp;
    }
}

int main() {
    double a, b, c;
    cin >> a >> b >> c;
    ordenarTres(a, b, c);
    cout << a << endl;
    cout << b << endl;
    cout << c << endl;
    return 0;
}