The goal of this SPA is to give you experience with writing procedural programs with arrays in C++. The basic process is to implement pseudocode we are giving you. But do read the SPA writeup carefully; there are several common mistakes that can lead to endless hours of debugging. NOTE: this is an individual assignment; the CSC/SWE academic integrity document applies in full.
As shown to the right, a histogram is a chart showing how frequently a particular value appears in a data set. Histograms can also be drawn sideways where the frequency is display horizontally. For this SPA, you will write a C++ program to display horizontal histograms. The input to the program will be nonnegative integers, and the output will be an ASCII chart showing the frequencies of each item. The axes will be labeled as described below. For example, if the input values are
0 1 1 4 3 1 1 0then the chart you will draw will be
4 |# 3 |# 2 | 1 |#### 0 |## +----+----+ 0 5 10Note that
#
is being used to mark each value read from the list of
numbers; the ##
means there were two zeros in the input.
In addition to the actual values, the input will start with a specifier
indicating the range of values to process. The first number is the lower
limit, and the second is the upper limit. If the input values
are x
and y
(you need to pick better names!), any
value less than x or larger than y would result in printing
Error: value z is out of rangewhere
z
is the actual value. For instance, if the
specifier is 5 10, then 4 would result in printing
Error: value 4 is out of rangeThe program will always display all of the possible values from the lower to the upper limit. Thus the above chart would be generated by the full input
0 4 0 1 1 4 3 1 1 0The 0 and the 4 represent the possible ranges, and the remaining numbers comprise the data. The input
9 13 12 9 9 12 9 11 14would give the output
Error: value 14 is out of range 13 | 12 |## 11 |# 10 | 9 |### +----+----+ 0 5 10Note that the error message is written to
cout
, not cerr
. This output also
shows that the values written at the start of each row (the 13, 12, etc.)
are printed in three columns to allow for input values up to 999.
The above examples have fewer than ten values. If the input was twelve 5s,
5 5 5 5 5 5 5 5 5 5 5 5(so the legal input range is 5 to 5) the chart would be
5 |########## +----+----+ 0 5 10If some input has a frequency greater than 10, extend the bottom axis to be the next greater multiple of ten. For example, if the input has thirty-two 2s (so first two specify the range is 2 to 2), you would display
2 |############################## +----+----+----+----+----+----+ 0 5 10 15 20 25 30Thirty-three 2s would have a bottom axis that extends out 40 places. The minimum bottom axis is 10 places, so the input "
0 0
" would
give the chart
0 | +----+----+ 0 5 10
Do not prompt for any of the data; just read the numbers from standard input and draw the chart on standard output. You can assume the first two inputs are nonnegative integers. You can also assume that the lower limit is no larger than the upper limit.
Pseudocode is being provided for this SPA (see below); the basic goal of the SPA is to convert the pseudocode into C++ code. However, you are not required to use the pseudocode.
All solutions must satisfy the following constraints. Some but not all of these are captured in the pseudocode.
main
,
which is a function), and no function can have more than 15
lines of code. The 15-line limit includes blank lines; see
the class coding standard.
drawHorizontalAxis
. In general, it is a bad idea to
both compute some result (such as the length of the horizontal axis)
and to write the result (such as displaying the axis) in a single
function. Write one function to compute the result, another to display
it, and call both from a third function. Part of your grade for this
SPA will be based on whether your functions have a single, clear
purpose. This is why blank lines are counted in the 15-line
limit. If you need to separate a function into sections, then the
function is probably overly complex and should be further subdivided.
int n; cin >> n; float nums[n];though in practice you might want to check that n is smaller than some pre-defined limit. For an example of code illustrating this, see
arr.cpp
. Do remember to initialize
the array!
map
or vector
. Instead, use standard arrays declared with [].
cout
and <<
. That is, do not use std::format
or printf
in your solution.
sizeof
in your solution. The
way that students want to use it - find the size of an array - works
reliably in very specific contexts. Use a separate variable to track the
size of your array and pass that information as a parameter to where it
is needed.
You can receive 50% credit for this assignment by
completing test 2, the example given
above. For this input, you can write a function to read the data (as
described above) and implement the longestRow
and axisWidth
functions to always return 10. That is,
the body of both would be simply
return 10;Likewise,
drawHorizontalAxis
would simply write "----+----+"
and labelHorizontalAxis
would write just the 0, 5, and the 10.
Getting this test to pass will go a long way to ensuring you have all of
the basic structure in place.
Note: Like Java, C++ arrays are passed "by reference"; that is, if
a function modifies an element in an array (or all of the elements), then
that change is visible to the rest of the
code. See ../../samples/increasing-numbers-v2.cpp
for sample code with functions and arrays. But unlike Java, there
is no general way to determine the size of an array; you must pass this
information as a separate parameter.
Complete the rest of the lab. You might start by
getting longestRow
and axisWidth
(or their
equivalents) to return correct values,
implement drawHorizontalAxis
, implement
labelHorizontalAxis
, and then correct any remaining issues.
If you run into segmentation fault errors or other run-time issues, see the
bottom of this writeup.
This section gives further hints for portions of this assignment. You do not have to follow these hints, but they might save you some time.
while
loop:
int num; cin >> num; while ( cin ) { // update number of times num appeared in the input cin >> num; }See
distinct1000.cpp
for sample code reading in integers and processing each. In particular,
note how distinct1000.cpp
captures whether or not the program
read any particular value. This SPA is very similar, but instead of
capturing whether a number was read, it captures how many
times that number was read. That is, the numbers_found
array can be replaced by an array of integers counting the number of
appearances. For example, if item 33 in the array has a count of 3, this
means you will print three hash marks for 33 in the resulting chart.
Another difference is that distinct1000
declares a fixed-sized
array; for this SPA you are to use a size that you read from standard input.
spa2-pseudocode.txt
contains
pseudocode for various functions that might be helpful for the SPA.
cout << setw(4) << x;will print x (say, an integer) in four spaces, adding leading spaces as needed to fill out all four spaces. If x takes more than four spaces, it will print the whole value (but without any spaces before it). To use
setw
, you need to write
#include <iomanip>at the top of the file, near the include for
iostream
. By
default, setw
aligns values to the right; you can
use left
and right
to control this if necessary
(though many solutions will not need either one). Alternatively, you could
simply format the data for yourself by writing (say) loops that print the
right number of spaces in front of any numbers.
list
or vector
in your solution. A key
part of this assignment is learning to process simple arrays.