    <rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:admin="http://webns.net/mvcb/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:content="http://purl.org/rss/1.0/modules/content/">
     <channel>
        <title>ACCU  :: Student Code Critique Competition 32</title>
        <link>https://members.accu.org/index.php/articles/790</link>
        <description>Professionalism in Programming</description>
        <dc:language>en-us</dc:language> 
        <dc:creator>Administrator</dc:creator> 
        <admin:generatorAgent rdf:resource="http://www.xaraya.org" /> 
        <admin:errorReportsTo rdf:resource="mailto:webeditor@accu.org" />
       <sy:updatePeriod>hourly</sy:updatePeriod>
       <sy:updateFrequency>1</sy:updateFrequency>
       <docs>http://backend.userland.com/rss</docs>




<div class="xar-mod-head"><span class="xar-mod-title">Student Code Critiques from CVu journal. + CVu Journal Vol 17, #1 - Feb 2005</span></div>

<table border="0" cellpadding="1" cellspacing="0">
    <tbody>
    <tr>
        <td valign="top">
            Browse in :
       </td>
       <td valign="top">

                                            <a href="https://members.accu.org/index.php/articles/">All</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c184/">Journal Columns</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c183/">Code Critique</a>
<br />

                                            <a href="https://members.accu.org/index.php/articles/">All</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c76/">Journals</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c77/">CVu</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c98/">171</a>
<br />

                                            <a href="https://members.accu.org/index.php/articles/c183-98/">Any of these categories</a>

                    -                        <a href="https://members.accu.org/index.php/articles/c183+98/">All of these categories</a>
<br />
</td>
   </tr>
   </tbody>
</table>




<div class="xar-error">
   <p>
 <strong>Note:</strong> when you create a new publication type,
the articles module will automatically use the templates
<em>user-display-[publicationtype].xt</em>
and <em>user-summary-[publicationtype].xt</em>.
If those templates do not exist when you try to preview or display a new article,
you'll get this warning :-)  Please place your own templates in themes/<em>yourtheme</em>/modules/articles . The templates will get the extension .xt there. </p>
</div>
<div class="xar-norm xar-standard-box-padding">
   <h1><strong>Title:</strong>&nbsp;Student Code Critique Competition 32</h1>
