Conjunto de problemas 1
Estude o programa a seguir e responda às perguntas abaixo. Queremos que você responda à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 dele. Isso vai acabar com 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 desse programa?
A) |
1 2 2 4 1 2 2 4 1 2 2 4 |
B) |
1 2 4 1 2 4 1 2 4 |
C) |
1 2 4 1 2 4 1 |
D) |
1 1 2 4 1 1 1 1 2 4 |
E) | Ele não gera nenhuma resposta, como há erros de sintaxe. |
Pergunta 2: o que aconteceria se a inicialização do "contador" fosse removida antes da repetição "do-while"?
A) | Uma repetição infinita: a repetição do-while vai produzir uma série de 1s |
B) | A saída do programa não vai mudar |
C) | A repetição do-while gera 2 e 4. |
D) | A repetição do-while não resultará em nada |
E) | A repetição do-while gera 3 e 9. |
Pergunta 3: considerando o programa original no topo desta página, suponha que removemos a linha que inicializa a variável de contador antes do loop "while". O que aconteceria se também removêssemos a linha contador++ dentro do "while-loop", como no exemplo a seguir?
A) | A repetição "while" não resulta em nada. |
B) | A repetição "while" gera 1 e 1, e a repetição do-while não gera nada. |
C) | A saída da repetição "while" é a mesma quando as duas linhas são incluídas. |
D) | O sistema vai gerar números aleatórios até desligar o computador. |
E) | A repetição "while" é uma repetição infinita |
Pergunta 4: considerando o programa original na parte superior 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++; }
A) | A saída da repetição "while" é a mesma do programa original. |
B) | A repetição "while" não gera resultados |
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?
A) | A repetição "while" produzirá algo, mas nada mais. |
B) | A repetição "fazer" vai gerar algo, mas nada mais vai. |
C) | Não haverá saída. |
D) | O programa vai separar por falha ou falha |
E) | A repetição for gera uma saída, mas nada mais. |
Pergunta 6: qual será a saída do programa se inicializarmos a primeira variável para que seja igual à última?
A) | A repetição "fazer" vai gerar algo, mas nada mais vai. |
B) | A repetição "while" produzirá algo, mas nada mais. |
C) | Cada loop gera uma linha. |
D) | A repetição "AND" vai produzir duas linhas e a outra vai gerar uma repetição. |
E) | Não vai gerar nada |
F) | A repetição for gera uma saída, mas nada mais. |
Conjunto de problemas 2
Como no conjunto de problemas anterior, este é um programa para sua consideração. 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 é a saída da variável Boys nas linhas marcadas?
A) |
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) | Ela não gera resultados porque não é compilado nem executado. |
Pergunta 2: escolha todas as opções que se aplicam relacionadas às seguintes linhas do programa:
void F1(int males, int females); void F2(int &m, int &f);
A) | As regras do C++ declaram que é possível remover essas duas linhas, desde que os métodos sejam definidos antes do uso. |
B) | As regras C++ declaram que os nomes dos argumentos precisam ser os mesmos na declaração e na definição. |
C) | Este programa falhará se removermos essas duas linhas. |
D) | É mais comum que as declarações sejam declaradas no escopo global. |
E) | Elas são chamadas de declarações de encaminhamento. |
Pergunta 3: se movermos a linha a seguir de main() e a colocarmos no escopo global, o que acontecerá?
int Boys = 3, Girls = 5;
A) | A saída seria 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 que fique assim:
// We have moved moved these to global scope const int Boys = 3; const int Girls = 5; void main() { //int Boys = 3, Girls = 5;
A) | O programa vai ser compilado, mas vai falhar quando for executado. |
B) | Não haveria mudanças na saída |
C) | A saída seria Meninos = 3 Meninas = 5 durante todo o programa |
D) | A saída seria Boys = 3 Girls = 5 apenas na saída de main() |
E) | O programa provavelmente não vai ser compilado (dependendo do compilador). |
Pergunta 5: os dados são transmitidos por valor em F2.
A) | Verdadeiro |
B) | Falso |
Conjunto de problemas 3
Como no conjunto de problemas anterior, este é um programa para sua consideração. Responda às perguntas a seguir observando apenas o código-fonte.Este é mais interessante do que os dois anteriores. Acompanhe o código com cuidado.
#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: o que esse programa gera com entradas 3 para linhas e 4 para colunas?
A) |
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 10 12 |
E) |
1 2 3 4 10 11 12 5 9 8 7 6 |
G) |
9 8 7 6 10 11 12 5 1 2 3 4 |
A) | Ele não gera nenhuma resposta. A lógica está com defeito. |
I) | Ele não gera nenhuma resposta, há erros de sintaxe. |
J) | Ela não gera nenhuma resposta, como deveria. |
K) | A saída são os 12 primeiros números que vêm à mente enquanto você espera a execução do programa. |
Pergunta 2: e se adicionássemos a linha a seguir à função main()?
MAX_SIZE = 10;
A) | Isso não é permitido em C++. |
B) | Isso é permitido; o programa seria executado com MAX_SIZE definido para 20 |
C) | Isso é permitido. O programa será executado com MAX_SIZE definido como 10. |
Pergunta 3: considere as quatro linhas a seguir 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 uma constante em um typedef?
2) É possível usar um typedef em uma declaração antes de uma variável ser declarada desse tipo?
A) | 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 20em vez de:
const int MAX_SIZE = 20;
A) | Sim, isso vai funcionar, e não há problema em usar #define para constantes em C++ |
B) | Sim, vai funcionar, mas geralmente 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.
A) | Verdadeiro |
B) | Falso |
Pergunta 6: o que aconteceria se a matriz não fosse inicializada como 0 na função Fill()?
A) | Ela será executada, mas a saída será todas as |
B) | Ele funcionará bem e gerará a mesma saída como se a matriz fosse inicializada como 0. |
C) | O programa não vai ser executado ou vai falhar |
D) | Ela será executada, mas a saída será totalmente 0 |
E) | Ela será executada, mas talvez não gere nenhuma saída |
Pergunta 7: marque todas as opções que se aplicam. Por que usamos const para MAX_SIZE neste programa? Não é mais fácil digitar "20" em vez de MAX_SIZE onde for necessário?
A) | MAX_SIZE é um valor C++ integrado que qualquer pessoa pode usar. Basta configurar e usar. |
B) | As constantes globais devem ser evitadas, assim como as variáveis globais |
C) | Usar uma constante torna nosso programa mais fácil de entender |
D) | Os números mágicos em um programa geralmente são considerados boas práticas. |
E) | Se quisermos mudar MAX_SIZE, precisaremos alterá-lo em um só lugar. |
Pergunta 8: a instrução switch na função Fill() precisa ter um caso padrão, porque é considerado um bom estilo incluir um.
A) | 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 precisarão ser declaradas na parte de cima da função?
A) | Não há problema em fazer isso. |
B) | Todas as variáveis precisam ser declaradas no topo da função. |
C) | Ambas as formas estão erradas. O C++ não permite variáveis em nenhum lugar do programa. |
D) | Todas as variáveis precisam ser declaradas no escopo global. |
Conjunto de problemas 4
Veja um conjunto de arquivos que definem e testam uma classe simples. Como de costume, responda às perguntas seguintes consultando apenas o código-fonte.
Este é o arquivo principal (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_; }; #endif
Este é 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 veja um programa cliente para esta 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?
A) | 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 dos métodos acessador e mutador em um arquivo principal. Observe que um acessador é um método que retorna um valor e um mutador é um método que modifica um valor.
A) | Verdadeiro |
B) | Falso |
Pergunta 3: precisamos de "Cow::" antes de cada uma das definições de função em cow.cc?
A) | Não, já que cow.h está incluído |
B) | Sim |
Pergunta 4: Qual função:
#ifndef COW_H #define COW_H ... #endif
são reproduzidos no arquivo de cabeçalho?
Marque todas as opções válidas:
A) | Eles não têm utilidade porque o nome do arquivo é cow.h, não COW_H. |
B) | Se isso não fosse feito, receberíamos um erro durante a execução. |
C) | Se não fizermos isso, podemos incluir o arquivo mais de uma vez |
D) | Eles não fazem nada porque uma ou mais das palavras-chave estão com a grafia incorreta. |
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 ao cowmain.cc?
cow1.weight_ = 24;
A) | O programa seria executado, e a variável de peso seria modificada por essa linha. |
B) | O programa seria compilado e executado, mas falharia nessa linha. |
C) | O C++ não permite isso. |
D) | O programa será compilado e executado, mas a variável de peso não será alterada por essa 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.
A) | Eles geralmente não retornam nenhum valor |
B) | Se não fornecermos um construtor na classe, ela não vai compilar |
C) | O construtor na classe Cow é atípico, já que 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 sejam diferentes |
F) | Um construtor é invocado quando uma classe é instanciada. |
Pergunta 7: quais são algumas características importantes de um destrutor?
A) | 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 no destrutor em cow.cc, porque ele não faz nada. |
D) | Se não criarmos um destrutor para a classe, ela não será compilada |
Pergunta 8: considerando a maneira como o programa cliente está usando a classe, considere o seguinte:
A divisão de membros em público e privado na classe Cow não é apropriada. Ou seja, algo que é privado deve ser público, ou algo público deve ser privado.
A) | Verdadeiro |
B) | Falso |
Pergunta 9: e se adicionarmos outro construtor além daquele que temos em cow.cc? O novo construtor vai ficar assim
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.
A) | A linha em main() em que inicializamos cow2 falhará. |
B) | Só podemos ter um construtor. |
C) | Isso é comum em C++ |
D) | Sim, mas esse não é o uso típico de C++ |
E) | Isso funcionará sem problemas, mas não terá saída porque os particulares não são inicializados. |
F) | Não é possível chamar setName(), setColor() e setWeight() de dentro de um método da mesma classe. |
Perguntas bônus
Pergunta 1) Qual é a saída do seguinte?
#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 afirmaçã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:
A) | Maçã* granny_smith = NULL; if (granny_smith == NULL)... NÃO é um problema, porque NULL não é um valor que pode ser verificado dessa maneira. |
B) | Apple* granny_smith, fuji; declara dois ponteiros para objetos Apple |
C) | A variável granny_smith contém os valores da 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. |
G) | O armazenamento do novo objeto da Apple é alocado no heap |
A) | O armazenamento do novo objeto da Apple é alocado na pilha de ambiente de execução. |
I) | int* a = &b; 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
Você deve responder a todas as perguntas acima sem ver 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.