CSCI 160: Fall Final Exam with Sample Solutions
Sections F16N01-F16N04 (Dr. Wessels)

Question Mark
0. Write a program
[8 marks]
 
1. Nested loops
[8 marks]
 
2. Scope and parameters
[8 marks]
 
3. Writing functions
[8 marks]
 
4. Recursion
[8 marks]
 
5. Arrays and searching
[8 marks]
 
6. Command line args
[8 marks]
 
7. File I/O
[8 marks]
 
8. Structs
[8 marks]
 
9. Dynamic allocation
[8 marks]
 
10. Pointers, structs, and linked lists
[8 marks]
 
Exam Total

[80 marks]

 

Question 0: Write a program [8]

Write a complete and correct C++ program that meets the following specifications:


Sample solution
#include <cstdio>

int main()
{
   const float target = 100;
   printf("Please enter two numbers\n");
   float m, n;
   if (scanf("%g", &m) && scanf("%g", &n)) {
      float diffm = m - target;
      if (diffm < 0) {
         diffm = -diffm;
      }
      float diffn = n - target;
      if (diffn < 0) { 
         diffn = -diffn;
      }
      float answer = m;
      if (diffn < diffm) {
         answer = n;
      }
      printf("Of your two numbers, %g and %g, ", m, n);
      printf("%g is closer to %g\n", answer, target);
   } else {
      printf("Incorrect data entered\n");
   }
}

Question 1: Nested loops [8]

Write the printFactors function following the algorithm below, using ints for all variables. (Assume cmath has been included.)

void printFactors(int n)
// for each integer x from 1 to n (inclusive)
//    limit = sqrt x
//    for each integer f from 1 to limit (inclusive)
//       if f evenly divides x then:
//          d = x / f
//          print a message saying f and d are factors of x

Sample solution
void printFactors(int n)
{
   for (int x = 1; x <= n; x++) {
       int limit = sqrt(x);
       for (int f = 1; f <= limit; f++) {
           if ((x % f) == 0) {
              int d = x / f;
              printf("%d and %d are factors of %d\n", f, d, x);
           }
       }
   }
}

Question 2: Scope and parameters [8]

The program below is a valid (though unusual) C++ program that uses a variety of different variable scopes. Study the program carefully, and show the precise output produced by the program.

#include <cstdio>

const int X = 1;
const int Y = 2;

void swap(int &X, int Y);
int f(int &X);

int main()
{
   int X = 3;
   swap(X, Y);
   printf("main(%d,%d)\n", X, Y);
   int Y = f(Y) * X;
}

void swap(int &X, int Y)
{
   int tmp = Y;
   X = Y;
   X = tmp;
   printf("swap(%d,%d)\n", X, Y);
}

int f(int &X)
{
   X = 4;
   int Y = 1;
   printf("f1(%d,%d)\n", X, Y);
   do {
      int X = Y*6;
      printf("f2(%d,%d)\n", X, Y);
      X--;
      Y++;
   } while (Y < X);
   return X;
}

Sample solution
swap(2,2)
main(2,2)
f1(4,1)
f2(6,1)
f2(12,2)
f2(18,3)

Question 3: Writing functions [8]

Write the two functions prototyped below.

// returns the negated square of x
// e.g. negSquare(3) returns -9
double negSquare(double x);

// alters the first n array values,
// multiplying each by s
void scale(float a[], int n, float s);

Sample solution
double negSquare(double x)
{
   return (- (x * x));
}

void scale(float a[], int n, float s)
{
   for (int i = 0; i < n; i++) {
       a[i] *= s;
   }
}

Question 4: Recursion [8]

Show the six lines of output produced by the following (valid) program:

#include <cstdio>

void mix(char arr[], int left, int right);
void swap(char &x, char &y);

int main()
{
   char arr[6] = "abcde";
   mix(arr, 1, 3);
}

