Quiz

Problem Set 1

Study the following program and then answer the questions below. We'd like you to answer the questions by looking only at the source code, i.e., please don't copy it into a file, compile it and answer the questions based on running it. That will take all the fun out of it!

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);
}

Question 1: What is the output of this program?

A) 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) It does not output anything - there are errors in syntax.

Question 2: What would happen if we remove the initialization of "counter" prior to the do-while loop?

A) An Infinite loop - the do-while loop will output a series of 1's
B) The program's output will not change
C) The do-while loop outputs 2 and 4.
D) The do-while loop will output nothing
E) The do-while loop outputs 3 and 9.

Question 3: Given the original program at the top of this page, assume we have removed the line that initializes the counter variable before the while loop. What would happen if we also remove the counter++ line inside the while-loop, as in the following?

A) The while loop outputs nothing.
B) The while loop outputs 1 and 1; the do-while loop outputs nothing.
C) The output of the while loop is the same as when both lines are included.
D) The system will output random numbers until we turn the computer off.
E) The while loop is an Infinite loop

Question 4: Given the original program at the top of this page, what would happen if the while loop looked like this?

counter = first;
while (counter <= last) {
  cout << "\n" << counter;
  if (first % 2 == 0)
    next = counter * counter;
  cout << "  " << next;
  counter++;
}
A) The output of the while loop is the same as in the original program.
B) The while loop will not output anything
C) The output of the while loop is 1 1 and 1 4.
D) The output of the while loop is 1 2 and 2 4.
E) The output of the while loop is 1 4 and 2 4.
F) The output of the while loop is 2 4 and 2 4.

Question 5: What would happen if the first variable is greater than the last?

A) The while-loop will output something, but nothing else will.
B) The do while-loop will output something, but nothing else will.
C) There will be no output at all.
D) The program will seg fault or crash
E) The for-loop will output something, but nothing else will.

Question 6: What will the program output if we initialize the first variable to be the same as the last variable?

A) The do while-loop will output something, but nothing else will.
B) The while-loop will output something, but nothing else will.
C) Each loop will output one line.
D) The do while-loop will output 2 lines, and the other loops one line.
E) It will output nothing
F) The for-loop will output something, but nothing else will.


Problem Set 2

As in the previous problem set, here is a program for your consideration. Please answer the questions that follow by looking only at the source code.

#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;
}

Question 1: What is the output of the Boys variable on the marked lines?

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) It outputs nothing because it does not compile or run.

Question 2: Choose all that apply relating to the following lines of the program:

void F1(int males, int females);
void F2(int &m, int &f);
A) C++ rules state that we can remove these two lines as long as the methods are defined before use.
B) C++ rules state that the argument names must be the same between the declaration and definition.
C) This program will crash if we remove these two lines.
D) It's more common for the declarations to be stated in the global scope.
E) These are called forward declarations.

Question 3: If we move the following line from main() and place it in the global scope, what will happen?

int Boys = 3, Girls = 5;
A) The output would be the same.
B) Boys would = 3 and Girls would = 5 in all output
C) Boys would = 3 and Girls would = 5 only in the output from main()

Question 4: What if we changed the beginning of the program to look like this:

// We have moved moved these to global scope
const int Boys = 3;
const int Girls = 5;

void main() {
  //int Boys = 3, Girls = 5;
A) The program would compile but will crash when we try and run it.
B) There would be no changes in the output
C) The output would be Boys = 3 Girls = 5 throughout the program
D) The output would be Boys = 3 Girls = 5 only in the output from main()
E) The program will probably not compile (depending on the compiler).

Question 5: Data is passed by value in F2.

A) True.
B) False.


Problem Set 3

As in the previous problem set, here is a program for your consideration. Please answer the questions that follow by looking only at the source code. This one is more interesting than the previous two - trace the code carefully.

#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;
  }
}

Question 1: What does this program output with input of 3 for rows and 4 for columns?

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
H) It does not output anything - the logic is faulty.
I) It does not output anything - there are syntax errors.
J) It does not output anything - it's not supposed to.
K) It outputs the first 12 numbers that come to mind as you are waiting for the program to run.

Question 2: What if we added the following line to our main() function?

MAX_SIZE = 10;
A) This is not allowed in C++.
B) This is allowed; the program would run with MAX_SIZE set to 20
C) This is allowed; the program would run with MAX_SIZE set to 10.

Question 3: Consider the following four lines from the program above:

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) Is it possible to use a const in a typedef?
2) Is it possible to use a typedef in a declaration before a variable has been declared of that type?

A) 1) Yes 2) Yes
B) 1) No 2) No
C) 1) No 2) Yes
D) 1) Yes 2) No

Question 4: Can we use the following:

#define MAX_SIZE 20
instead of:
const int MAX_SIZE = 20;
A) Yes it will work and it's fine to use #define for constants in C++
B) Yes it will work but we usually do not to use #define for constants in C++
C) #define is not available in C++
D) You can't do either of these things in C

Question 5: typedef is used to create an alias for a type name.

A) True.
B) False.

Question 6: What would happen if we did not initialize the array to 0 in the Fill() function?

A) It will run but the output will be all 12's
B) It will run fine and generate the same output as if the array were initialized to 0
C) The program will not run or will crash
D) It will run but the output will be all 0's
E) It will run but may not generate any output

