There are three complete case studies here. The
first two case studies assume that students have been
introduced to the fundamental instructions read in, write out,
assign a value, loop (for, while), select (if, if-else)
but are not yet familiar with programmer-defined subroutines.
Case Study #1: Find youngest person's age from a list of ages. (Interactive;
No subroutines)
Case Study #2: Find youngest person's age and its frequency from a
list of ages. (Uses files; No subroutines)
Case Study #3: Use Newton's Method to find square roots of numbers.
(Interactive; Uses subroutines)
CASE STUDY #1
PROBLEM.
Write an interactive program which, given the number of ages in a list
and given the list of ages (integers),
finds the lowest (smallest!) age in the list.
CLARIFICATION.
No data editing needs to be done for this program. That is, assume that
the user will enter the numbers
within the ranges specified below. It will not matter if the list contains
duplicate ages.
Input:
This program finds the smallest age from a list of ages which
you
will enter at the keyboard. The ages must be in the range
0 to 125, inclusive.
Number of ages > 2
Age > 12
Age > 9
Smallest age = 9
Sample Session #2:
<Same opening message for each run!>
Number of ages > 3
Age > 68
Age > 68
Age > 68
Smallest age = 68
Sample Session #3:
Number of ages > 9
Age > 18
Age > 49
Age > 65
Age > 17
Age > 22
Age > 17
Age > 81
Age > 17
Age > 17
Smallest age = 17
DATA:
Output Variables: smallestAge integer smallest age from among those read in
Other Variables: counter integer loop counter
ALGORITHM (shown in the form of a structure chart):
(Greet user)
Write out message to user telling what program does
(Initialize)
smallestAge <-- 125
(Find out how many ages to be entered)
write out "Number of ages ? "
read in numOfAges
(Find age statistics)
Loop for counter going from 1 to numOfAges:
(Examine to see if stats need to be updated)
If (currentAge < smallestAge)
smallestAge currentAge
The C++ program :
//--------------------------------------------------------------------------------------------
// Program: Smallest
// Programmed by: Funky Winkerbean, 6/97.
//
// This program reads in a list of ages from the keyboard and then
// displays the smallest age in the list.
//---------------------------------------------------------------------------------------------
#include <iostream.h>
void main()
{
//Greet user
cout << "\nThis program finds the smallest age from a list of
ages\n"
<< "which you will enter
at the keyboard. The ages\n"
<< "must be in the range
0 to 125, inclusive.\n\n";
//Initialize (Alternatively, you may initialize in the declaration statement.)
smallestAge = 125;
//Find out how many ages to be entered
cout << "Number of ages? ";
cin >> numOfAges;
//Find age statistics
for (int counter=1; counter <= numOfAges; counter++)
{
// Get next age
cout << "\nAge? ";
cin >> currentAge;
// Examine to see if stats need to be
updated
if (currentAge < smallestAge)
// this age smaller than smallest age so far
smallestAge = currentAge;
}
//Display statistics
cout << "\n\n"
<< "The smallest age is
"
<< smallestAge;
CASE STUDY #2: This is a modification of the program in
Case Study #1. The two main differences are :
i) this program is not interactive; and
ii) this program also finds the frequency of the smallest age.
PROBLEM.
Write a program which, given a text file containing the number of ages
in a list and the list of ages (integers),
finds the lowest (smallest!) age and its frequency and writes that
information to another file.
CLARIFICATION.
No data editing needs to be done for this program. That is, assume
that the input file contains data which is
within the ranges specified below.
Input (from a file named "ages.dat"):
Sample Output #1: (to "results.dat")
There are 2 ages.
Ages:
12
9
Smallest age = 9
Frequency = 1
Sample Input #2: (from "ages.dat")
3
68
68
68
Sample Output #2: (to "results.dat")
There are 3 ages.
Ages:
68
68
68
Smallest age = 68
Frequency = 3
Sample Input #3: (from "ages.dat")
9
18
49
65
17
22
17
81
17
17
Sample Output #3: (to "results.dat")
There are 9 ages.
Ages:
18
49
65
17
22
17
81
17
17
Smallest age = 17
Frequency = 4
Output Variables: smallestAge integer
smallest age from among those read in
frequency integer
how often smallest age was entered
Other Variables: inFile
text file contains
input
outFile
text file contains
output
counter integer
loop counter
THE ALGORITHM in PSEUDOCODE REPRESENTATION with comments in parentheses:
(Initialize)
smallestAge <-- 125
frequency <-- 0
(Open data files)
Open inFile for reading from
Open outFile for writing to
(Find out how many ages to be entered)
read in numOfAges from inFile
write out numOfAges to outFile
(Find age statistics)
Loop for counter going from 1 to numOfAges:
(Examine to see if stats need to be updated)
If (currentAge < smallestAge)
smallestAge <-- currentAge
frequency <-- 1
Else
If (currentAge = smallestAge)
frequency
<-- frequency + 1
(Close files)
close inFile
close outFile
//---------------------------------------------------------------------------------------------------
// Program: Smallest (file processing version)
// Programmed by Funky Winkerbean, 6/97.
// This program reads in a list of ages (integers) from a file and
then writes the smallest
// integer in the list along with its frequency to another file.
//---------------------------------------------------------------------------------------------------
#include <fstream.h>
#include <iomanip.h>
void main()
{
// Initialize
smallestAge = 125; // The value 125 could have been
defined as a constant!
frequency = 0;
// Open data files
inFile.open("ages.dat", ios::in);
outFile.open("results.dat", ios::out);
// Find out how many ages to be entered
inFile >> numOfAges;
outFile << "\nThere are "
<<
numOfAges
<<
" ages\n\n";
outFile << "Ages:\n";
//Find age statistics
for (int counter=1; counter <= numOfAges; counter++)
{
// Examine to see if stats need to be updated
if (currentAge < smallestAge) // this age smaller
than
{
// smallest age so far
smallestAge = currentAge;
frequency = 1;
}
else
if (currentAge == smallestAge)
// another instance of smallestAge
frequency
= frequency + 1;
//Display statistics
outFile << "\n\nSmallest age = "
<<
smallestAge
<<
"\nFrequency = "
<<
frequency;
// Close files
inFile.close();
outFile.close();
CASE STUDY #3: This case study contains a sample design
and resulting program which requires functions
and procedures.
PROBLEM.
Write an interactive program which uses Newton's Method to calculate
the square root of a number and
then displays it next to the square root of the same number found using
the C++ function "sqrt". The program
will continue giving the user the option to find more square roots
until the user chooses to terminate the program.
BACKGROUND.
There are many methods for actually calculating the square root of
a number. If you had no square root
function available to you, you'd have to write an algorithm for finding
the square root, but the Babylonians
(ca. 1800-1600 BC) beat you to it! Although the method was attributed
to Sir Isaac Newton (hence its
name), it was fully described on clay tablets more than three millennia
before Newton was even a gleam
in his mother's eye.
CLARIFICATION.
Newton's Method to find the square root of a positive real number (which
we'll call num) is described here:
For this program let epsilon be a constant equal to 1.0E-09 (or 1 x 10-9).
INPUT SPECIFICATIONS:
1. The number (for which the square root is to be found) will be a
positive real.
2. The user's guess will be a positive real.
3. When given a choice to continue, the user must be required to enter
a valid response ('Y', 'y', 'N', or 'n).
OUTPUT SPECIFICATIONS:
1. Display an opening message (of your choice) to the user, telling
(in brief) what the program does.
2. Prompt the user for all input--namely, the number, the initial guess,
and the answer regarding whether or not
to continue.
3. For each iteration, list the iteration number, the old guess, and
the new guess.
4. After the desired precision has been reached, print out the approximated
square root calculated using
Newton's Method and the square roots calculated
using the C++ sqrt function. Write all floating point output
showing 12 decimal places.
5. Appropriately label all output, as shown in the sample session below,
including column headings for data
in (3).
When the user decides to terminate the program, display a final message
such as the one shown in the sample
session below.
SAMPLE SESSION (with output in bold):
Welcome to Newton's Method for Square Roots program.
This program allows you to find the square root of a positive real
number by entering
a guess for the square root and then applying Newton's Method for
calculating the
square root based on your guess.
Number > 56.03
Guess > 7.5
Iteration # Old Guess
New Guess
-----------------------------------------------------------------
1
7.5
7.48533333333
2
7.48533333333 7.48531896449
3
7.48531896449 7.48531896448
Newton's Method: 7.48531896448
C++ sqrt function: 7.48531896448
Do you wish to continue? y/n > y
<< screen clears >>
Number > 2
Guess > 1.4
Iteration # Old Guess
New Guess
-----------------------------------------------------------------
1
1.4
1.41428571429
2
1.41428571429 1.41421356421
3
1.41421356421 1.41421356237
4
1.41421356237 1.41421356237
Newton's Method: 1.41421356237
C++ sqrt function: 1.41421356237
Do you wish to continue? y/n > n
<< screen clears >>
Thanks for using Newton's Method!
Part One: The MAIN Program.
The Main Algorithm:
THE MAIN ALGORITHM in PseudoCode:
Call WelcomeUser
Loop while UserWantsToContinue:
In place of PreCondition and PostConditions, for the first program design in which subroutines are used, the students may simply describe the "Task" instead. Later, once "programming by contract" has been discussed, students can be required to define pre- and post-conditions.
Procedure : WelcomeUser
PreCondition: none
PostCondition: Message telling what program does has been displayed
to screen.
Parameters: (none)
Local variables:(none)
Algorithm:
Write out a welcome to user and tell briefly what program does.
Algorithm:
Procedure : PrintHeadings
PreCondition: none
PostCondition: Column headings for output have been displayed at screen.
Parameters: (none)
Local variables: (none)
Algorithm:
Constants: EPSILON real 1.0 * 10-9
Local Variables:
Algorithm:
count <-- 0
Loop while MoreAccuracyNeeded(newGuess, oldGuess, EPSILON):
Note:
If EPSILON had been declared as a global constant there would have
been no need to
pass it as a parameter here.
Procedure: PrintSquareRoot
PreCond: number is original number whose
square root is to be found;
newtonRoot is square root of number from using Newton's Method.
PostCond: Square roots from Newton's Method and the
Borland C++ square
root function have been displayed.
Parameters:
Algorithm:
Algorithm:
return continue
Algorithm:
//-------------------------------------------------------------------
// Newtons.cpp
//
// Programmed by Funky Winkerbean, 6/97.
//
// This is an interactive program which finds the square root of a
// number using Newton's Method.
//-------------------------------------------------------------------
// libraries
//---------------------------
#include <iostream.h>
#include <conio.h>
#include <math.h>
#include <iomanip.h>
#include <ctype.h>
// prototypes
//------------------------------
void WelcomeUser();
void GetValues (double&, double&);
void PrintHeadings();
void CalculateSquareRoot (double, double&);
void PrintSquareRoot(double, double);
bool MoreAccuracyNeeded (double, double, double);
bool UserWantsToContinue();
void ShowIteration (int, double, double);
// the main program
//--------------------------------------------------------------
void main (void)
{
WelcomeUser();
// Apply Newton's Method
do
{
GetValues (number, newGuess);
PrintHeadings();
CalculateSquareRoot(number, newGuess);
PrintSquareRoot(number, newGuess);
} while (UserWantsToContinue());
// Subroutines
//--------------------------------------------------------------
// WelcomeUser
// PreCond: none
// PostCond: Message telling what program does has been displayed to
screen.
//-------------------------------------------------------------------------------------
void WelcomeUser()
{
// GetValues
// PreCond: none
// PostCond: User has entered number and initial guess.
//------------------------------------------------------------------------------
void GetValues (double& number,
double& guess)
{
// PrintHeadings
// PreCond: none
// PostCond: Column headings for output have been displayed at screen.
//----------------------------------------------------------------------------------------------------
void PrintHeadings()
{
// CalculateSquareRoot
// PreCond: number and newGuess have values entered by
user
// PostCond: Newton's Method has been applied to find square root of
number.
//-------------------------------------------------------------------------------------
void CalculateSquareRoot(double number,
double& newGuess)
{
// find approximations til within tolerance
do
{
while (MoreAccuracyNeeded(newGuess, oldGuess, EPSILON));
// PrintSquareRoot
// PreCond: number is original number
whose square root is to be found;
//
newtonRoot is square root of number from using Newton's Method.
// PostCond: Square roots from Newton's Method and
the Borland C++ square
//
root function have been displayed.
//---------------------------------------------------------------------------------
void PrintSquareRoot(double number,
double newtonRoot)
{
// MoreAccuracyNeeded (function)
// PreCond: newGuess has latest estimated square root, oldGuess has
//
previous square root value, EPSILON is tolerance.
// PostCond: true returned if difference btw the two guesses exceeds
EPSILON;
//
false otherwise.
//-----------------------------------------------------------------------------------------
bool MoreAccuracyNeeded (double newGuess,
double oldGuess,
double EPSILON)
{
// UserWantsToContinue (function)
// PreCond: none
// PostCond: Returns true if user has indicated that he/she
//
wishes to continue using Newton's Method; false otherwise.
//---------------------------------------------------------------------------------
bool UserWantsToContinue()
{
do
{
return (yesorno == 'y');
// ShowIteration
// PreCond: count, oldGuess, newGuess have values for current
iteration.
// PostCond: All three values have been displayed.
//----------------------------------------------------------------------------
void ShowIteration (int count,
double oldGuess,
double newGuess)
{
END of CASE STUDIES.