Conjunto de problemas 1
Estude o programa a seguir e responda às perguntas abaixo. Gostaríamos que você respondesse às perguntas analisando apenas o código-fonte, ou seja, não o copie em um arquivo, compile-o e responda às perguntas com base na execução. Isso vai tirar toda a diversão!
int main() {
int counter, first, last, next;
first = 1; last = 2;
for (counter = first; counter <= last; counter++) {
cout << "\n " << counter;
next = counter * counter;
cout << " " << next;
}
counter = first;
while (counter <= last) {
cout << "\n " << counter;
next = counter * counter;
cout << " " << next;
counter++;
}
counter = first;
do {
cout << "\n " << counter;
next = counter * counter;
cout << " " << next;
counter++;
} while (counter < last);
}
Pergunta 1: qual é o resultado do programa?
| R) |
1 2 2 4 1 2 2 4 1 2 2:4 |
| B) |
1 1 2 4 1 1 2 4 1 1 2 4 |
| C) |
1 1 2 4 1 1 2 4 1 1 |
| D) |
1 1 2 4 1 1 1 1 2 4 |
| E) | Não gera resultados. Há erros de sintaxe. |
Pergunta 2: o que aconteceria se removêssemos a inicialização do "counter" antes da repetição do-while?
| R) | Um loop infinito: o loop do-while gera uma série de |
| B) | O resultado do programa não vai mudar |
| C) | A repetição do-while gera 2 e 4. |
| D) | A repetição do-while não gera resultados |
| E) | As saídas do loop do-while são 3 e 9. |
Pergunta 3: Dado o programa original no topo desta página, suponha que temos removeu a linha que inicializa a variável de contador antes da repetição while. O quê? aconteceria se também removêssemos a linha do contador ++ dentro da repetição, como em o seguinte?
| R) | A repetição "while" não gera nada. |
| B) | A repetição "while" resulta em 1 e 1. a repetição do-while não gera resultados. |
| C) | A saída do loop "while" é a mesma de quando ambas as linhas são incluída. |
| D) | O sistema vai gerar números aleatórios até ligarmos o computador |
| E) | A repetição "while" é infinita |
Pergunta 4: Dado o programa original no topo desta página, o que aconteceria se a repetição "while" fosse assim?
counter = first;
while (counter <= last) {
cout << "\n" << counter;
if (first % 2 == 0)
next = counter * counter;
cout << " " << next;
counter++;
}| R) | A saída da repetição "while" é a mesma do programa original. |
| B) | A repetição "while" não gera nada |
| C) | A saída da repetição "while" é 1 1 e 1 4. |
| D) | A saída da repetição "while" é 1 2 e 2 4. |
| E) | A saída da repetição "while" é 1 4 e 2 4. |
| F) | A saída da repetição "while" é 2 4 e 2 4. |
Pergunta 5: o que aconteceria se a primeira variável fosse maior que a última?
| R) | A repetição "while" vai gerar algo, mas nada mais vai gerar. |
| B) | A repetição do código ao vivo gera uma saída, mas nada mais gera. |
| C) | Não haverá saída. |
| D) | O programa vai encontrar falhas ou falhas |
| E) | A repetição "for" gera uma saída, mas nada mais gera. |
Pergunta 6: qual será a saída do programa se inicializarmos a primeira variável igual à última variável?
| R) | A repetição do código ao vivo gera uma saída, mas nada mais gera. |
| B) | A repetição "while" vai gerar algo, mas nada mais vai gerar. |
| C) | Cada loop vai gerar uma linha. |
| D) | A repetição do código do processo gera 2 linhas, e o da repetição do processo gera uma linha. |
| E) | Não vai gerar uma saída |
| F) | A repetição "for" gera uma saída, mas nada mais gera. |
Conjunto de problemas 2
Como no conjunto de problemas anterior, aqui está um programa para você considerar. Responda às perguntas a seguir observando apenas o código-fonte.
#include <iostream>
using namespace std;
int main() {
int Boys = 3, Girls = 5;
void F1(int males, int females);
void F2(int &m, int &f);
F1(Boys, Girls);
cout << "\nAfter calling F1, within main()";
cout << "\n\tBoys = " << Boys; // #2
cout << "\n\tGirls = " << Girls;
F2(Boys, Girls);
cout << "\nAfter calling F2, within main()";
cout << "\n\tBoys = " << Boys; // #4
cout << "\n\tGirls = " << Girls;
}
void F1(int b, int g) {
b += 3, g += 4;
cout << "\nF1";
cout << "\n\tBoys = " << b; // #1
cout << "\n\tGirls = " << g;
}
void F2(int &b, int &g) {
b = b + 8, g = g + 5;
cout << "\nF2";
cout << "\n\tBoys = " << b; // #3
cout << "\n\tGirls = " << g;
}Pergunta 1: qual é o resultado da variável Boys nas linhas marcadas?
| R) |
1: 6 2: 3 3: 11 4: 11 |
| B) |
1: 6 2: 3 3: 11 4: 3 |
| C) |
1: 6 2: 6 3: 11 4: 11 |
| D) | Ele não gera resultados porque não é compilado nem executado. |
Pergunta 2: escolha todas as opções que se aplicam com relação às seguintes linhas do programa:
void F1(int males, int females); void F2(int &m, int &f);
| R) | As regras do C++ afirmam que é possível remover essas duas linhas, desde que os métodos são definidos antes do uso. |
| B) | As regras do C++ declaram que os nomes dos argumentos precisam ser os mesmos entre declaração e definição. |
| C) | Este programa falhará se removermos essas duas linhas. |
| D) | É mais comum que as declarações sejam feitas no formato do projeto. |
| E) | Essas são as declarações encaminhadas. |
Pergunta 3: se movermos a linha a seguir de main() e colocá-la na escopo, o que vai acontecer?
int Boys = 3, Girls = 5;
| R) | A saída será a mesma. |
| B) | Meninos = 3 e Meninas = 5 em toda a saída |
| C) | Meninos = 3 e Meninas = 5 apenas na saída de main() |
Pergunta 4: e se mudássemos o início do programa para ficar assim:
// We have moved moved these to global scope
const int Boys = 3;
const int Girls = 5;
void main() {
//int Boys = 3, Girls = 5;| R) | O programa seria compilado, mas falhava quando tentávamos executá-lo. |
| B) | Não haveria mudanças na saída |
| C) | O resultado seria Boys = 3 Girls = 5 ao longo do programa |
| D) | O resultado seria Boys = 3 Girls = 5 apenas na saída de main() |
| E) | O programa provavelmente não será compilado (dependendo do compilador). |
Pergunta 5: os dados são transmitidos por valor em F2.
| R) | Verdadeiro |
| B) | Falso |
Conjunto de problemas 3
Como no conjunto de problemas anterior, aqui está um programa para você considerar. Não se esqueça responder às perguntas a seguir observando apenas o código-fonte.Este é mais interessantes que os dois anteriores, rastreie o código cuidadosamente.
#include <iostream>
using namespace std;
const int MAX_SIZE = 20;
typedef int ARR2D[MAX_SIZE][MAX_SIZE];
void Print(ARR2D in_array, int rows, int cols);
void Fill(ARR2D in_array, int rows, int cols);
int main() {
ARR2D matrix;
int row, col;
do {
cout << "Please enter the size of the matrix to generate (rows and cols) :" << endl;
cin >> row >> col;
} while (row <= 0 || row > MAX_SIZE || col <= 0 || col > MAX_SIZE);
Fill(matrix, row, col);
Print(matrix, row, col);
return(0);
}
void Print(ARR2D in_array, int rows, int cols) {
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++)
cout << '\t' << in_array[i][j];
cout << endl;
}
}
void Fill(ARR2D in_array, int rows, int cols) {
for(int i = 0; i < rows; i++)
for (int j = 0; j < cols; j++)
in_array[i][j] = 0;
const int limit = rows * cols;
int cNum = 1;
int cRow = 0;
int cCol = 0;
int cDir = 0; // 0-north, 1-east, 2-south, 3-west
while(true) {
// Place the number.
in_array[cRow][cCol] = cNum;
cNum++;
if (cNum > limit) break;
int fRow = cRow;
int fCol = cCol;
while (true) {
fRow = cRow;
fCol = cCol;
switch(cDir) {
case 0: fRow--; break;
case 1: fCol++; break;
case 2: fRow++; break;
case 3: fCol--; break;
}
if ( fRow >= 0 && fRow < rows && fCol >= 0 && fCol < cols && in_array[fRow][fCol] == 0)
break;
cDir = (cDir + 1) % 4;
}
cRow = fRow;
cCol = fCol;
}
}Pergunta 1: qual é a saída do programa com a entrada 3 para linhas e 4 para colunas?
| R) |
1 2 3 4 5 6 7 8 9 10 11 12 |
| B) |
1 2 3 4 5 6 7 8 9 10 11 12 |
| C) |
12 11 10 9 8 7 6 5 4 3 2 1 |
| D) |
1 3 2 4 8 6 7 5 9:11 1012 |
| E) |
1 2 3 4 10 11 12 5 9 8 7 6 |
| P) |
9 8 7 6 10 11 12 5 1 2 3 4 |
| A) | Ele não emite nada. A lógica está defeituosa. |
| I) | Não emite nada, há erros de sintaxe. |
| J) | Isso não acontece porque não deveria. |
| K) | Ela gera os 12 primeiros números que vêm à sua mente enquanto você espera a execução do programa. |
Pergunta 2: e se adicionarmos a linha a seguir à função main()?
MAX_SIZE = 10;
| R) | Isso não é permitido em C++. |
| B) | Isto é permitido; o programa seria executado com MAX_SIZE definido como 20 |
| C) | Isto é permitido; o programa seria executado com MAX_SIZE definido como 10. |
Pergunta 3: considere as quatro linhas do programa acima:
const int MAX_SIZE = 20; typedef int ARR2D [MAX_SIZE][MAX_SIZE]; void Print (ARR2D A, int rows, int cols); void Fill (ARR2D A, int rows, int cols);
1) É possível usar um const em um typedef?
2) É possível usar um typedef em uma declaração antes que uma variável seja declarada desse tipo?
| R) | 1) Sim 2) Sim |
| B) | 1) Não 2) Não |
| C) | 1) Não 2) Sim |
| D) | 1) Sim 2) Não |
Pergunta 4: podemos usar o seguinte:
#define MAX_SIZE 20
const int MAX_SIZE = 20;
| R) | Sim, funcionará e não há problema em usar #define para constantes no C++ |
| B) | Sim, funciona, mas normalmente não usamos #define para constantes em C++ |
| C) | #define não está disponível em C++ |
| D) | Não é possível fazer nenhuma dessas coisas em C |
Pergunta 5: typedef é usado para criar um alias para um nome de tipo.
| R) | Verdadeiro |
| B) | Falso |
Pergunta 6: o que aconteceria se não inicializássemos a matriz como 0 no Função Fill()?
| R) | Ele será executado, mas a saída será todas as 12 |
| B) | Ele vai funcionar bem e gerar a mesma saída como se a matriz fosse inicializado como 0 |
| C) | O programa não será executado ou falhará |
| D) | Ele será executado, mas a saída será todos 0s |
| E) | Ele será executado, mas talvez não gere nenhuma saída |
Pergunta 7: Selecione todas as opções aplicáveis. Por que usamos const para MAX_SIZE neste programa? Não é mais fácil digitar apenas "20" em vez de MAX_SIZE onde quer que esteja necessário?
| R) | MAX_SIZE é um valor C++ integrado que qualquer pessoa pode usar. Pronto e usá-los. |
| B) | Evite as constantes globais, assim como as variáveis globais |
| C) | O uso de um constante torna nosso programa mais fácil de entender |
| D) | Números mágicos em um programa geralmente são considerados uma boa prática. |
| E) | Se quisermos alterar MAX_SIZE, precisamos alterá-lo de uma só vez lugar |
Pergunta 8: a instrução switch na função Fill() deve ter um valor nesse caso, porque é considerado bom estilo incluir um.
| R) | Verdadeiro |
| B) | Falso |
Pergunta 9: Observe que, na função Fill(), declaramos variáveis entre instruções. Por exemplo, cNum e cRow são declarados e inicializados após a execução de um loop for. Isso funcionará em C++ ou todas as variáveis precisam ser declaradas no topo do a função?
| R) | Não há problema em fazer isso. |
| B) | Todas as variáveis precisam ser declaradas no topo da função. |
| C) | As duas maneiras estão erradas: o C++ não permite variáveis em nenhum lugar da neste programa. |
| D) | Todas as variáveis precisam ser declaradas no escopo global. |
Conjunto de problemas 4
Este é um conjunto de arquivos que definem e testam uma classe simples. Como sempre, responda às perguntas a seguir mencionando apenas o código-fonte.
Este é o arquivo de cabeçalho (cow.h):
#ifndef COW_H
#define COW_H
using namespace std;
typedef enum Color {black, brown, beige, blackandwhite, nocolor};
class Cow {
public:
Cow();
~Cow();
// accessors
double weight() { return weight_; };
string name() { return name_; };
Color color() { return color_; };
// mutators
void set_name(string inName) { name_ = inName; };
void set_color(Color inColor) { color_ = inColor; };
void set_weight(double inWeight) {weight_ = inWeight; };
void Moo();
void Properties();
private:
Color color_;
double weight_;
string name_;
};
#endifEste é o arquivo .cc associado (cow.cc):
#include <iostream>
#include "cow.h"
using namespace std;
Cow::Cow() {}
Cow::~Cow() {}
void Cow::Moo() {
cout << name() << " says MOO." << endl;
}
void Cow::Properties() {
cout << name() << " weighs " << weight() << ", is "
<< color() << " and says MOO." << endl;
}E este é um programa cliente para essa classe (cowmain.cc):
#include <iostream>
#include "cow.h"
using namespace std;
int main() {
Cow cow1;
cow1.set_name("betsy");
cow1.set_weight(400.0);
cow1.set_color(black);
cow1.Moo();
cow1.Properties();
}Pergunta 1: o que esse programa gera?
| R) | Betsy diz MOO. betsy pesa 400, é 0 e diz MOO. |
| B) | Betsy diz MOO. betsy pesa 400, é preta e diz MOO. |
| C) | Betsy diz MOO. betsy pesa 400, é |
Pergunta 2: nunca devemos colocar o código em métodos de acesso e mutador em um arquivo de cabeçalho. (Observe que um acessador é um método que retorna um valor, e um mutador é um método que modifica um valor.)
| R) | Verdadeiro |
| B) | Falso |
Pergunta 3: precisamos que o "Cow::" antes de cada uma das definições de função em cow.cc?
| R) | Não, já que cow.h está incluído |
| B) | Sim |
Pergunta 4: qual é o papel:
#ifndef COW_H #define COW_H ... #endif
reproduzir no arquivo principal?
Marque todas as opções válidas:
| R) | Eles não servem para nenhuma finalidade porque o nome do arquivo é cow.h. e não COW_H. |
| B) | Se não fizéssemos isso, obteríamos um erro de tempo de execução |
| C) | Se não fizermos isso, poderemos incluir o arquivo mais de uma vez |
| D) | Eles não fazem nada porque uma ou mais palavras-chave contêm erros ortográficos. |
| E) | Eles não fazem nada porque a classe Cow tem apenas um arquivo de cabeçalho. |
Pergunta 5: o que aconteceria se adicionássemos a linha a seguir a cowmain.cc?
cow1.weight_ = 24;
| R) | O programa seria executado, e a variável de peso seria modificada por esta linha. |
| B) | O programa era compilado e executado, mas falhava nessa linha. |
| C) | O C++ não permite isso. |
| D) | O programa seria compilado e executado, mas a variável de peso não é alterado por esta linha. |
Pergunta 6: quando a linha a seguir é executada, o construtor na classe Cow é chamado:
Cow cow1;
Quais são algumas características importantes dos construtores?
Escolha todas as opções válidas.
| R) | Elas geralmente não retornam valores |
| B) | Se não fornecermos um construtor em nossa classe, ela não compilar |
| C) | O construtor na classe Cow é atípico, porque não inicializa as variáveis privadas. |
| D) | Eles sempre têm o mesmo nome da classe |
| E) | Podemos ter vários construtores em uma classe, desde que os argumentos diferem |
| F) | Um construtor é invocado quando uma classe é instanciada. |
Pergunta 7: Quais são algumas características importantes de um destruidor?
| R) | Um destrutor é chamado quando um objeto sai do escopo. |
| B) | Um destrutor tem o mesmo nome da classe, mas precedido por "~" |
| C) | Há algo errado com o destructor em cow.cc em que não faz nada. |
| D) | Se não criarmos um destrutor para a classe, ela não compilar |
Pergunta 8: considerando a forma como o programa cliente está usando a classe, considere o seguinte:
A divisão de membros em público e privado na classe Vaca não é apropriada. Ou seja, algo privado deve ser público ou algo que é público deve ser privado.
| R) | Verdadeiro |
| B) | Falso |
Pergunta 9: e se adicionarmos outro construtor além daquele que "cow.cc". O novo construtor tem a seguinte aparência:
Cow::Cow(string inName, double inWeight, Color inColor) {
set_name(inName);
set_weight(inWeight);
set_color(inColor);
}E adicionamos as seguintes linhas a main():
Cow cow2("milly", 350.2, brown);
cow2.Moo();
cow2.Properties();Podemos fazer isso?
Escolha todas as opções válidas.
| R) | A linha em main() em que inicializamos cow2 vai falhar. |
| B) | Só podemos ter um construtor. |
| C) | Isso é comum em C++ |
| D) | Sim, mas esse não é um uso comum do C++ |
| E) | Isso funcionará normalmente, mas não gerará nada porque o privates não são inicializados. |
| F) | Não podemos chamar setName(), setColor() e setWeight() de dentro um método da mesma classe. |
Perguntas bônus
Pergunta 1) Qual é o resultado?
#include <iostream>
using namespace std;
void HelpMe(int *p, int *num, int *q);
void WhereAmI(int *p, int *q, int a);
void HelpMe(int *p, int *num, int *q) {
int a;
a = 2;
q = &a;
*p = *q + *num;
num = p;
}
void WhereAmI(int *p, int *q, int a) {
a = 6;
*p = a + *p;
*q = a + 3;
HelpMe(q, &a, p);
}
int main() {
int *p;
int q;
int *num;
int a;
a = 3;
q = 5;
p = &a;
num = &q;
HelpMe(&a, p, num);
WhereAmI(&q, p, *num);
cout << "*p = " << *p << " q = " << q << " *num = " << *num << endl;
}
Pergunta 2) Considere a seguinte instrução, supondo que uma classe Apple existe e foi inicializada. A classe Apple tem uma variável de instância color_:
Apple* granny_smith = new Apple;
Escolha todas as afirmações verdadeiras abaixo:
| R) | Apple* granny_smith = NULL; if (granny_smith == NULL)... Isto não é aceitável - NULL não é um valor que pode ser verificado dessa maneira. |
| B) | Maçã* granny_smith, fuji; Declara dois ponteiros para objetos da Apple. |
| C) | A variável "granny_smith" contém os valores de variável de instância associados a um objeto da Apple. |
| D) | Apple* granny_smith = NULL; Tudo bem, |
| E) | A variável "granny_smith" contém o endereço de um objeto da Apple. |
| F) | string gs_color = *(granny_smith.get_color()); Essa instrução retorna a cor do objeto granny_smith, supondo que ele tenha sido inicializado. |
| P) | O armazenamento do novo objeto da Apple é alocado na heap. |
| A) | O armazenamento do novo objeto da Apple é alocado na pilha do ambiente de execução. |
| I) | int* a = &b; Isso coloca o endereço de b em a. |
Pergunta 3) Qual é o resultado do programa a seguir?
#include <iostream>
using namespace std;
const int kNumVeggies = 4;
void Grill(int squash, int *mushroom);
int Saute(int onions[], int celery);
void Grill(int squash, int *mushroom) {
*mushroom = squash/4;
cout << *mushroom + squash << endl;
}
int Saute(int onions[], int celery) {
celery *= 2;
onions[celery]++;
Grill(onions[0], &onions[3]);
cout << celery << " " << onions[3] << endl;
return celery;
}
int main() {
int broccoli, peppers[kNumVeggies], *zucchini;
for (broccoli = 0; broccoli < kNumVeggies; broccoli++)
peppers[broccoli] = kNumVeggies - broccoli;
zucchini = &peppers[Saute(peppers,1)];
Grill(*zucchini, zucchini);
zucchini--;
cout << peppers[3] + *zucchini + *(zucchini + 1) << endl;
}
Respostas do teste
Responda a todas as perguntas acima sem ler as respostas. É melhor pedir ajuda a alguém do que ir direto para a folha de respostas.
Veja as respostas para os problemas acima aqui.