Question 7: Check all that apply. Why do we use const for MAX_SIZE in this program? Isn't it easier to just type "20" instead of MAX_SIZE wherever it is needed?

A) MAX_SIZE is a built-in C++ value that anyone can use. Just set it and use it.
B) Global consts should be avoided just like global variables
C) Using a const makes our program easier to understand
D) Magic numbers in a program are usually considered good practice.
E) If we want to change MAX_SIZE, we only need to change it in one place

Question 8: The switch statement in the Fill() function should have a default case, because it's considered good style to include one.

A) True.
B) False.

Question 9: Notice in the Fill() function, we declare variables in between statements. For example, cNum and cRow are declared and initialized after a for-loop has run. Will this work in C++, or do all the variables have to be declared at the top of the function?

A) It's fine to do this.
B) All the variables must be declared at the top of the function.
C) Both ways are wrong - C++ doesn't allow variables anywhere in a program.
D) All variables must be declared in the global scope.

Problem Set 4

Here are a set of files defining and testing a simple class. As usual, answer the questions that follow by referring to the source code only.

Here is the header file (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

Here is the associated .cc file (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;
}

And here is a client program for this class (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();
}

Question 1: What does this program output?

A) betsy says MOO.
betsy weighs 400, is 0 and says MOO.
B) betsy says MOO.
betsy weighs 400, is black and says MOO.
C) betsy says MOO.
betsy weighs 400, is

Question 2: We should never place the code for accessor and mutator methods in a header file. (Note an accessor is a method that returns a value, and a mutator is a method that modifies a value.)

A) True.
B) False.

Question 3: Do we need the "Cow::" before each of the function definitions in cow.cc?

A) No - since cow.h is included
B) Yes

Question 4: What role do:

#ifndef COW_H
#define COW_H
...
#endif

play in the header file?

Choose all that apply:

A) They serve no purpose because the name of the file is cow.h not COW_H.
B)  If we didn't do this, we would get a runtime error
C) If we didn't do this, we might include the file more than once
D) They do nothing because one or more of the keywords are misspelled.
E) They do nothing because the Cow class has only one header file.

Question 5: What would happen if we added the following line to cowmain.cc?

cow1.weight_ = 24;
A) The program would run, and the weight variable would be modified by this line.
B) The program would compile and run, but would crash on that line.
C) C++ does not allow this.
D) The program would compile and run, but the weight variable is not changed by this line.

Question 6: When the following line is executed, the constructor in the Cow class is called:

Cow cow1;

What are some important characteristics of constructors?

Choose all that apply

A) They usually do not return any values
B) If we do not provide a constructor in our class, the class will not compile
C) The constructor in the Cow class is atypical since it does not initialize the private variables.
D) They always have the same name as the class
E) We can have several constructors in a class as long as the arguments differ
F) A constructor is invoked when a class is instanciated.

Question 7: What are some important characteristics of a destructor?

A) A destructor is called when an object goes out of scope
B) A destructor has the same name as the class but preceded by "~"
C) There is something wrong in the destructor in cow.cc in that it doesn't do anything.
D) If we do not create a destructor for our class, the class will not compile

Question 8: Given the way the client program is using the class, consider the following:

The division of members into public and private in the Cow class is not appropriate. That is, something that is private should be public or something that is public should be private.

A) True.
B) False.

Question 9: What if we added another constructor in addition to the one that we have to cow.cc. The new constructor looks like this

Cow::Cow(string inName, double inWeight, Color inColor) {
  set_name(inName);
  set_weight(inWeight);
  set_color(inColor);
}

And we add the following lines to main():

Cow cow2("milly", 350.2, brown);
cow2.Moo();
cow2.Properties();

Can we do this?

Choose all that apply

A) The line in main() where we initialize cow2 will crash.
B) We can only have one constructor.
C) This is common in C++
D) Yes but this is not typical C++ usage
E) This will run okay, but it will not output anything because the privates are not initialized.
F) We cannot call setName(), setColor() and setWeight() from within a method of the same class.


Bonus Questions

Question 1) What is the output of the following?

#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;
}
 

Question 2) Consider the following statement, assuming an Apple class exists and has been initialized. The Apple class has a color_ instance variable:

Apple* granny_smith = new Apple; 

Choose all of the statements below which are true:

A) Apple* granny_smith = NULL; if (granny_smith == NULL)... This is NOT okay - NULL is not a value that can be checked in this manner.
B) Apple* granny_smith, fuji; This declares two pointers to Apple objects
C) The granny_smith variable contains the instance variable values associated with an Apple object
D) Apple* granny_smith = NULL; This is okay,
E) The granny_smith variable contains the address for an Apple object
F) string gs_color = *(granny_smith.get_color()); This statement returns the color of the granny_smith object, assuming it has been initialized.
G) Storage for the new Apple object is allocated in the heap
H) Storage for the new Apple object is allocated on the runtime stack
I) int* a = &b; This places the address of b into a.


Question 3) What is the output of the following program?

#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;
}


Quiz Answers

You should try to complete all of the above questions without looking at the answers. It's better to ask someone for help than to jump straight to the answer sheet for help.

You can view the answers to the above problems here.