<p><strong>Author:</strong>&nbsp;</p>
<p>
<strong>Date:</strong> 06 February 2005 13:16:10 +00:00 or Sun, 06 February 2005 13:16:10 +00:00</p>
<p><strong>Summary:</strong>&nbsp;</p>
<p><strong>Body:</strong>&nbsp;<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e22" id="d0e22"></a></h2>
</div>
<p><span class="bold"><b>Prizes provided by Blackwells Bookshops
&amp; Addison-Wesley</b></span></p>
<p class="c2"><span class="remark">Please note that participation
in this competition is open to all members. The title reflects the
fact that the code used is normally provided by a student as part
of their course work.</span></p>
<p class="c2"><span class="remark">This item is part of the
Dialogue section of C Vu, which is intended to designate it as an
item where reader interaction is particularly important. Readers'
comments and criticisms of published entries are always
welcome.</span></p>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e33" id="d0e33"></a>Before We
Start</h2>
</div>
<p>Besides wishing you all (unpunctually) a prosperous 2005, a
special thanks to those who participate in this competition for
their support.</p>
<p>Remember that you can get the current problem set at the ACCU
website (<a href="http://www.accu.org/journals/" target=
"_top">http://www.accu.org/journals/</a>). This is for people
living overseas who get the magazine much later than members in the
UK and Europe.</p>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e43" id="d0e43"></a>Editor's
Note</h2>
</div>
<p>Due to the large number of entrants this time, I have found this
a particularly difficult SCC to judge; the entries are that good
(as you'll see!). As we're at the start of a new year, two prizes
will be awarded for this SCC.</p>
<p>Thank you to everyone who entered for making this the most
difficult SCC to judge, and oddly enough, the most enjoyable - keep
sending those entries in folks!</p>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e50" id="d0e50"></a>Student Code
Critique 31 Entries</h2>
</div>
<p><span class="emphasis"><em>Here is the code I have using the
equation to drop the lowest number from the grades. The problem is,
if I change up number 3 and number 4, I get a different answer. I
used the numbers 80, 84, 60, 100 and 90. Putting the numbers in
like that, I get 88 but, if I mix up the 100 and 60 then I get a
grade of 81. Can anyone tell me why it is not finding the lowest
number and just dropping it when I tell it to (-
lowest)?</em></span></p>
<pre class="programlisting">
#include &lt;iostream&gt;
#include &lt;iomanip&gt;
using namespace std;

int main() {
int test1, test2, test3, test4,test5,average,
                          averagescore,divide;
cout &lt;&lt;&quot;This program will gather five test
                                scores and\n&quot;;
cout &lt;&lt;&quot;drop the lowest score, giving you the
                                   average\n&quot;;
cout &lt;&lt;&quot;\n&quot;;
cout &lt;&lt;&quot;Please enter Five Test scores\n&quot;;
cin &gt;&gt; test1&gt;&gt;test2&gt;&gt;test3&gt;&gt;test4&gt;&gt;test5;
int lowest = test1;
       // test 1 is the lowest number unless
if (test2 &lt; test1)lowest = test2;
       // test 2 is smaller than test 1 unless
if (test3 &lt; test2)lowest = test3;
       // test 3 is smaller than test 2 unless
if (test4 &lt; test3)lowest = test4;
       // test 4 is smaller than test 3 unless
if (test5 &lt; test4)lowest = test5;
       // test 5 is smaller than test 4.
average = (test1+test2+test3+test4+test5);
       // all test scores averaged together
averagescore = average - lowest;
       // average score minus the lowest grade
divide = averagescore /4;
       // average grade is then divided by 4
cout &lt;&lt; divide&lt;&lt; endl;
       // final grade after division
return 0;
}
</pre>
<p>Besides the question asked by the student, this code gives you a
chance to discuss topics such as extensibility, design and style.
Please address as many issues as you consider necessary, without
omitting the answer to the original question.</p>
<div class="sect2" lang="en">
<div class="titlepage">
<h3><a name="d0e60" id="d0e60"></a>From Tim Penhey
<tt class="email">&lt;<a href=
"mailto:Tim.PENHEY@rbos.com">Tim.PENHEY@rbos.com</a>&gt;</tt></h3>
</div>
<p>I do have to admit that on first scan of the code, I didn't
notice the error. It was only when typing the code in that I
noticed it.</p>
<p>One thing that I often do when working with numbers is to
actually transpose the numbers into the code and look for errors.
It is very easy to get caught by &quot;off by one&quot; errors, however this
is not one of those times. Firstly let's look at the first sequence
of numbers:</p>
<pre class="programlisting">
80 84 60 100 90
</pre>
<p>Now put these into the code replacing the test variables (let's
replace the comments too):</p>
<pre class="programlisting">
int lowest = 80;
// 80 is the lowest number unless
if (84 &lt; 80) lowest = 84;
// 84 is smaller than 80 unless
if (60 &lt; 84) lowest = 60;
// 60 is smaller than 84 unless
if (100 &lt; 60) lowest = 100;
// 100 is smaller than 60 unless
if (90 &lt; 100) lowest = 90;
// 90 is smaller than 100.
</pre>
<p>Now we can easily see that the logic is flawed. Checking the
adjacent value will not choose the smallest. The simplest change
that will get the code to work is the check against the current
lowest value instead</p>
<pre class="programlisting">
int lowest = test1;
         // test 1 is the lowest number unless
if (test2 &lt; lowest) lowest = test2;
         // test 2 is smaller than lowest unless
if (test3 &lt; lowest) lowest = test3;
         // test 3 is smaller than lowest unless
if (test4 &lt; lowest) lowest = test4;
         // test 4 is smaller than lowest unless
if (test5 &lt; lowest) lowest = test5;
         // test 5 is smaller than lowest.
</pre>
<p>Now to comment on style...</p>
<div class="itemizedlist">
<ul type="disc">
<li>
<p>maybe it is just me, but I prefer to have the comment above the
code that it is referring to, not below. Perhaps it is just that I
like to know the intent before I see the code. [<i><span class=
"remark">Production Editor - that was my fault, comments were at
the end of the lines, and as there wasn't room within the standard
layout I inserted line breaks with indentation, which is standard
procedure for the ACCU journals. This is the only layout change I
ever make to the code critique problem</span></i>]</p>
</li>
<li>
<p><tt class="filename">&lt;iomanip&gt;</tt> is not needed as the
only manipulator being used is <tt class="literal">endl</tt>, and
that is defined in <tt class="filename">&lt;ostream&gt;</tt> (which
is included through <tt class="filename">&lt;iostream&gt;</tt>.</p>
</li>
<li>
<p>use appropriate variable names. <tt class="varname">average</tt>
in the example is not the <tt class="varname">average</tt> but the
sum, and <tt class="varname">averagescore</tt> is the sum less the
lowest.</p>
</li>
</ul>
</div>
<p>What is going to happen if we now need to test six values, or
ten, or even a class of 30? The algorithm being used is not
particularly extensible.</p>
<p>One solution is to calculate the sum and the lowest while
entering value. However when doing this we now have to handle the
boundary cases where the user may enter any number of values. No
values obviously has average of zero, while one value is by
definition also the lowest, and the average of the rest (no values)
is zero, so the average calculation is only valid where the number
of entered values is greater than one. Here is an example that
accumulates on the fly:</p>
<pre class="programlisting">
#include &lt;iostream&gt;
#include &lt;limits&gt;
using namespace std;
int main() {
  cout &lt;&lt; &quot;This program will gather &quot;
       &lt;&lt; &quot;test scores and drop the\n&quot;
       &lt;&lt; &quot;lowest score, giving you the &quot;
       &lt;&lt; &quot;average of the remaining.\n\n&quot;
       &lt;&lt; &quot;Enter test scores.  Terminate &quot;
       &lt;&lt; &quot;the last score with a period.\n&quot;;
  int sum = 0;
  int count = 0;
  int value;
  int lowest = numeric_limits&lt;int&gt;::max();
  while(cin &gt;&gt; value) {
    if(value &lt; lowest) lowest = value;
    sum += value;
    ++count;
  }
  int average = 0;
  if(count == 0)
    cout &lt;&lt; &quot;No entries entered\n&quot;;
  else if(count == 1)
    cout &lt;&lt; &quot;Only one value entered, &quot;
         &lt;&lt; &quot;so it is the lowest value.&quot;;
  else
    average = (sum - lowest) / (count - 1);
  cout &lt;&lt; &quot;Average: &quot; &lt;&lt; average &lt;&lt; endl;
  return 0;
}
</pre>
<p><tt class="classname">numeric_limits</tt> is used to define the
initial value of the <tt class="varname">lowest</tt> variable.
Since any other integer value will be equal or less than this, then
any value typed in as the first value will set the <tt class=
"varname">lowest</tt> to be that. Subsequent values are then
checked against the current <tt class="varname">lowest</tt>.</p>
<p>The other &quot;trick&quot; in the code is using the <tt class=
"varname">fail</tt> flag on cin to terminate the entry loop. The
<tt class="varname">fail</tt> flag happens when we ask to stream
into an integer and the stream contains a non-whitespace
non-integer value, hence the terminating the last score with a
period.</p>
<p>Another solution is to use standard containers and use
algorithms like <tt class="classname">accumulate</tt> to sum the
values, but this I'll leave as an exercise for the reader (or other
submitters).</p>
</div>
<div class="sect2" lang="en">
<div class="titlepage">
<h3><a name="d0e146" id="d0e146"></a>From Thaddaeus
Frogley <tt class="email">&lt;<a href=
"mailto:codemoney_uk@mac.com">codemoney_uk@mac.com</a>&gt;</tt></h3>
</div>
<p>The code does not work because of a simple logical error, and
not a language specific problem. Each <tt class="literal">if</tt>
statement is evaluated &quot;locally&quot; and in effect ignores the
preceding work done. Thus, as the student as observed, if
<tt class="varname">test5</tt> contains a smaller value than
<tt class="varname">test4</tt> then lowest is assigned <tt class=
"varname">test5</tt>, irrespective of the results of the preceding
tests. The straightforward fix is to change the sequence of if
statements to compare each time against the current lowest value,
then I would expect the code to work.</p>
<p>This of course ignores issues of extensibility, design and
style, but for a student of this level I would consider it more
important to understand the logical flow required to solve the
problem at this simple level. Ultimately knowledge of the standard
library is second to a solid grasp of constructing a logical
sequence of steps to solve a problem programatically. For future
reading I would advise reading up on arrays and containers, and the
<tt class="classname">std::sort</tt> algorithm. Constant use of
<tt class="literal">std::endl</tt> vs <tt class="literal">\n</tt>
would also be nice.</p>
</div>
<div class="sect2" lang="en">
<div class="titlepage">
<h3><a name="d0e176" id="d0e176"></a>From Roger Orr
<tt class="email">&lt;<a href=
"mailto:rogero@howzatt.demon.co.uk">rogero@howzatt.demon.co.uk</a>&gt;</tt></h3>
</div>
<p>The first thing to do is to answer the student's question - they
want to know what is wrong with the code. The answer is the
sequence of comparisons of adjacent test values: the result of each
stage (the new value of lowest) needs to be passed into the next
comparison.</p>
<p>Simply change the sequence to:</p>
<pre class="programlisting">
int lowest = test1;
      // test 1 is the lowest number unless
if(test2 &lt; lowest) lowest = test2;
      // test 2 is smaller than lowest so far unless
if(test3 &lt; lowest) lowest = test3;
      // test 3 is smaller than lowest so far unless
if(test4 &lt; lowest) lowest = test4;
      // test 4 is smaller than lowest so far unless
if(test5 &lt; lowest) lowest = test5;
      // test 5 is smaller than lowest so far.
</pre>
<p>This fixes the code - but there are several other things worth
commenting on. Firstly, this sort of code cries out for a loop! In
order to do this we want an array variable rather than 5 separate
variables. C++ comes with a suitable collection object: the
<tt class="classname">vector</tt>. So we can replace the list of
variables <tt class="varname">test1</tt> to <tt class=
"varname">test5</tt> with:</p>
<pre class="programlisting">
std::vector&lt;int&gt; test(5);
</pre>
<p>then the input, the test and the addition can all be done by
using loops - this is immediately generalisable to cases where
you've got more (or less) than 5 numbers to process.</p>
<p>To make the code more robust, this should be the last time we
use the hard-coded number '5' - the rest of the program can use the
size of the <tt class="classname">vector</tt> to ensure it copes
with changes to this number.</p>
<pre class="programlisting">
for(int i = 0; i != test.size(); ++i)
  cin &gt;&gt; test[i];
int lowest = test[0];
for(int i2 = 1; i2 != test.size(); ++i2)
  if(test[i2] &lt; lowest) lowest = test[i2];
          // get the lowest number
average = 0;
for(int i3 = 0; i3 != test.size(); ++i3)
  average += test[i3];
</pre>
<p>I'd also like to change the names of the variables - the names
don't match the contents. For example, <tt class=
"varname">average</tt> and <tt class="varname">averagescore</tt>
both contain totals, not averages!</p>
<p>It is good to pick meaningful names for variables, but important
to remember to keep the names of the variables consistent with
their usage to avoid leading the reader of the code astray.</p>
<p>Lastly, we can get rid of some of the loops by using algorithms
provided by the standard library. We can use <tt class=
"classname">min_element</tt> to find the lowest value and
<tt class="classname">accumulate</tt> to perform the sum.</p>
<p>My final version of the program looks like this:</p>
<pre class="programlisting">
#include &lt;iostream&gt;
#include &lt;iomanip&gt;
#include &lt;vector&gt;
#include &lt;algorithm&gt;
#include &lt;numeric&gt;
using namespace std;

int main() {
  cout &lt;&lt; &quot;This program will gather &quot;
       &lt;&lt; &quot;five test scores and\n&quot;;
  cout &lt;&lt; &quot;drop the lowest score, &quot;
       &lt;&lt; &quot;giving you the average\n&quot; &lt;&lt; &quot;\n&quot;;
  cout &lt;&lt; &quot;Please enter Five Test scores\n&quot;;
  std::vector&lt;int&gt; test(5);
  for(int i = 0; i != test.size(); ++i)
    cin &gt;&gt; test[i];
  int lowest = *min_element(test.begin(),
                            test.end());
  int totalscore = std::accumulate(test.begin(),
                               test.end(), -lowest);
          // total score (minus the lowest grade)
  int divide = totalscore / ( test.size() - 1);
     // average grade is then total divided by (n-1)
  cout &lt;&lt; divide &lt;&lt; endl;
          // final grade after division
  return 0;
}
</pre>
<p>My hope is that the resultant code is easy to understand and
does the task well enough. This code may be slower to write than
the original code the first time, but with practice it will become
second nature. The time spent learning to do this is also repaid in
the reduction in bugs.</p>
</div>
<div class="sect2" lang="en">
<div class="titlepage">
<h3><a name="d0e233" id="d0e233"></a>From Richard
Wheeler <tt class="email">&lt;<a href=
"mailto:acht85@ukgateway.net">acht85@ukgateway.net</a>&gt;</tt></h3>
</div>
<p>OK, so I am not a programmer but every now and then I get to
look at code, especially when I want to know what actually happens
in a program. (Especially when I do not believe the documentation
or there is no documentation). Thank heavens this code compiles and
runs - I don't think I could handle obscure syntax problems.
Anyway, full marks to the student for carrying out sufficient
testing to identify that there is a problem. Now, looking at the
student's code a number of points to comment on jump out at me. I
will treat them in order so the trivial are mixed in with the more
important - but then with just a short piece of code it is not
clear how a trivial comment would scale into a programme with
thousands of lines of code.</p>
<p><span class="bold"><b>1. Input validation</b></span></p>
<p>There is no validation of the input. This is not the student's
issue but it is worth a remark as I would expect significant
further programming effort to ensure that the input is properly
validated (sensible means of stopping the programme if run in
error, the correct number of exam grades are entered, each is a
number, each within sensible bounds, meaningful error messages to
the user, etc).</p>
<p><span class="bold"><b>2. Choice of variable names</b></span></p>
<p>I do not like variable names which look like reserved words -
<tt class="varname">average</tt> and <tt class=
"varname">divide</tt> (and further down <tt class=
"varname">lowest</tt>) make me uneasy. These names look as though
they are self-documenting but I would prefer something like
<tt class="varname">average_score</tt> and <tt class=
"varname">lowest_score</tt> as better self-documenting names. [See
also comment 7 below].</p>
<p><span class="bold"><b>3. Consistent programming
style</b></span></p>
<p>I look for a consistent programming style as this should speed
up comprehension of code. Here we have a block where all the
<tt class="type">int</tt> variables are defined except for the
single variable <tt class="varname">lowest</tt> which is defined
later. I may be making a mountain out of a molehill in this case
but when a programme extends to thousands of lines then consistency
is important.</p>
<p><span class="bold"><b>4. Program logic</b></span></p>
<p>This is the guts of the student's problem. The process should be
to set up a placeholder for the lowest grade. This is given any
grade as its initial value (and the first grade is as good as any).
Then each grade is compared in turn to the placeholder and if the
grade has a lower value the placeholder is reset to that grade.
From this description it follows that the <tt class=
"literal">if</tt> statements should read</p>
<pre class="programlisting">
if(testn &lt; lowest)lowest = testn;
</pre>
<p>for each value of <tt class="varname">n</tt> from 1 to 5.</p>
<p><span class="bold"><b>5. Generalisation (1)</b></span></p>
<p>I am against unnecessary generalisation but in this case I think
it clarifies the program logic. If we allow for a variable number
of tests we can generalise the logic into a <tt class=
"literal">for</tt> loop using an array of test scores. Something on
the following lines should do</p>
<pre class="programlisting">
lowest_score = test_score(1);
for(int i = 1, i &lt;= number_of_tests, i++) {
  if(test_score(i) &lt; lowest_score)
    lowest_score = test_score(i);
}
</pre>
<p>(The student might want to change the input process to start
with obtaining the number of grades, so giving a value to the new
variable <tt class="varname">number_of_tests</tt> - there are other
approaches which could be used).</p>
<p>A bit of cleverness might be to avoid the first iteration in the
loop as this is unnecessary. But that, in my opinion, tends to
obscure the logic process.</p>
<p><span class="bold"><b>6. Comments should be meaningful
(1)</b></span></p>
<p>I found the comments against all the if statements were not very
helpful. In fact one reason for generalising to the for loop above
was to think how the for loop should be commented and compare this
to the existing comments. In fact I would not bother to comment the
<tt class="literal">for</tt> loop at all.</p>
<p><span class="bold"><b>7. Variable names are
misleading</b></span></p>
<p>The variable <tt class="varname">average</tt> is set to a total
and is not an average at all. As variable names, <tt class=
"varname">average</tt> and <tt class="varname">averagescore</tt>
give no clues as to the different (or same) data entities they
refer to. <tt class="varname">divide</tt> gives no clues at all to
what it means. I would suggest that the following are more
meaningful values</p>
<p><tt class="varname">total_score</tt> for <tt class=
"varname">average</tt></p>
<p><tt class="varname">adjusted_total_score</tt> for <tt class=
"varname">averagescore</tt></p>
<p><tt class="varname">final_grade</tt> for <tt class=
"varname">divide</tt></p>
<p><span class="bold"><b>8. Comments should be meaningful
(2)</b></span></p>
<p>The comments in the section of code which calculates the final
grade are wrong. (Note the distinction - the variable names are
misleading, the comments are wrong). With good variable names (such
as those suggested above) I think that comments are
unnecessary.</p>
<p><span class="bold"><b>9. Magic numbers</b></span></p>
<p>The evaluation of <tt class="varname">divide</tt> uses the
&quot;magic number&quot; 4. This comment is scarcely worth bothering about in
this specific example but is something to be aware of if the
programme is generalised to handle any number of grade scores.</p>
<p><span class="bold"><b>10. Generalisation (2)</b></span></p>
<p>Following on from the generalisation of the logic there needs to
be corresponding generalisation of calculation of the <tt class=
"varname">total_score</tt>. I would use</p>
<pre class="programlisting">
total_score = 0;
for(int i = 1, i &lt;= number_of_tests, i++) {
  total_score = total_score + test_score(i);
}
</pre>
<p>Now there are two <tt class="literal">for</tt> loops. Perhaps
compiler optimisation can roll these up into one. I would do this
explicitly and, at last, include a comment</p>
<pre class="programlisting">
// calculate lowest score and total of all scores
lowest_score = test_score(1);
total_score = 0;
for(int i = 1, i &lt;= number_of_tests, i++) {
  if(test_score(i) &lt; lowest_score)
    lowest_score = test_score(i);
  total_score = total_score + test_score(i);
}
</pre>
<p>and, just for comparison, we could save the first iteration of
the loop with</p>
<pre class="programlisting">
// calculate lowest score and total of all scores
lowest_score = test_score(1);
total_score = test_score(1);
for(int i = 2, i &lt;= number_of_tests, i++) {
  if(test_score(i) &lt; lowest_score)
    lowest_score = test_score(i);
  total_score = total_score + test_score(i);
}
</pre>
<p>But, as I said before, I think this is unnecessary cleverness
which obscures what is happening.</p>
<p><span class="bold"><b>11. User interface niceties</b></span></p>
<p>The student has taken care on input to explain to whoever runs
the program what the program does. But for the results, the
adjusted grade value is all that appears. I think it would be an
improvement to have a line which explains the results. Something
like</p>
<pre class="programlisting">
cout &lt;&lt; &quot;The adjusted grade for your &quot;
     &lt;&lt; &quot;five test scores is \n&quot;;
</pre>
<p>Finally there are a number of other points which make me feel
uneasy. I would want to discuss these with the student's tutor /
mentor / project leader as to whether the student needs additional
help. These are:</p>
<div class="itemizedlist">
<ul type="disc">
<li>
<p>The student's initial description of the problem does not come
over as fluent English. Is the student a native English speaker? (I
have worked on multi-national projects with English as the project
language. I found that fluent English speakers were still worried
that as &quot;non-native speakers&quot; they could misunderstand the
subtleties of requirements etc). [<i><span class="remark">I don't
know where he is from. David</span></i>]</p>
</li>
<li>
<p>I wonder whether the student's incorrect comments about
calculating the average etc are a problem with the English language
or a problem with understanding the code.</p>
</li>
<li>
<p>Whilst I give the student full marks for identifying the problem
through testing, it is not that difficult to step through this code
line by line with the two sets of test values and work out what is
going wrong.</p>
</li>
<li>
<p>I could quite well be over-reacting. After all, we all have
off-days. However, I think it would be worthwhile to find out a bit
more about the student and not stop after completing a coding
criticsm.</p>
</li>
</ul>
</div>
</div>
<div class="sect2" lang="en">
<div class="titlepage">
<h3><a name="d0e412" id="d0e412"></a>From Neil
Youngman <tt class="email">&lt;<a href=
"mailto:ny@youngman.org.uk">ny@youngman.org.uk</a>&gt;</tt></h3>
</div>
<p>To start with the question as asked, the code does not always
find the lowest value because the value is only compared with its
neighbours, not with the lowest value found so far. Obviously this
can result in the value selected not always being the lowest.</p>
<p>Once this is fixed, I would expect the the program to work as
expected, provided the input is exactly as expected, but it may not
handle any unexpected variations in input gracefully and any
extensions, e.g. to handle a different number of inputs, will
require changes to the code.</p>
<p>After fixing the bug, I would start further improvements to the
code by providing a more flexible input mechanism that allows the
variable numbers of inputs. I would also break the program down
into functions that will handle the individual tasks, so I might as
well make this change by way of a new function, which I shall call
input_data. I have defined <tt class="varname">input_data</tt>
as:</p>
<pre class="programlisting">
std::vector&lt;int&gt; input_data(istream &amp;in) {
  std::vector&lt;int&gt; data;
  while(!in.eof() &amp;&amp; in.good()) {
    int val;
    in &gt;&gt; val;
    if(in.good()) {
      data.push_back(val);
    }
  }
  if(!in.eof()) {
    // We should only get here if there
    // has been an error on the stream
    cerr &lt;&lt; &quot;Input error reading data&quot;
         &lt;&lt; endl;
    exit(1);
  }
  return data;
}
</pre>
<p>[<i><span class="remark">Watch out here. This function contains
some pitfalls. For instance, what happens when EOF is right after
the last number? Is it pushed into the vector?
David</span></i>]</p>
<p>The first thing you should notice is that this function returns
a <tt class="classname">vector</tt> of <tt class="type">int</tt>s.
A <tt class="classname">vector</tt> is a structure provided the
standard template library, which is capable of handling a variable
number of elements. As <tt class="classname">vector</tt>s are
defined by templates they may be used to contain any type you
choose, in this case <tt class="type">int</tt>s. Bear in mind that
other list structures are available and a <tt class=
"classname">vector</tt> may not always be the best choice.</p>
<p>You may also notice that the input stream is left as a
parameter, so that the function may read data from any input
stream, e.g. a file, instead of being restricted to reading from
<tt class="classname">cin</tt>.</p>
<p>Also needed is a way of indicating that the end of input has
been reached. I have chosen to request an end of file character to
indicate the end of the list. Again, this is not the only possible
choice and a non technical audience may prefer something like
entering the word &quot;end&quot;, but this approach is simpler to code.</p>
<p>Another important point is that there was no error checking in
your existing code. This function checks for errors and exits when
there is an error on the stream. You should consider whether this
code should continue when an error has occurred, in which case it
will need some action to reset the stream to a good state before it
will be able to read further.</p>
<p>I have updated the prompts to read</p>
<pre class="programlisting">
cout &lt;&lt; &quot;This program will gather test &quot;
     &lt;&lt; &quot;scores and drop the lowest&quot; &lt;&lt; endl
     &lt;&lt; &quot;score, giving you the average of the &quot;
     &lt;&lt; &quot;remaining scores&quot; &lt;&lt; endl &lt;&lt; endl
     &lt;&lt; &quot;Please enter your test scores&quot; &lt;&lt; endl
     &lt;&lt; &quot;When all scores have been entered &quot;
     &lt;&lt; &quot;please terminate the list&quot; &lt;&lt; endl
     &lt;&lt; &quot;with an end of file character &quot;
     &lt;&lt; &quot;(^D in Unix, ^Z in Windows)&quot; &lt;&lt; endl;
</pre>
<p>It is important that when you modify a program, comments and
text shown to the user are updated to match. If this is not done at
the same time it will often be forgotten.</p>
<p>Many will argue that the use of endl for all line endings is
inefficient. I prefer to always use endl for consistency, unless a
program has a serious I/O performance problem.</p>
<p>The next task is to find the lowest value, which can be done by
a simple function, but rather than writing our own, we can see that
there is a suitable function already provided in the STL called
<tt class="classname">min_element</tt>, which we can use:</p>
<pre class="programlisting">
std::vector&lt;int&gt;::iterator lowest
   = min_element(data.begin(), data.end());
</pre>
<p>Similarly we can use the STL function <tt class=
"classname">accumulate</tt> to produce an initial sum. To avoid
confusion you really should not use the name &quot;average&quot; for the
initial sum, that's somewhat confusing and your other names are
similarly poorly chosen. I would suggest something like:</p>
<pre class="programlisting">
int sum = accumulate(data.begin(), data.end(), 0);
int adjusted_sum = sum - *lowest;
int result = adjusted_sum / (data.size()-1);
</pre>
<p>Other things I would change include changing <tt class=
"literal">using namespace std</tt> to using specific items from the
<tt class="literal">std</tt> namespace and declaring variables
where they are used instead of declaring them all at the start of
the function. This leaves the final program looking like:</p>
<pre class="programlisting">
#include &lt;vector&gt;
#include &lt;iostream&gt;
#include &lt;iomanip&gt;
#include &lt;algorithm&gt;
#include &lt;numeric&gt;
using std::istream;
using std::vector;
using std::cin;
using std::cout;
using std::cerr;
using std::endl;
std::vector&lt;int&gt; input_data(istream &amp;in) {
  std::vector&lt;int&gt; data;
  while(!in.eof()) {
    int val;
    in &gt;&gt; val;
    if(in.good()) {
      data.push_back(val);
    }
  }
  if(!in.eof()) {
    // We should only get here if there
    // has been an error on the stream
    cerr &lt;&lt; &quot;Input error reading data&quot; &lt;&lt; endl;
    exit(1);
  }
  return data;
}

int main() {
  cout &lt;&lt; &quot;This program will gather test &quot;
       &lt;&lt; &quot;scores and drop the lowest&quot; &lt;&lt; endl
       &lt;&lt; &quot;score, giving you the average of the &quot;
       &lt;&lt; &quot;remaining scores&quot; &lt;&lt; endl &lt;&lt; endl
       &lt;&lt; &quot;Please enter your test scores&quot; &lt;&lt; endl
       &lt;&lt; &quot;When all scores have been entered &quot;
       &lt;&lt; &quot;please terminate the list&quot; &lt;&lt; endl
       &lt;&lt; &quot;with an end of file character &quot;
       &lt;&lt; &quot;(^D in Unix, ^Z in Windows)&quot; &lt;&lt; endl;
  std::vector&lt;int&gt; data = input_data(cin);
  std::vector&lt;int&gt;::iterator lowest
       = min_element(data.begin(), data.end());
  int sum = accumulate(data.begin(), data.end(), 0);
  int adjusted_sum = sum - *lowest;
  int result = adjusted_sum / (data.size()-1);
  cout &lt;&lt; result &lt;&lt; endl;
  return 0;
}
</pre></div>
<div class="sect2" lang="en">
<div class="titlepage">
<h3><a name="d0e494" id="d0e494"></a>From Margaret
Wood <tt class="email">&lt;<a href=
"mailto:margaretwood@pocketmail.com.au">margaretwood@pocketmail.com.au</a>&gt;</tt></h3>
</div>
<p>I'm sure lots of people can tell you why the output of your
program depends on the order you enter the numbers, but I think it
will be more useful to help you work it out for yourself. You can
do this by looking at the values of the variables as you progress
through the code. Here is a modified version of your code, I have
added some more calls to <tt class="classname">cout</tt>, to show
the value of <tt class="varname">lowest</tt> after each
comparison.</p>
<pre class="programlisting">
#include &lt;iostream&gt;
#include &lt;iomanip&gt;
using namespace std;

int main() {
  int test1, test2, test3, test4, test5,
      average, averagescore, divide;
  cout &lt;&lt; &quot;This program will gather &quot;
       &lt;&lt; &quot;five test scores and\n&quot;;
  cout &lt;&lt; &quot;drop the lowest score, &quot;
       &lt;&lt; &quot;giving you the average\n&quot;;
  cout &lt;&lt; &quot;\n&quot;;
  cout &lt;&lt; &quot;Please enter Five Test scores\n&quot;;
  cin &gt;&gt; test1 &gt;&gt; test2 &gt;&gt; test3 &gt;&gt; test4 &gt;&gt; test5;
  cout &lt;&lt; endl;
  int lowest = test1;
  cout &lt;&lt; &quot;lowest is &quot; &lt;&lt; lowest &lt;&lt; endl;
          // test 1 is the lowest number unless
  if (test2 &lt; test1) lowest = test2;
          // test 2 is smaller than test 1 unless
  cout &lt;&lt; &quot;lowest is &quot; &lt;&lt; lowest &lt;&lt; endl;
          // test 3 is smaller than test 2 unless
  if (test3 &lt; test2) lowest = test3;
  cout &lt;&lt; &quot;lowest is &quot; &lt;&lt; lowest &lt;&lt; endl;
  if (test4 &lt; test3) lowest = test4;
          // test 4 is smaller than test 3 unless
  cout &lt;&lt; &quot;lowest is &quot; &lt;&lt; lowest &lt;&lt; endl;
  if (test5 &lt; test4) lowest = test5;
          // test 5 is smaller than test 4.
  cout &lt;&lt; &quot;lowest is &quot; &lt;&lt; lowest &lt;&lt; endl;
  average = (test1 + test2 + test3 + test4 + test5);
        // all test scores averaged together
  averagescore = average - lowest;
        // average score minus the lowest grade
  divide = averagescore /4;
        // average grade is then divided by 4
  cout &lt;&lt; endl;
  cout &lt;&lt; divide &lt;&lt; endl;
        // final grade after division
  return 0;
}
</pre>
<p>If you run this version, with the values 80,84,60,100,90 it will
print out</p>
<pre class="programlisting">
lowest is 80
lowest is 80
lowest is 60
lowest is 60
lowest is 90
81
</pre>
<p>Why has lowest increased to 90? What was the program doing just
before the change? It was comparing <tt class="varname">test4</tt>
and <tt class="varname">test5</tt>. Since <tt class=
"varname">test5</tt> is smaller than <tt class="varname">test4</tt>
the value of <tt class="varname">lowest</tt> is reset to 90.
However you only want <tt class="varname">lowest</tt> to be reset
if the new value (test5) is smaller than <tt class=
"varname">lowest</tt>. Here is a modified version of your code
which should give the answer you want.</p>
<pre class="programlisting">
#include &lt;iostream&gt;
#include &lt;iomanip&gt;
using namespace std;
int main() {
  int test1, test2, test3, test4, test5,
      average, averagescore, divide;
  cout &lt;&lt; &quot;This program will gather &quot;
       &lt;&lt; &quot;five test scores and\n&quot;;
  cout &lt;&lt; &quot;drop the lowest score, &quot;
       &lt;&lt; &quot;giving you the average\n&quot;;
  cout &lt;&lt; &quot;\n&quot;;
  cout &lt;&lt; &quot;Please enter Five Test scores\n&quot;;
  cin &gt;&gt; test1 &gt;&gt; test2 &gt;&gt; test3 &gt;&gt; test4 &gt;&gt; test5;
  cout &lt;&lt; endl;
  int lowest = test1;
        // test 1 is the lowest number unless
  if (test2 &lt; lowest) lowest = test2;
        // test 2 is smaller than test 1 unless
  if (test3 &lt; lowest) lowest = test3;
        // test 3 is smaller than test 2 unless
  if (test4 &lt; lowest) lowest = test4;
        // test 4 is smaller than test 3 unless
  if (test5 &lt; lowest) lowest = test5;
        // test 5 is smaller than test 4.
  average = (test1 + test2 + test3 + test4 + test5);
        // all test scores averaged together
  averagescore = average - lowest;
        // average score minus the lowest grade
  divide = averagescore /4;
        // average grade is then divided by 4
  cout &lt;&lt; divide &lt;&lt; endl;
        // final grade after division
  return 0;
}
</pre>
<p>Now I would like to mention a few other things I noticed while
looking at your code.</p>
<p>Some of the variable names are misleading. The variable you call
<tt class="varname">average</tt> is in fact the total, <tt class=
"varname">averagescore</tt> is a modified total - perhaps you could
call it <tt class="varname">modTotal</tt> - and <tt class=
"varname">divide</tt> is the average.</p>
<p>I'm not sure why you have included <tt class=
"filename">iomanip</tt> - the code works without it.
[<i><span class="remark">Maybe he thought (mistakenly) it would be
needed by std::endl. David</span></i>]</p>
<p>If this was my code I would calculate the average as a
<tt class="type">float</tt>. For the 5 numbers you entered the
average is in fact 88.5, so presenting 88 as your answer is fair
enough, but if you had chosen say, 80, 84, 60, 91, 100, the average
would be 88.75 and in many circumstances it would be better to
round the answer up to 89. However I don't know the precise details
of the problem you were asked to solve, so let's leave it as it is
for now.</p>
<p>Finally I'd like to look at some ways of making your code more
versatile. At the moment it requires exactly 5 inputs, it is
relatively simple to make it work with any number of scores greater
than one.</p>
<pre class="programlisting">
#include &lt;iostream&gt;
using namespace std;

int main() {
  int inValue, total, lowest, count, average;
  cout &lt;&lt; &quot;This program will gather two &quot;
          &quot;or more test scores and\n&quot;;
  cout &lt;&lt; &quot;drop the lowest score, giving &quot;
          &quot;you the average\n&quot; &lt;&lt; &quot;\n&quot;;
  cout &lt;&lt; &quot;Please enter at least two test scores\n&quot;;
  cout &lt;&lt; &quot;End your input with a single full stop\n&quot;;
  cin &gt;&gt; inValue;
  lowest = inValue;
  total = inValue;
  count = 1;
  while(cin &gt;&gt; inValue) {
    ++count;
    total += inValue;
    if(inValue &lt; lowest) lowest = inValue;
  }
  if (count &lt; 2) {
    cout &lt;&lt; &quot;This program requires at least &quot;
         &lt;&lt; &quot;two values&quot; &lt;&lt; endl;
  } else {
    average = (total - lowest)/(count-1);
    cout &lt;&lt; average &lt;&lt; endl;
  } 
  return 0;
}
</pre>
<p>Just one more improvement to go! In real life you may not have a
user typing data in at the prompt - it may have come from a
database, spreadsheet or a special user interface. So let's make
your program into a function that returns the answer to whatever
called it. We will assume that the calling program has already put
the values into a <tt class="classname">vector</tt>.</p>
<pre class="programlisting">
#include &lt;iostream&gt;
#include &lt;vector&gt;
using namespace std;

int myAverage(vector&lt;int&gt; values) {
  int total, lowest, average;
  total = 0;
  lowest = values[0];
  for(vector&lt;int&gt;::iterator it = values.begin();
      it != values.end(); ++it) {
    total += *it;
    if(*it &lt; lowest) lowest = *it;
  }
  average = (total - lowest)/(values.size()-1);
  return average;
}
</pre></div>
<div class="sect2" lang="en">
<div class="titlepage">
<h3><a name="d0e578" id="d0e578"></a>From Nevin Liber
<tt class="email">&lt;<a href=
"mailto:nevin@eviloverlord.com">nevin@eviloverlord.com</a>&gt;</tt></h3>
</div>
<p>The question as stated is slightly wrong. Here is the
correction:</p>
<pre class="programlisting">
80 84 60 100 90 ==&gt; 81 (incorrect!)
80 84 100 60 90 ==&gt; 88 (correct)
</pre>
<p>[<i><span class="remark">Good, you verified the student's
statement, which was probably a typo. David</span></i>]</p>
<p><span class="bold"><b>Improvement #1: Fix the bug</b></span></p>
<p>The bug is in the if statements: instead of comparing adjacent
test scores, each test score should be compared against lowest. The
corrected code:</p>
<pre class="programlisting">
#include &lt;iostream&gt;
using namespace std;

int main() {
  int test1, test2, test3, test4, test5,
      average, averagescore, divide;
  cout &lt;&lt; &quot;This program will gather five &quot;
       &lt;&lt; &quot;test scores and\n&quot;;
  cout &lt;&lt; &quot;drop the lowest score, giving &quot;
          &quot;you the average\n&quot; &lt;&lt; &quot;\n&quot;;
  cout &lt;&lt; &quot;Please enter Five Test scores\n&quot;;
  cin &gt;&gt; test1 &gt;&gt; test2 &gt;&gt; test3 &gt;&gt; test4 &gt;&gt; test5;
  int lowest = test1;
  if (test2 &lt; lowest) lowest = test2;
  if (test3 &lt; lowest) lowest = test3;
  if (test4 &lt; lowest) lowest = test4;
  if (test5 &lt; lowest) lowest = test5;
  average = (test1 + test2 + test3 + test4 + test5);
       // all test scores averaged together
  averagescore = average - lowest;
       // average score minus the lowest grade
  divide = averagescore /4;
       // average grade is then divided by 4
  cout &lt;&lt; divide&lt;&lt; endl;
       // final grade after division
  return 0;
}
</pre>
<p><span class="bold"><b>Style:</b></span> not bad, actually. Only
a few minor nits.</p>
<div class="orderedlist">
<ol type="1">
<li>
<p>Don't include <tt class="filename">iomanip</tt>, since nothing
in it is being used.</p>
</li>
<li>
<p>Be more consistent with whitespace.</p>
</li>
<li>
<p>Each variable declaration should be on a separate line.</p>
</li>
<li>
<p>Each variable declaration should be as close to its use as
possible.</p>
</li>
<li>
<p>Put curly braces around the statements inside <tt class=
"literal">if</tt>s.</p>
</li>
<li>
<p>Pick better variable names (eg: <tt class="varname">average</tt>
should really be <tt class="varname">sum</tt> or <tt class=
"varname">total</tt>). Note: Since I am trying to build upon the
student's solution, I will not be changing his variable names even
when I know that they aren't quite accurate.</p>
</li>
</ol>
</div>
<p><span class="bold"><b>Design:</b></span> once the bug is fixed,
his code gets the job done, albeit in a brute force sort of
way.</p>
<p><span class="bold"><b>Extensibility:</b></span> here is the real
shortcoming of this code. The number of test scores is fixed at 5.
The number of scores we drop is fixed at 1. We can, of course, do
better.</p>
<p><span class="bold"><b>Improvement #2: Variable number of test
scores</b></span></p>
<p>When I first read this problem, it screamed out to me that we
should be using algorithms over a collection of test scores.
Without changing the structure of the original solution too much, I
came up with:</p>
<pre class="programlisting">
#include &lt;algorithm&gt; // for std::min_element
#include &lt;deque&gt;
#include &lt;iostream&gt;
#include &lt;iterator&gt;  // for std::distance
#include &lt;numeric&gt;   // for std::accumulate
typedef std::deque&lt;int&gt; Scores;
int AverageTestScore(Scores::iterator first,
                     Scores::iterator last) {
  int lowest = *std::min_element(first, last);
  int average = 0;
  average = std::accumulate(first, last, average);
  int averagescore = average - lowest;
  int divide = averagescore
                 / (std::distance(first, last) - 1);
  return divide;
}
int main() {
  std::cout &lt;&lt; &quot;This program will gather test scores &quot;
       &lt;&lt; &quot;and\ndrop the lowest score, giving you &quot;
       &lt;&lt; &quot;the average\n\nPlease enter Test scores, &quot;
       &lt;&lt; &quot;followed by \&quot;end\&quot;&quot; &lt;&lt; std::endl;
  // store all the ints in cin into scores
  Scores scores;
  int test;
  while(std::cin &gt;&gt; test) {
    scores.push_back(test);
  }
  // Need at least two elements for this calculation
  if(1 &lt; scores.size()) {
    int divide = AverageTestScore(scores.begin(),
                                  scores.end());
    std::cout &lt;&lt; divide &lt;&lt; std::endl;
  }
  else {
    std::cerr &lt;&lt; &quot;The number of scores needed is &quot;
         &lt;&lt; &quot;at least 2; you only entered &quot;
         &lt;&lt; scores.size() &lt;&lt; std::endl;
    return 1;
  }
  return 0;
}
</pre>
<p><span class="bold"><b>Highlights:</b></span></p>
<div class="orderedlist">
<ol type="1">
<li>
<p>I use a <tt class="classname">deque</tt> to store the elements.
I could have just as easily used a <tt class=
"classname">vector</tt> or even a <tt class="classname">list</tt>.
It is hard to make the tradeoffs between them without running this
on real data and profiling.</p>
</li>
<li>
<p>Unlike the original solution, there is now a potential error
condition when too few scores are given to perform the calculation.
I had to add code to handle this situation.</p>
</li>
<li>
<p>I use the <tt class="classname">min_element</tt> algorithm to
get the lowest score. Since I know there are at least two elements
in <tt class="varname">scores</tt>, I also know that I can legally
dereference the iterator returned from <tt class=
"varname">min_element</tt>.</p>
</li>
<li>
<p>I use <tt class="classname">accumulate</tt> to calculate the
<tt class="varname">average</tt>. A better variable name would have
been <tt class="varname">sum</tt> or <tt class=
"varname">total</tt>, but I was trying to keep this as close to the
original solution as possible.</p>
</li>
<li>
<p>Both <tt class="classname">min_element</tt> and <tt class=
"classname">accumulate</tt> do not modify the collection, and they
are &quot;linear&quot; (O(N)) algorithms.</p>
</li>
<li>
<p>Since there are at least two elements in <tt class=
"varname">scores</tt>, the division performed in <tt class=
"varname">divide</tt> will never result in a divide by 0 error.</p>
</li>
</ol>
</div>
<p><span class="bold"><b>Improvement #3: Variable number of low
scores dropped</b></span></p>
<p>In order to do this, we need to sort the scores. There are a
variety of different ways to do this. We could store them in a
<tt class="classname">multiset</tt>. We could sort the entire
collection. But this is overkill (in the sense of greater than
linear time algorithms, such as Nlog(N)), as we don't need to sort
the entire collection; we just need to group the low scores away
from the high scores.</p>
<p>And there just happens to be an algorithm which does what we
want: <tt class="function">nth_element(...)</tt>. What it does is
put the nth element in the correct position as if the whole thing
were sorted, and all the elements before the nth position are &lt;=
the nth element, and all the elements after the nth position are
&gt;= the nth element. Plus, <tt class=
"function">nth_element(...)</tt> runs in linear time on average.
However, <tt class="function">nth_element(...)</tt> requires random
access iterators, thus limiting the collection types to <tt class=
"classname">vector</tt> or <tt class="classname">deque</tt>, but
not <tt class="classname">list</tt>.</p>
<pre class="programlisting">
#include &lt;algorithm&gt; // for std::nth_element
#include &lt;stdlib.h&gt;  // for exit
#include &lt;deque&gt;
#include &lt;iostream&gt;
#include &lt;numeric&gt;   // for std::accumulate
typedef std::deque&lt;int&gt; Scores;

int NonnegativeIntFromCin() {
  int value;
  if(!(std::cin &gt;&gt; value) || value &lt; 0) {
    std::cerr &lt;&lt; &quot;Next time, please enter a &quot;
         &lt;&lt; &quot;non-negative integer&quot; &lt;&lt; std::endl;
    exit(1);
  }
  return value;
}
int AverageTestScore(Scores::iterator first,
      Scores::iterator low, Scores::iterator last) {
  // Put the lowest test scores in [first, low) 
  std::nth_element(first, low, last);
  // Sum all the high [low, last) test scores
  int averagescore = 0;
  averagescore = std::accumulate(low, last,
                                 averagescore);
  int divide = averagescore / (last - low);
  return divide;
}
int main() {
  // Enter the number of low test scores to drop
  std::cout &lt;&lt; &quot;This program will gather test scores &quot;
       &lt;&lt; &quot;and\ndrop the lowest score, giving you &quot;
       &lt;&lt; &quot;the average\n\nPlease enter the number of &quot;
       &lt;&lt; &quot;low Test scores to drop&quot; &lt;&lt; std::endl;
  int lowdropped = NonnegativeIntFromCin();
  // enter the test scores
  std::cout &lt;&lt; &quot;Please enter Test scores, followed &quot;
       &lt;&lt; &quot;by \&quot;end\&quot;&quot;&lt;&lt; std::endl;
  Scores scores;
  int test;
  while(std::cin &gt;&gt; test) {
    scores.push_back(test);
  }
  // need at least 1 more score than number dropped
  if(lowdropped &lt; scores.size()) {
    int divide = AverageTestScore(scores.begin(),
         scores.begin() + lowdropped, scores.end());
    std::cout &lt;&lt; divide &lt;&lt; std::endl;
  }
  else {
    std::cerr &lt;&lt; &quot;The number of scores needed is &quot;
         &lt;&lt; &quot;at least &quot; &lt;&lt; lowdropped + 1
         &lt;&lt; &quot;; you only entered &quot; &lt;&lt; scores.size()
         &lt;&lt; std::endl;
    return 1;
  }
  return 0;
}
</pre>
<p>The original functionality can be gotten by calling:</p>
<pre class="programlisting">
AverageTestScore(scores.begin(),
                 scores.begin() + 1, scores.end());
</pre>
<p><span class="bold"><b>Improvement #4: Variable number of high
scores dropped</b></span></p>
<p>That is another predictable extension, and it isn't hard to add.
Basically, do the <tt class="function">nth_element(...)</tt> trick
on the high side of the collection as well, taking care not to
resort the lowest scores.</p>
<pre class="programlisting">
#include &lt;algorithm&gt; // for std::nth_element
#include &lt;stdlib.h&gt;  // for exit
#include &lt;deque&gt;
#include &lt;iostream&gt;
#include &lt;numeric&gt;   // for std::accumulate
typedef std::deque&lt;int&gt; Scores;

int NonnegativeIntFromCin() {
  int value;
  if(!(std::cin &gt;&gt; value) || value &lt; 0) {
    std::cerr &lt;&lt; &quot;Next time, please enter a &quot;
         &lt;&lt; &quot;non-negative integer&quot; &lt;&lt; std::endl;
    exit(1);
  }
  return value;
}
int AverageTestScore(Scores::iterator first,
       Scores::iterator low, Scores::iterator high,
       Scores::iterator last) {
  // Put the lowest test scores in [first, low)
  std::nth_element(first, low, last);
  // Put the middle test scores in [low, high)
  std::nth_element(low, high, last);
  // Sum all the middle [low, high) test scores
  int averagescore = 0;
  averagescore
         = std::accumulate(low, high, averagescore);
  int divide = averagescore / (high - low);
  return divide;
}

int main() {
  // Enter the number of low test scores to drop
  std::cout &lt;&lt; &quot;This program will gather test &quot;
       &lt;&lt; &quot;scores and\ndrop the lowest score, &quot;
       &lt;&lt; &quot;giving you the average\n\nPlease enter &quot;
       &lt;&lt; &quot;the number of low Test scores to drop&quot;
       &lt;&lt; std::endl;
  int lowdropped = NonnegativeIntFromCin();
  // Enter the number of high test scores to drop
  std::cout &lt;&lt; &quot;Please enter the number of high &quot;
       &lt;&lt; &quot;Test scores to drop&quot; &lt;&lt; std::endl;
  int highdropped = NonnegativeIntFromCin();
  // enter the test scores
  std::cout &lt;&lt; &quot;Please enter Test scores, &quot;
       &lt;&lt; &quot;followed by \&quot;end\&quot;&quot; &lt;&lt; std::endl;
  Scores scores;
  int test;
  while(std::cin &gt;&gt; test) {
    scores.push_back(test);
  }
  // need at least 1 more score than number dropped
  if(lowdropped + highdropped &lt; scores.size()) {
    int divide = AverageTestScore(scores.begin(),
          scores.begin() + lowdropped,
          scores.end() - highdropped, scores.end()); 
    std::cout &lt;&lt; divide &lt;&lt; std::endl;
  }
  else {
    std::cerr &lt;&lt; &quot;The number of scores needed is &quot;
        &lt;&lt; &quot;at least &quot; &lt;&lt; lowdropped + highdropped + 1
        &lt;&lt; &quot;; you only entered &quot; &lt;&lt; scores.size()
        &lt;&lt; std::endl;
    return 1;
  }
  return 0;
}
</pre>
<p>The original functionality can be achieved by calling</p>
<pre class="programlisting">
AverageTestScore(scores.begin(), scores.begin() + 1,
                 scores.end(), scores.end());
</pre>
<p>As you can see, this isn't much different than my solution for
improvement #3. Since it didn't involve much extra engineering or
testing, I felt it was worth adding this functionality. Your
mileage may very.</p>
<p>At this point I am done. There are other ways to extend this
code (for instance, making <tt class=
"function">AverageTestScore</tt> a templated function instead of
hard coding its parameters); however, they tend to get in the way
of readability and understandability for a student first getting
started with the language (my target audience), and I'll leave
those as an exercise for the reader.</p>
</div>
<div class="sect2" lang="en">
<div class="titlepage">
<h3><a name="d0e771" id="d0e771"></a>From Chris Main
<tt class="email">&lt;<a href=
"mailto:chris@chrismain.uklinux.net">chris@chrismain.uklinux.net</a>&gt;</tt></h3>
</div>
<p>&quot;It's not fair!&quot;</p>
<p>Inspector Slack was dozing peacefully in his favourite armchair
after his Christmas dinner when he was interrupted by the familiar
and unmistakeable sound of his children bickering.</p>
<p>&quot;It's that computer game Sergeant Lake gave us for Christmas.
Joy scored 80, 84, 60, 100 and 90 and got a grade of 88. I scored
80, 84, 100, 60 and 90 and only got 81&quot;, complained Matthew.</p>
<p>&quot;Why is that unfair?&quot;</p>
<p>&quot;Because I got exactly the same scores, just in a different
order&quot;.</p>
<p>&quot;Just like those gloves I knitted for little Tommy Smith&quot;.</p>
<p>Slack ignored this remark from his house guest, a little old
lady knitting quietly in the corner, and proceeded to vent his fury
on his sergeant.</p>
<p>&quot;Lake! I told him that Open Source Software would be no good.
Bungling amateurs!&quot;.</p>
<p>&quot;Did you say Open Source, Inspector?&quot; inquired Miss Marple.
&quot;Doesn't that mean <span class="emphasis"><em>anyone</em></span>
can read the program? I should be most interested to see it, though
I don't suppose I shall understand it.&quot;</p>
<p>Before Slack had time even to think &quot;interfering old woman&quot;,
Matthew had downloaded the source code from the internet and built
it.</p>
<p>&quot;See. If I enter my scores it gives me 81, but if I enter Joy's
she gets 88.&quot;</p>
<p>&quot;Oh dear!&quot; exclaimed Miss Marple. &quot;Do we have to type in the
numbers every time we want to try it out?&quot;</p>
<p>&quot;I know,&quot; said Joy, &quot;let's turn it into a function that can use
any input stream. Then we can feed it test data in string streams
and the real thing from standard input&quot;.</p>
<p>The children typed away busily, setting up a test function that
used an <tt class="function">assert</tt> to check the result of
calculating a grade. With this rearrangement they could easily add
other test cases too:</p>
<pre class="programlisting">
namespace {
  int CalculateGrade(istream &amp;stream) { ... }
  struct TestCase {
    const char *scores;
    int grade; 
  };
  void CheckCalculateGrade(const TestCase &amp;testCase) {
    istringstream stream(testCase.scores);
    assert(CalculateGrade(stream) == testCase.grade);
  }
  void TestCalculateGrade() {
    const TestCase testCases[]
      = { { &quot;80 84 60 100 90&quot;, 88 },
          { &quot;80 84 100 60 90&quot;, 88 } };
    const unsigned count
      = sizeof(testCases)/sizeof(testCases[0]);
    for_each(testCases, testCases+count,
             CheckCalculateGrade);
  }
}
int main() {
  TestCalculateGrade();
  cout &lt;&lt; &quot;This program will gather five test &quot;
       &lt;&lt; &quot;scores and\n&quot;;
  cout &lt;&lt; &quot;drop the lowest score, giving you the &quot;
       &lt;&lt; &quot;average\n&quot; &lt;&lt; &quot;\n&quot;;
  cout &lt;&lt; &quot;Please enter Five Test scores\n&quot;;
  cout &lt;&lt; CalculateGrade(cin) &lt;&lt; endl;
  return 0;
}
</pre>
<p>When they tried it out, it duly reported an assert failure.</p>
<p>&quot;How thoughtful,&quot; said Miss Marple with approval, &quot;the program
prints out what it is supposed to do. Do all programs do that?&quot;</p>
<p>&quot;Sadly not,&quot; sighed Matthew.</p>
<p>&quot;It should really only be output when a command line option such
as <tt class="literal">/?</tt>, <tt class="literal">-h</tt> or
<tt class="literal">-help</tt> is set,&quot; added Inspector Slack with
a punctilious air of authority.</p>
<p>&quot;Dear me, my eyesight is poor these days, I seem to be seeing
double looking at this program,&quot; fussed the old lady as she
adjusted her spectacles.</p>
<p>&quot;It's not your eyes,&quot; replied Joy, &quot;it's just that every line
has a comment repeating what the previous line does.&quot;</p>
<p>&quot;Well, my dears, let's get rid of all that. There's absolutely
no point in stating the obvious.&quot;</p>
<p>Slack bristled as he felt sure that Miss Marple had glanced
knowingly at him when making this last point, but now she was again
scrutinizing the code with an expression of sweetness and innocence
on her face.</p>
<p>&quot;Ah, that's much clearer. Now, surely what is named an
<tt class="varname">average</tt> is really a sum, and what is
called <tt class="varname">divide</tt> is actually the
average.&quot;</p>
<p>Matthew reworked the code. &quot;You always manage to work out which
people aren't who they say they are. I bet that fixes it.&quot; He ran
the program, but it still failed. Slack allowed himself a smile of
satisfaction; this problem demanded professional detection
skills.</p>
<p>&quot;I thought these computers were supposed to make tasks easier,
but I notice you still have to add up the test scores in one big
sum,&quot; observed Miss Marple.</p>
<p>&quot;We could use <tt class="classname">std::accumulate</tt>
instead,&quot; answered Joy, &quot;but we have to put the scores in a
container first, like a <tt class="classname">vector</tt>.&quot; Miss
Marple wasn't quite sure what a <tt class="classname">vector</tt>
was. Her nephew Raymond West had once taken her for a very fast
drive in his sports car which she was sure was called a <tt class=
"classname">Vector</tt>. With this fond memory she encouraged Joy
to make the change. From this it became apparent that the number 5
would make a useful constant for the input loop, and could be used
in the average calculation.</p>
<p>&quot;Such a pity,&quot; muttered Miss Marple as she considered the
simplicity of the <tt class="classname">accumulate</tt>
statement.</p>
<p>&quot;What's a pity?&quot; asked Matthew.</p>
<p>&quot;I was thinking, if only there were a nice function already
available for finding the lowest value, similar to accumulate for
finding the sum&quot;.</p>
<p>&quot;But there is, it's called <tt class=
"function">std::min_element</tt>.&quot; Matthew replaced all the
<tt class="literal">if</tt> statements with <tt class=
"function">min_element</tt>. The first attempt failed to compile,
then he remembered it returned an iterator rather than a value.
After de-referencing it the code built. Even better, the tests ran
successfully too.</p>
<p>&quot;I've got it!&quot; cried Inspector Slack, who had been working
feverishly with pencil and paper.</p>
<p>&quot;It's okay, Dad, Miss Marple's already fixed it,&quot; Joy informed
him.</p>
<p>Crestfallen, Slack looked at their code:</p>
<pre class="programlisting">
namespace {
  const int scoreCount = 5;
  int CalculateGrade(std::istream &amp;stream) {
    vector&lt;int&gt; scores;
    for(unsigned n = 0U; n != scoreCount; ++n) {
      int score;
      stream &gt;&gt; score;
      scores.push_back(score);
    }
    const int sum = accumulate(scores.begin(),
                               scores.end(), 0);
    const int lowest
       = *min_element(scores.begin(), scores.end());
    const int average = (sum-lowest) / (scoreCount-1);
    return average;
  }
}
</pre>
<p>&quot;Yes, but that doesn't explain why the original code didn't
work. You see, the <tt class="literal">if</tt> statements compare
each value to the previous value, when they should compare each
value to the current lowest value.&quot;</p>
<p>&quot;How clever of you, Inspector,&quot; said Miss Marple. Slack beamed
with pride.</p>
<p>&quot;However,&quot; she went on, &quot;it seems to me that the really
interesting question is <span class="emphasis"><em>why</em></span>
the mistake occurred. The programmer says in, now what did Joy call
them? oh, yes, in the comments that he is using 'the equation' to
drop the lowest number. He must have either been given the wrong
equation or, more likely, noted it down incorrectly. I remembered I
once made a mistake copying a knitting pattern from Mrs
McGillicuddy, and made a pair of gloves for little Tommy Smith
where the fingers came out in the wrong order.&quot;</p>
<p>Seeing the look of disappointment on the Inspector's face, and
feeling guilty for outwitting him whilst enjoying his hospitality,
she made a proposal. &quot;I should very much like to see one of your
magic tricks, Inspector, I do so enjoy them.&quot;</p>
<p>&quot;I've been working on sawing the lady in half. Perhaps you'd
like to lie down in that box over there while I fetch my saw,&quot;
suggested Slack, with just the slightest hint of menace.</p>
</div>
<div class="sect2" lang="en">
<div class="titlepage">
<h3><a name="d0e907" id="d0e907"></a>From Ian Glover
<tt class="email">&lt;<a href=
"mailto:ian@manicai.net">ian@manicai.net</a>&gt;</tt></h3>
</div>
<p>First the bug, the code above only works if the numbers after
the lowest value are in increasing order, so for instance 80, 84,
100, 60, 90 works because the sequence 60, 90 is increasing, but
80, 84, 60, 100, 90 does not as 60, 100, 90 is not an increasing
sequence (the problem description is the wrong way round it terms
of the output of these sequences). The simplest correction would be
not to compare each value in the series to the previous but to
compare it to the lowest found so far.</p>
<pre class="programlisting">
int lowest = test1;
     // test 1 is the lowest number unless 
if(test2 &lt; lowest) lowest = test2;
     // test 2 is smaller or
if(test3 &lt; lowest) lowest = test3;
     // test 3 is smaller or
if(test4 &lt; lowest) lowest = test4;
     // test 4 is smaller or
if(test5 &lt; lowest) lowest = test5;
     // test 5 is smaller.
</pre>
<p>While this fixes the bug it does leave some aspects still
wanting in the program.</p>
<p>To deal with some of the stylistic points first. The early
declarations of <tt class="varname">average</tt>, <tt class=
"varname">averagescore</tt> and <tt class="varname">divide</tt> are
unnecessary and should be shifted to where those variables are
first defined. It would also be worth changing the name of
<tt class="varname">average</tt> and <tt class=
"varname">averagescore</tt>, because the names do not match the
meanings, perhaps <tt class="varname">total</tt> and <tt class=
"varname">amendedtotal</tt> respectively; <tt class=
"varname">divide</tt> could then be renamed <tt class=
"varname">averagescore</tt> which gives a better sense of its
purpose. Another minor point is that the inclusion of <tt class=
"filename">iomanip</tt> is superfluous as nothing from this header
is used. Personally I would also prefer to use a single <tt class=
"classname">std::cout</tt> reference for the printed block at the
top, since this makes for fewer changes should we wish to send the
output to a different stream in future (though this is a more
marginal decision than the others).</p>
<p>A rather more major issue than those is the design of the
program in that it does not easily allow extension. As more tests
are added we would have to remember to update the code in seven
places (the declaration of the test variables, the two references
to five tests in the printed text, the cin statement, the
comparison tests, the summation to produce the total score and the
division to produce the average). The solution to this is to use
one of the STL sequences to hold the scores.</p>
<p>While the initial thought might be to use <tt class=
"classname">std::vector</tt> or <tt class=
"classname">std::list</tt>, the arithmetic operations that we do on
the sequence suggest a better choice in the form of <tt class=
"classname">std::valarray</tt>. This has convenient methods
allowing us to find the minimum held value, the sum of the values
and the length which are the three pieces of information we use.
Implementing this change alters most of the program to produce
something like:</p>
<pre class="programlisting">
#include &lt;iostream&gt;
#include &lt;valarray&gt;

int main() {
  const size_t number_of_scores = 5;
  std::valarray&lt;int&gt; scores(number_of_scores);
  std::cout &lt;&lt; &quot;This program will gather &quot;
       &lt;&lt; scores.size() &lt;&lt; &quot; test scores and\n&quot;
       &lt;&lt; &quot;drop the lowest score giving you the &quot;
       &lt;&lt; &quot;average\n\n&quot;
            &lt;&lt; &quot;Please enter &quot; &lt;&lt; scores.size()
            &lt;&lt; &quot; test scores\n&quot;;
  for(size_t i = 0; i &lt; scores.size(); ++i) {
    std::cin &gt;&gt; scores[i];
  }
  int averagescore = (scores.sum() - scores.min())
                         / (scores.size() - 1);
  std::cout &lt;&lt; averagescore &lt;&lt; std::endl;
  return 0;
}
</pre>
<p>A couple of notes. As you can see I've changed things round so
that the number of scores is only set in one place and everything
after that checks the the valarray size. I've also got rid of the
intermediate variables for calculating the average as the method
names on valarray express what the intent of the formula
accurately.</p>
</div>
<div class="sect2" lang="en">
<div class="titlepage">
<h3><a name="d0e970" id="d0e970"></a>From Andrew
Marlow <tt class="email">&lt;<a href=
"mailto:andrew@marlowa.plus.com">andrew@marlowa.plus.com</a>&gt;</tt></h3>
</div>
<p>The code is very close to working. There are two bugs: the first
bug is in the code to calculate lowest. The code needs to compare
successive grade results with the current v</p>
<p><strong>Notes:</strong>&nbsp;</p>
<p><em>More fields may be available via dynamicdata ..</em></p>
</div>
</channel>
</rss>