void mix(char arr[], int left, int right)
{
   if (left > right) {
      return;
   } else if (left == right) {
      printf("%s\n", arr);
   } else {
      mix(arr, left+1, right);
      for (int pos = left+1; pos <= right; pos++) {
          if (arr[left] != arr[pos]) {
             swap(arr[left], arr[pos]);
             mix(arr, left+1, right);
             swap(arr[left], arr[pos]);
          }
      }
   }
}

void swap(char &x, char &y)
{
   char tmp = x;
   x = y;
   y = tmp;
}

Sample solution
abcde
abdce
acbde
acdbe
adcbe
adbce

Question 5: Arrays and searching [8]

Write a C++ function that meets the specifications below:


Sample solution
int together(int arr[], int n, int size)
{
   for (int pos = 0; pos < (size-1); pos++) {
       if ((arr[pos] == n) && (arr[pos+1] == n)) {
          return pos;
       }
   }
   return -1;
}

Question 6: Command line arguments [8]

Part 1: Write a function that meets the following specifications:

Part 2:Write a main routine that:


Sample solution
void embed(char str1[], char str2[], char result[])
{
   strcpy(result, str1);
   strcat(result, str2);
   strcat(result, str1);
}

int main(int argc, char *argv[])
{
   if (argc != 3) {
      printf("Correct usage is:  %s str1 str2\n", argv[0]);
      return 0;
   }
   const int StrSize = 256;
   char result[StrSize];
   embed(argv[1], argv[2], result);
   printf("combining %s and %s gives %s\n", argv[1], argv[2], result);
}

Question 7: File I/O [8]

Write a function that has a bool return type and takes three parameters: two character arrays (file1, file2), and an integer value (n).

The function copies the first n characters of file1 into file2, with appropriate error checking.

The function returns true if both files opened successfully and all n characters were copied successfully and false otherwise.


Sample solution
bool copyn(char file1[], char file2[], int n)
{
   FILE *fpin;
   FILE *fpout;
   fpin = fopen(file1, "r");
   if (!fpin) {
      printf("Unable to open file %s for reading\n", file1);
      return false;
   }
   fpout = fopen(file2, "w");
   if (!fpout) {
      printf("Unable to open file %s for writing\n", file2);
      fclose(fpin);
      return false;
   }
   int count = 0;
   while ((count < n) && (!feof(fpin))) {
       char curr = fgetc(fpin);
       if (!feof(fpin)) {
          fprintf(fpout, "%c", curr);
          count++;
       }
   }
   fclose(fpin);
   fclose(fpout);
   if (count == n) {
      return true;
   } else {
      printf("Only able to copy %d of %d characters\n", count, n);
      return false;
   }
}

Question 8: Structs [8]

Given the struct definition and the two function prototypes below, complete the implementation of the functions.

// the maximum number of values in a data set
const int MaxVals = 500;

// a data set is a collection of up to 500 values,
// numVals records how many are actually stored at the moment
struct DataSet {
   double values[MaxVals];
   int numVals;
};

// calculate and return the average of the values in data set d
//    (i.e. the sum of the values / the number of values)
double average(DataSet d);

// calculate and return the average of all the data sets in array S
//    (the sum of the data set averages / the number of data sets)
double overallAverage(DataSet S[], int numSets);

Sample solution
double average(DataSet d)
{
    double sum = 0;
    for (int i = 0; i < d.numVals; i++) {
        sum += d.values[i];
    }
    return (sum / d.numVals);
}

double overallAverage(DataSet S[], int numSets)
{
   double grandTotal = 0;
   for (int i = 0; i < numSets; i++) {
       grandTotal += average(S[i]);
   }
   return (grandTotal/numSets);
}

Question 9: Dynamic allocation [8]

Suppose that someone else has written a function processarray with the following specifcations:

// the function does something with the contents of the array of floats
void processarray(float arr[], int size);
Your task is to write a main routine that: (DO NOT WRITE ANYTHING OTHER THAN THE MAIN ROUTINE)
Sample solution
int main()
{
   float *fptr;
   int n;
   printf("How many values would you like to enter?\n");
   if (scanf("%d", &n)) {
      fptr = new float[n];
      if (!fptr) {
         printf("Unable to allocate enough space for %d floats\n", n);
      } else {
         processarray(fptr, n);
         delete [] fptr;
      }
   } else {
     printf("That was not a number\n");
   }
}

