n_refinement - CIS Programs at Baruch College

advertisement
Writing a Good Program
[The following guidelines use the word program but hold true just as well for code
pieces, i.e., functions, classes, etc.]
Programs should, optimally, be functional, elegant, efficient, user-friendly, and selfdocumenting.
Why bother with programming style? Lots of reasons.
 ease in debugging
 to enable other programmers to follow your logic and the way it was carried
through in the program. A program is usually used many times, by many
different people.
 You may want to use your program again yourself in the future. A poorly written
/ documented program is hard to understand and does not lend itself to reuse.
 A well-written program is often more efficient and economical than a poorly
written one.
 Modifications may be called for in the future. An unintelligible program is a
monster to modify and debug.
A. Functional - The program should do what it is called upon to do. It should be errorfree and produce output that is correct.
B. Elegant - The program should do it in the best possible way. Avoid convoluted logic
and awkward control mechanisms. break, continue, and goto statements are
occasionally useful - employ them only when absolutely necessary.
C. Efficient - The program should not be unnecessarily wasteful of computer resources,
namely, time and space (memory). Avoid the use of extra variables and/or operations
that are not needed for the functionality or readability of the program.
D. User-friendly - The program should make as few assumptions as possible about the
capabilities of the user.
This means giving interactive user screens and printed reports a “natural” style
and appearance. As always, we are trying to bring the machine up to the level of
the human user (rather than the other way around). We use prompts to let the user
know what kind of data is expected and in what format. Whenever possible we
provide the user with a menu of options or possible data values to input. We
validate the input data and provide helpful error messages (and a chance to enter
the data again) if the input data is not in the correct range, format, etc.
106741325.doc
1 of 16
E. Self-documenting - The program should contain within the source code as much
documentation information as possible.
The program should be structured to highlight the major processes involved. Use
descriptive names for variables, constants, functions, classes, objects, etc.
Employ a recognized and consistent indenting scheme. Avoid unnecessary
variables - too many variables not only waste memory but they also make
programs harder to understand. Liberal use of comments: to explain what each
variable name stands for; to clarify complicated calculations; to give information
regarding the data needed by the program: data format, type, files used, etc.
Comment block at the beginning of the program can contain: descriptive name
for the program, author’s name, date written, date last modified, purpose of
program.
Assignment: Redo a programming assignment of your choice to make it as userfriendly and as self-documenting as possible. Submit together with your previous version
of the assignment.
106741325.doc
2 of 16
Progressive Modification: Example
Problem - Case #1 I have a sum of money to invest at a particular rate of interest for 10 years.
How much money will I have at the end of 10 years, if compounded annually? What
is my total interest earned?
Analysis:
a) output principal in 10 years P
amount earned E
b) input initial amount of money - P0
rate of interest R
c) method - compound interest calculation - pseudocode or flowchart
Pseudocode:
(1) Start working on program.
(2) Input amount, interest rate.
(3) Calculate P1 (principal in year 1) as P0+ P0* R
(4) Output principal for year 1
(5) Calculate P2 (principal in year 2) as P1+ P1* R
(6) Output principal for year 2
(7) For each of the remaining years, N = 3 through 10, repeat steps (5) and (6), for
principal in year N.
(8) Calculate E: P10 - P0.
(9) Output P10, E.
(10) Stop working on program.
START
Flowchart:
INPUT P0, R
CALCULATE
and PRINT P for
each year
CALCULATE P10 , E
OUTPUT P10, E
STOP
106741325.doc
3 of 16
//case1.cpp
// Compound Interest Program - Case 1
// This program computes interest on some initial investment,
// compounded annually for 10 years.
#include <iostream>
int main()
{
int year;
float pzero, p, rate, earned;
cout << "Starting principal? ";
cin >> pzero;
cout << "Interest rate? ";
cin >> rate;
cout << endl;
p = pzero;
for (year=1; year<=10; year++){
p = p + p * rate;
cout << "After " << year << " years, you will have $" <<p <<endl;
}
earned = p - pzero;
cout << "\nTotal interest earned: $" << earned <<endl;
return 0;
//successful termination
} //end main
Case 1 program output:
Of course, we would really like the output to look like we are working with dollars
and cents. We will use the stream manipulator functions of <iomanip>.
106741325.doc
4 of 16
cout
<< setiosflags (ios::fixed | ios::showpoint)
<< setw(20)
<< setprecision(2)
<< var
<< endl;
//** Formatting for stream output**
// fixed point |
// always print decimal point
// field width is 20 characters
// 2 digits after decimal point
// variable to be output
// newline
//case1a.cpp
// Compound Interest Program - Case 1 - revised for nicer output
// This program computes interest on some initial investment,
// compounded annually for 10 years.
#include <iostream>
#include <iomanip>
int main()
{
int year;
float pzero, p, rate, earned;
cout << "Starting principal? ";
cin >> pzero;
cout << "Interest rate? ";
cin >> rate;
cout << endl;
cout << setiosflags(ios::fixed |ios::showpoint) << setprecision(2);
p = pzero;
for (year=1; year<=10; year++){
p = p + p * rate;
cout << "After " << year << " years, you will have $" <<p <<endl;
}//end for
earned = p - pzero;
cout << "\nTotal interest earned: $" << earned <<endl;
return 0;
//successful termination
} //end main
Much nicer!
106741325.doc
5 of 16
Case 2 -- Suppose I wish to perform these calculations for 5 different sets of input
data:
//case2.cpp
// Compound Interest Program - Case 2
// This program computes interest on some initial investment,
// compounded annually for 10 years.
#include <iostream>
#include <iomanip>
int main()
{
int year;
float pzero, p, rate, earned;
for (int count = 1; count <=5; count++) {
cout << "\n\n\tInvestment decision #" << count << endl;
cout << "\nStarting principal? ";
cin >> pzero;
cout << "Interest rate? ";
cin >> rate;
cout << endl;
cout << setiosflags(ios::fixed |ios::showpoint)
<< setprecision(2);
p = pzero;
for (year=1; year<=10; year++){
p = p + p * rate;
cout << "After " << year << " years, you will have $"
<< p <<endl;
} //end for
earned = p - pzero;
cout << "\nTotal interest earned: $" << earned <<endl;
}//end for
return 0;
//successful termination of program
} //end main
106741325.doc
6 of 16
Partial output:
Partial output:
106741325.doc
7 of 16
Case 3 - Why limit the investment to 10 years only?
//case3.cpp
// Compound Interest Program - Case 3
// This program computes interest on some initial investment,
// compounded annually for any number of years.
#include <iostream>
#include <iomanip>
int main()
{
int n, year, years;
float pzero, p, rate, earned;
for (int count = 1; count<=5; count++) {
cout << "\n\n\tInvestment decision #" << count << endl;
cout << "\nStarting principal? ";
cin >> pzero;
cout << "Interest rate? ";
cin >> rate;
cout << "How many years? ";
cin >> years;
cout << endl;
cout << setiosflags(ios::fixed |ios::showpoint)
<< setprecision(2);
p = pzero;
for (year=1; year<=years; year++){
p = p + p * rate;
cout << "After " << year << " years, you will have $"
<< p <<endl;
} //end for
earned = p - pzero;
cout << "\nTotal interest earned: $" << earned <<endl;
}//end for
return 0;
//successful termination of program
} //end main
106741325.doc
8 of 16
Partial Output:
106741325.doc
9 of 16
Case 4 - How about for N sets of data?
//case4.cpp
// Compound Interest Program - Case 4
// This program computes interest on some initial investment,
// compounded annually for any number of years.
#include <iostream>
#include <iomanip>
int main()
{
int n, year, years;
float pzero, p, rate, earned;
cout << "How many sets of data? ";
cin >> n;
for (int count = 1; count <=n; count++) {
cout << "\n\n\tInvestment decision #" << count << endl;
cout << "\nStarting principal? ";
cin >> pzero;
cout << "Interest rate? ";
cin >> rate;
cout << "How many years? ";
cin >> years;
cout << endl;
cout << setiosflags(ios::fixed |ios::showpoint)
<< setprecision(2);
p = pzero;
for (year=1; year<=years; year++){
p = p + p * rate;
cout << "After " << year << " years, you will have $"
<< p <<endl;
} //end for
earned = p - pzero;
cout << "\nTotal interest earned: $" << earned <<endl;
}//end for
return 0;
//successful termination of program
} //end main
106741325.doc
10 of 16
Partial output:
106741325.doc
11 of 16
Case 5 - Producing a simple report
//case5.cpp
// Compound Interest Program - Case 5
// Using a report textfile
// This program computes interest on some initial investment,
// compounded annually for any number of years.
#include <fstream>
#include <iostream>
#include <iomanip>
int main()
{
int n, year, years;
float pzero, p, rate, earned;
ofstream cprn ("report.txt"); //File contains the report
cout << "How many sets of data? ";
cin >> n;
for (int count = 1; count <=n; count++) {
cout << "\n\n\tInvestment decision #" << count << endl;
cout << "\nStarting principal? ";
cin >> pzero;
cout << "Interest rate? ";
cin >> rate;
cout << "How many years? ";
cin >> years;
cout << endl;
cprn << setiosflags(ios::fixed |ios::showpoint)
<< setprecision(2);
p = pzero;
cprn << "\n\n\tInvestment decision #" << count << endl;
cprn << "Starting Principal = $" << pzero <<endl
<< "Interest rate = " << rate <<endl<<endl;
for (year=1; year<=years; year++){
p = p + p * rate;
cprn << "After " << setw(3) << year
<< " years, you will have $"
<< p <<endl;
} //end for
earned = p - pzero;
cprn << "\nTotal interest earned: $" << earned <<endl;
}//end for
cout << "See report in textfile \"report.txt\"\n\n";
return 0;
//successful termination of program
} //end main
ofstream is a class defined in the fstream.h header file. We use it to define an object
called cprn. When we use cprn in place of cout, the stream output is sent to the
report.txt textfile rather than to the standard output (screen). This will become clearer
when we write our own classes and objects.
106741325.doc
12 of 16
Interactive Output Window:
106741325.doc
13 of 16
Print the contents of report.txt:
Investment decision #1
Starting Principal = $100.00
Interest rate = 0.05
After
After
After
After
After
After
After
After
After
After
1
2
3
4
5
6
7
8
9
10
years,
years,
years,
years,
years,
years,
years,
years,
years,
years,
you
you
you
you
you
you
you
you
you
you
will
will
will
will
will
will
will
will
will
will
Total interest earned:
have
have
have
have
have
have
have
have
have
have
$105.00
$110.25
$115.76
$121.55
$127.63
$134.01
$140.71
$147.75
$155.13
$162.89
$62.89
Investment decision #2
Starting Principal = $100.00
Interest rate = 0.15
After
After
After
After
After
After
After
After
After
After
After
After
After
After
After
After
After
After
After
After
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
years,
years,
years,
years,
years,
years,
years,
years,
years,
years,
years,
years,
years,
years,
years,
years,
years,
years,
years,
years,
you
you
you
you
you
you
you
you
you
you
you
you
you
you
you
you
you
you
you
you
will
will
will
will
will
will
will
will
will
will
will
will
will
will
will
will
will
will
will
will
Total interest earned:
106741325.doc
have
have
have
have
have
have
have
have
have
have
have
have
have
have
have
have
have
have
have
have
$115.00
$132.25
$152.09
$174.90
$201.14
$231.31
$266.00
$305.90
$351.79
$404.56
$465.24
$535.03
$615.28
$707.57
$813.71
$935.76
$1076.13
$1237.55
$1423.18
$1636.65
$1536.65
14 of 16
More on Formatting Program Ouptut
Standard I/O - <iostream.h>
cin
cout
I/O manipulators - use <iomanip.h> header file
setfill(ch)
set the fill character to ch
setw(n)
set the field width to n
setprecision(n)
set the floating-point precision to n places
setiosflags(flags) set the format flags for the ios [input/output stream]
Note: The setiosflags manipulator is also called a parametized manipulator, since it has
parameters (arguments).
format flags for setiosflags()
[these flags may be combined by | operators]
ios::showpoint
always show the decimal point (default is 6 decimal digits)
ios::showpos
display a leading + sign when the number is positive
ios::fixed
display up to 3 integer digits and 2 digits after the decimal point.
(For larger values, use exponential notation.)
ios::scientific
use exponential notation to display output
ios::showbase
show base indicator on output
ios::left
left justify output
ios::right
right justify output
ios::skipws
skip whitespace on input
ios::fixed forces all subsequent numbers placed on the cout stream to be placed as if they
were floating point values. ios::showpoint is then used to always display a decimal point.
Since we often want both of these flags set, we will frequently joint them with the OR
operator: setiosflags(ios::fixed || ios::showpoint). Then, setprecision(2) is used to ensure
that (say) 2 decimal digits will always print even for numbers like 4 (4.00) or 4.1 (4.10).
Flag  in the current usage, a flag sets a certain condition as active. Activating one flag
(e.g. right) may automatically deactivate other flag(s) (e.g. left).
(Bronson p.132) Examples:
[with ios::fixed flag set]
manipulator(s)
number
display
comments
setw(2)
setw(2)
setw(2)
setw(2)
| 3|
|43|
|143|
|2.3|
number fits
number fits
field width
field width
setw(5)
106741325.doc
3
43
143
2.3
in field
in field
ignored
ignored
field width 5
15 of 16
setprecision(2) 2.366
|
2.37|
setw(5)
setprecision(2) 42.3
| 42.3|
setw(5)
setprecision(2) 142.364 |142.36|
106741325.doc
w/ 2 decimal digits
number fits in field
field width ignored but
precision spec used
16 of 16
Download