The objective of this laboratory assignment is to introduce you to the notion of
"problem decomposition" using functions. We will focus on defining new functions,
calling functions, using return values, and debugging functions.
In addition, automated unit testing with assert() will be covered.
This assignment has the following steps:
- Generating random numbers
The rand function generates a random integer between 0 and RAND_MAX (a symbolic constant
defined in the <stdlib.h> header file). The minimum value of RAND_MAX must be at least 32767.
If we want a to generate random numbers to simulate the throw of a dice, then all we need is
numbers between 1 - 6. To achieve this the mod % operator is used:
1 + rand % 6 will return
a random number from 1 to 6.
The rand function is actually a pseudo-random number generator. Calling rand
repeatedly produces a sequence of numbers that appears to be random. However, the sequence
repeats itself each time the program is executed. The following example illustrates this.
The given program is a simulation of a very basic online Roulette spinning wheel.
It is based on a single number bet. The returns usually are 35 to 1. Cut and paste
this program into a cpp file and execute more than once. Follow the sequence
of values closely.
//-------------------------------------------------------
// Roulette.cpp
// Program to demonstrate rand() and srand() functions.
// Author Suchit Batheja
// Fall 2003
//-------------------------------------------------------
#include < iostream >
#include < cstdlib >
#include < ctime >
using namespace std;
int main()
{
int Number;
double Bet;
int Roule = 0;
// Repeat until user quits
char Ch = 'y';
while ((Ch == 'Y') || (Ch == 'y'))
{
// Get number
Number = -1;
while ((Number < 0) || (number > 36))
{
cout << "enter number to bet on (between 0 - 36) " << endl;
cin >> Number;
}
// Get bet
Bet = 0.0;
while (Bet <= 0.0)
{
cout << "enter bet amount" << endl;
cin >> Bet;
}
// Spinning the wheel
Roule = rand() % 37;
// After Spinning
cout << "lucky number is " << roule << endl;
if (number == roule)
cout << "congratulations!! you have won " << (35 * bet) << endl;
else
cout << "oops you lost. better luck next time :-(" << endl;
cout << endl << "play again y/n" << endl;
cin >> Ch;
}
return 0;
}
If you noticed, the random number sequence generated over different executions
are the same. This is useful if you wish to run the same experiments again, but
not good for a game of chance. To overcome this problem a function called
srand(unsigned int) can be used to change the starting point of the sequence.
If the seed remains the same over multiple executions then the sequence
generated is again pseudo random. If the seed is made based on the system time, it
will be different every time we run the program and we will get a different
random sequence every time. Insert this line of code in your program:
srand(time(NULL)); The seed is now set to the current time.
Now see how lucky you get.
Program output
- Writing automated unit tests with assert()
Another useful function (actually its a macro) in the C++ standard
library is assert(). assert()
is
defined in the standard include file cassert
.
assert()
takes one parameter which is a boolean
expression. If the expression evaluates to true, then nothing happens
when the assert()
is executed. If the expression evaluates
to false, then the program halts at that point and prints a message indicating
the line and the expression of the failing assert()
.
assert()
statements can be added to your programs to test your code.
For instance, the following program uses assert()
to verify that the
sum()
function works correctly.
//-------------------------------------------------------
// sum.cpp
// Program to demonstrate assert() macro.
// Author David Janzen
// Fall 2005
//-------------------------------------------------------
#include <iostream>
#include <cassert>
using namespace std;
int sum(int min, int max);
int main()
{
assert(sum(3,7)==25);
assert(sum(-2,3)==3);
assert(sum(-5,5)==0);
cout << "No errors encountered" << endl;
}
// This function sums the integers
// from min to max inclusive.
// Pre: min < max
// Post: return-value = min + (min+1) + ...
// + (max-1) + max
int sum(int min, int max)
{
int sum = 0;
for(int i=min;i<=max;i++)
{
sum += i;
}
return sum;
}
Add three more assert statements to test the sum()
function.
For instance, pass in two negative numbers or make both parameters the
same number.
Your main function
- User defined functions
The following functions can be used to calculate the volumes of three different
solids. Show how you should call each of these functions in the main function to
perform the specified tasks. Make sure the data types on parameters and return values
match the function definitions.
//-------------------------------------------------------
// Author: John Gauch
// Date: Fall 2003 //tests added by David Janzen Fall 2005
//-------------------------------------------------------
#include <iostream>
#include <cassert>
using namespace std;
// Function prototypes
float cubeVolume( float sideLength );
double sphereVolume( float sidelength );
int cylinderVolume( float radius, int height );
// Calculate the volume of a cube
float cubeVolume( float sideLength )
{
return ( sideLength * sideLength * sideLength );
}
// Calculate the colume of a sphere
double sphereVolume( float radius )
{
return ( (4.0 / 3.0) * 3.14159 * radius * radius * radius );
}
// Calculate the volume of a cylinder
int cylinderVolume( float radius, int height )
{
return (int) ( 3.14159 * radius * radius * height );
}
// Main function to test volume functions
int main( int argc, char * argv[] )
{
// Use assert() to write a test to compute the volume of a cube whose sides are 4 long
// Use assert() to use a sphere radius and output volume
// Use assert() to calculate the volume of a Pepsi can (or Coke if you prefer)
cout << "No errors encountered" << endl;
return 0;
}
Your main function
- Write a short function
N Factorial is equal to the product of all integers from 1 to N.
Specifically, factorial(N) = N x (N-1) x (N-2) x ... x 2 x 1. Write an
iterative function that performs the N Factorial calculation.
The function should take an int as a parameter and return an int as the
result of the function.
Write a short program that uses assert()
to test
your factorial function. Place all your assert()
statements in a run_tests()
function like this:
void run_tests();
int main()
{
run_tests();
}
void run_tests()
{
{ //test 1
assert( /* fill this in */ );
} //test 1
{ //test 2
assert( /* fill this in */ );
} //test 2
}
Tests like these are called unit tests
because you are testing one unit (a function) of your program.
Writing tests after you have written some code is called
test-last programming. An alternative is to do test-first
programming where you write a test first, then write a function to make
the test pass, then repeat to write another test. Notice that
test-last programming primarily uses tests to verify that the code
works correctly, while test-first programming forces you to make design
decisions such as the function name, the function parameters, the function
return type, and the function's expected behavior when you are writing
the test. We will apply a test-first approach in lab next week.
Now that you have tested your factorial function, extend your program
so that it prompts the user for a value of the N to
calculate factorial. The program should output the result of the
calculation, then prompt the user again. It should prompt the user
until the user enters a value of zero. Then the program should exit.
Leave the tests in the program. You can comment out the call to
run_tests()
if you don't want them run.
Here is a sample of what your output might look like:
> Enter value of N: 3
Factorial(N) = 6
> Enter value of N: 5
Factorial(N) = 120
> Enter value of N: 0
End of program.
Your factorial program
- Run the program
Test the program you created by calculating two or three typical
values and copy the output of the program below. See if you can
"break" the program by changing what you input. Tests like these
are called integration tests because you are putting everything
together, or if the user is running them they are called acceptance tests
because you are seeing if the whole program functionality is acceptable.
Cut and paste your results below.
Your program output
- Debugging a program
The following program uses functions to generate the multiplication table of the
number passed to the function. It was developed without any unit tests.
Identify the errors present in the program and correct them.
Add comments to the program to explain what each function does.
//-------------------------------------------------------
// Author: Abhishek Shivadas
// Date: Fall 2003
//-------------------------------------------------------
#include <iostream>
using namespace std;
void multiply_by_two(int number);
int multiply_by_three(int number);
int main()
{
float number_two;
char number_three;
int number_four;
cout << "Enter the Number to multiply by two:" << endl;
cin >> number_two;
cout << "Enter the Number to multiply by three:" << endl;
cin >> number_three;
cout << "Enter the Number to multiply by four:" << endl;
cin >> number_four;
}
void multiply_by_two(float number)
{
int i;
for(i = number; i <= 9; i++)
cout << i << "times 2 is" << number * 2;
return i;
}
int multiply_by_three(int number)
{
int i;
for(i == number; i <= 9; i++)
{
number = number * 3;
cout << i << "times 3 is" << number * 3;
return number;
}
}
int multiply_by_four(int number)
{
int i;
boolean finished_calculating = true;
for(i = number; i <= 9; i++)
cout << i << "times 4 is" << number * 4;
return finished_calculating;
}
Create a C++ program called Number_Functions.cpp, and use "cut" and
"paste" to copy the text above into the same. What errors do you get when
you try to compile the program? Before you start correcting these errors,
edit the file to add comments describing the purpose of the program, the
author, and date at the top of Number_Functions.cpp. Now, start entering
your corrections to make the compile errors go away. As a general rule,
it is best to start with the first error message and recompile until that
error is corrected.
For each correction, make a comment near the code you
corrected indicating what you did. This way, you can remember what you did.
When you work on joint programming projects everyone can keep track of
changes to the code by reading everyone's comments. Ponder over the
warnings which appear while compiling the code and if possible try to
correct the warnings as well. The output of the above program should be
like this:
"Number" times "2 or 3 or 4" is "Answer"
.
.
.
.
.
9 times "2 or 3 or 4" is "Answer"
Corrected code
Output here
- Submit Your Work
This lab assignment will be submitted electronically to the TAs once you
fill in the fields below and click on the "submit" button. You do NOT need to
print a copy of this document to hand in.
If you are ready to send the lab to the grader, click on
the submit button. Otherwise, go back and fill in any
missing pieces and then submit your work.