Question 10: Pointers, structs, and linked lists [8]

Part I: Given the struct definition and the function prototype below, complete the implementation of the function.

// stores a time as three integer values, hour (1-12), minutes (0-59), seconds (0-59)
struct time {
   int hour, minute, second;
};

// displays a time in the format hh:mm:ss
// e.g. 12:05:15
void display(time *tptr);

Part II: Given the struct definition and function prototype below, complete the implementation of the function. Be sure to include all appropriate null-pointer checking.

// Fraction represents an individual fraction (numerator/denominator)
//    that can be held as one element of a doubly-linked list
struct Fraction {
   long numerator, denominator;  // the Fraction data fields
   Fraction *next; // pointer to the next Fraction in the list (i.e. closer to the back)
   Fraction *prev; // pointer to the next Fraction in the list (i.e. closer to the front)
};

// given pointers to the front and back of the list, and a pointer to the
//    fraction, f, to be inserted,
// inserts the supplied fraction supplied fraction at the back of the list,
//    returning true if successful, false otherwise
bool insertF(Fraction* &front, Fraction* &back, Fraction* f);

Sample solution
void display(time *tptr)
{
   printf("%02d:%02d:%02d\n", tptr->hour, tptr->minute, tptr->second);
}

bool insert(Fraction* &front, Fraction* &back, Fraction* f)
{
   if (!f) {
      return false;
   }
   if (front == NULL) {
      front = f;
      back = f;
      return true;
   }
   back->next = f;
   f->prev = back;
   back = f;
   return true;
}



  CSCI 160 Exam Quick Reference Sheet: Sections F16N01-F16N04

Comments:    Single line //
          or Multi-line  /* ....
                            .... */

C++ operators
=============
Arithmetic operators:     +   -   *   /   %   ++  --
Assignment operators:  =  +=  -=  *=  /=  %=
Boolean operators:     &&  ||  !  ==  !=  <=  >=  <  >

Data Types
=======================================================
Data        Keywords             Literal Examples    Special values
integers:   short, int, long     3, -200, 0          INT_MAX, INT_MIN  (climits library)
reals:      float, double        3.14, -0.0003       FLT_MAX, FLT_MIN  (cfloat  library)
character:  char                 'x'                 \'  \"  \\  \t \n  \0
boolean:    bool                 true, false

Sample variable declarations (with/without initialization)
==========================================================
int    i;       int    i = 3;
char   c;       char c = 'Q';   char c = '\n';
bool   b;       bool b = true;
long arr[5];    long arr[5] = { 0, 0, 0, 0, 0 };   // array assignment only valid
char str[10];   char str[] = "some text";          //    at point of declaration

Sample constant declarations
============================
const double Pi = 3.1415;
const char[] ErrMsg = "Error: something terrible happened!\n";

Sample enumerated type definitions
==================================
enum Weekdays { Sun, Mon, Tue, Wed, Thu, Fri, Sat };
enum Commands { Quit = 'Q', Continue = 'C', Print = 'P' };

Sample input with scanf, fgets, and getc (cstdio library)
=========================================================
// scanf returns a count of the number of variables "filled"
scanf("%c", &x);  // read a character into char variable x
scanf("%d", &i);  // read an integer into int variable i
scanf("%ld", &n);  // read an integer into long variable n
scanf("%g", &f);  // read a real number into float variable f
scanf("%s", &a);  // read text into variable a (char[])
scanf("%*s");     // read and discard the next word of input
scanf("%[abc]", &x); // read an a, b, or c into variable x
scanf("%*[ \t\n]%c", &x); // skip tabs, spaces, and newlines and read next char into x
scanf("%4d", &i); // read a maxium of 4 digits into int variable i
fgets(arr, 100, stdin); // read the rest of the line (up to 100 chars max) into the char array
x = getc(stdin);  // read a single character into char variable x
ungetc(c, stdin); // take char c and push it into the input buffer

