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
.cppcom 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 domain, como vimos nos vídeos. - Formato estilo juiz online: a entrada é só os valores pedidos, sem mensagem de prompt (nada de
cout << "Digite..."antes docin). 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
cinpor valor. - Compile e rode cada programa antes de entregar, testando com os valores de exemplo.
- Entrega: envie todos os arquivos
.cppjuntos 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ão | Resposta |
|---|---|
| 1 | b |
| 2 | a |
| 3 | c |
| 4 | d |
| 5 | b |
| 6 | a |
| 7 | c |
| 8 | d |
| 9 | b |
| 10 | a |
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;
}