Sample output with printf (cstdio library)
==========================================
// printf returns a count of the number of characters printed
printf("%c", x);  // print the contents of  char variable c
printf("%d", i);  // print the contents of int variable i
printf("%ld", n);  // print the contents of long variable n
printf("%g", f);  // print the contents of float variable f
  // (%f gives fixed point, %e gives exponential notation, %g can do either)
printf("%5.2g, f); // print the contents of f with width 5, 2 decimal places
printf("%s", a);  // print the contents of character array a

Some useful library functions and constants
===========================================
cctype                 cfloat                   cmath
------                 ------                   -----
bool isalpha(char)     FLT_MIN, FLT_MAX         double ceil(double)
bool isalnum(char)     DBL_MIN, DBL_MAX         double floor(double)
bool isdigit(char)                              double fabs(double)
bool islower(char)     climits                  double log(double)
bool isupper(char)     -------                  double pow(double, double)
bool ispunct(char)     CHAR_MIN, CHAR_MAX       double cos(double)
bool isspace(char)     SHORT_MIN, SHORT_MAX     // also acos, sin, asin, tan, atan
char tolower(char)     INT_MIN, INT_MAX         double sqrt(double)
char toupper(char)     LONG_MIN, LONG_MAX

cstring                            cstdlib
-------                            -------
char* strcat(char*, char*)         int abs(int)
char* strncat(char*, char*, int)   int atoi(char*)
char* strcpy(char*, char*)         float atof(char*)
char* strncpy(char*, char*, int)   void srand(time(NULL)) // needs ctime lib
int   strcmp(char*, char*)         int rand(int)
int   strncmp(char*, char*, int)
int   strlen(char*)




Sample control structures
=========================
if (expr) {                  // works on short, int, long,      for (x = 1; x < 9; x++) {
   .......                   //    char, or enum values             ....
} else if (expr) {           switch (expr) {                    }
   ........                     case value1:
} else {                            .....                       while (x < 9) {
   ........                         break;                          ....
}                               case value2:                        x++;
                                    .....                       }
// is X between 3 and 9?            break;
if ((3 < X) && (X < 9)) {       default:                        do {
   // yes it is                     .....                           ....
} else {                            break;                          x++;
   // no it isn't            };                                 } while (x < 9);
}
         Sample function prototypes and implementations         Sample calls
         ==============================================         ============
void swap(int &a, int &b);      float calc(int x, float f)      int main()
......                          .....                           {
void swap(int &a, int &b)       float calc(int x, float f)         int i = 1;
{                               {                                  int j = 2;
    int temp = a;                  float result = x * f;           swap(i, j);
    a = b;                         return result;                  float f = calc(i, 2.5);
    b = temp;                   }                                  int array[20];
}                                                                  initArray(array, 20);
                                                                }
void initArray(int arr[], int size)
{
   for (int i = 0; i < size; i++
       arr[i] = 0;
}

Pointer examples
================
int i;       // an integer variable i
int *iPtr;   // iPtr can point at integers in memory
iPtr = &i;   // iPtr now points at variable i (& takes the address of i)
(*iPtr) = 3; // store 3 whereever iPtr points in memory

Sample function prototype with a pointer passed by reference
============================================================
void doSomething(int* &ptr);

Dynamic memory allocation and deallocation
==========================================
using new/delete            using malloc/free
----------------            -----------------
int *i = new int;           int *i = (int*)malloc(sizeof(int);        // alloc new int
delete i;                   free i;                                   // free the int
float *f = new float[10];   float *f = (float*)malloc(sizeof(float)); // alloc new arr of floats
delete [] f;                free f;                                   // free the array
// remember to test for NULL after any call to new or malloc

Sample struct definition and use
===================================
struct Info {                         Info i;
   char initials[2];                  i.id = 0;
   int id;                            i.value = -34.216;
   float value;                       i.initials[0] = 'D';
};

The C++ string class (using the  library)
====================
std::string str; // declare a string variable str
str = "blah blah blah"; // assign text to a string
printf("%s", str.c_str()); // print the string contents
str[3] = 'x'; // change the fourth character in the string to x