    <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 13</title>
        <link>https://members.accu.org/index.php/articles/1141</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 13, #6 - Dec 2001</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/c117/">136</a>
<br />

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

                    -                        <a href="https://members.accu.org/index.php/articles/c183+117/">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 13</h1>
<p><strong>Author:</strong>&nbsp;</p>
<p>
<strong>Date:</strong> 03 December 2001 13:15:48 +00:00 or Mon, 03 December 2001 13:15:48 +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="d0e18" id="d0e18"></a></h2>
</div>
<p>prizes provided by Blackwells Bookshops &amp; Addison-Wesley</p>
<p class="c2"><span class="remark">Note that if anyone has not
received a promised prize they should contact me
(Francis.glassborow@ntlworld.com) so that I can see what has gone
wrong because I believe that I am now up to date.</span></p>
<p>I had a very small response to the last piece of code and that
worries me. The code had quite a bit that merited comment, so how
was it that so few of you entered? In fact I had to ask one of my
friends to provide a critique, though soon after he did so I had a
genuine entry.</p>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e27" id="d0e27"></a>Student code
Critique 12</h2>
</div>
<p>Let us start with the code:</p>
<pre class="programlisting">
// From Borland C++ 4.5 page 100 Demonstration 
// of loops using Newtons Method of finding 
// square roots
#include &lt;iostream.h&gt;
const double TOLERANCE = 1.0e-7;
double abs(double x) {
  return (x &gt;= 0) ? x : -x;
}
double sqroot(double x) {
  double guess = x /2;
  do {
    guess = (guess + x / guess) / 2;
  }while(abs(guess * guess - x ) &gt; TOLERANCE);
  return guess;
}
double getNumber() {
  double x;
  do {
    cout &lt;&lt; &quot;Enter a number:  &quot;;
    cin &gt;&gt; x;
  } while (x &lt; 0);
  return x;
}
main(){
  char c;
  double x, y;
  do {
    x = getNumber();
    y = sqroot(x);
    cout &lt;&lt; &quot;Sqrt (&quot;  &lt;&lt; x &lt;&lt;  &quot;) = &quot;
         &lt;&lt; y &lt;&lt; endl
      &lt;&lt; &quot;Enter another number?  (Y/N)  &quot;;
      cin &gt;&gt; c;
      cout &lt;&lt; endl;
  }  while (c == 'Y'  ||  c ==  'y' ) ;
  return 0;
}
</pre>
<div class="sect2" lang="en">
<div class="titlepage">
<h3><a name="d0e34" id="d0e34"></a>Some Comments</h3>
</div>
<div class="sect3" lang="en">
<div class="titlepage">
<h3><a name="d0e37" id="d0e37"></a>Walter
Milner<tt class="email">&lt; <a href=
"mailto:%20w.w.milner@bham.ac.uk">w.w.milner@bham.ac.uk</a>&gt;</tt></h4>
</div>
<p>I'm going for the 'most terse entry' prize -</p>
<div class="orderedlist">
<ol type="1">
<li>
<p>The comment - it is pedagogically unsound to use this to
demonstrate loops - there are far too many distracting issues it
raises</p>
</li>
<li>
<p>Globals should be avoided wherever possible - so make <tt class=
"constant">TOLERANCE</tt> local to <tt class=
"function">sqroot</tt></p>
</li>
<li>
<p>Prototype functions</p>
</li>
<li>
<p>Use <tt class="function">double abs(double)</tt> from
&lt;cmath&gt;</p>
</li>
<li>
<p>Use <tt class="literal">/ 2.0</tt> in <tt class=
"function">sqroot()</tt></p>
</li>
<li>
<p>Use <tt class="literal">x &lt; 0.0</tt> in <tt class=
"function">getNumber</tt></p>
</li>
<li>
<p>Trap <tt class="literal">x==0.0</tt> in <tt class=
"function">sqroot</tt> to avoid divide by zero if user enters 0</p>
</li>
<li>
<p>Declare <tt class="function">main</tt> as <tt class=
"function">int main(void)</tt></p>
</li>
<li>
<p>The student should compare this to <tt class=
"function">pow(double, double)</tt></p>
</li>
</ol>
</div>
<p class="c2"><span class="remark">I have no problem with terse
entries as long as they are substantially complete and correct. The
problem with Walter's submission is that he seems to have missed
that most of the code is floating point code (e.g. his choice of
abs instead of fabs(). He correctly tries to trap divide by zero
but his trap will not deal with the overflow potential in
C.)</span></p>
<p class="c2"><span class="remark">Oh, and prototypes are not
needed if the definition is visible at the time of use (i.e. the
definitions are in the same file and before the first call of that
function).</span></p>
<p class="c2"><span class="remark">Good try, but not enough to get
a free book.</span></p>
</div>
</div>
<div class="sect2" lang="en">
<div class="titlepage">
<h3><a name="d0e112" id="d0e112"></a>A Once Over by
The Harpist</h3>
</div>
<p>As Francis had very few entries for this competition he has
persuaded me to provide an entry. It is under the strict condition
that I must not be the winner. Some of my comments may be a little
unfair because I think the material was extracted from an older
book, however I am going to pretend for the sake of this review
that it was written yesterday. I will stick to my usual format of
working through the code as it was provided.</p>
<pre class="programlisting">
#include &lt;iostream.h&gt;
</pre>
<p>Well we can argue about this one. There is nothing wrong with
that as a header file as long as the author does not claim that it
is a Standard C++ header. It is not and never has been. The correct
header file for Standard C++ i/o is iostream (note: no '.h') which
places everything in namespace std. To keep things simple I will
assume that the actual first two lines were:</p>
<pre class="programlisting">
#include &lt;iostream&gt;
using namespace std;
</pre>
<p>There is nothing exactly wrong about this next line:</p>
<pre class="programlisting">
const double TOLERANCE = 1.0e-7;
</pre>
<p>but there are two things that I would do differently. I never
use identifiers that are devoid of lowercase letters if they are
not provided by the pre-processor (I never use lowercase letters in
preprocessor identifiers). I also try to stick firmly to writing
'const directly after the type being qualified. Neither of these
things is a major issue so do not waste time arguing about it.</p>
<pre class="programlisting">
double const tolerance = 1.0e-7;
</pre>
<p>However that tolerance seems somewhat generous if you are
computing with doubles. It also suffers from being an absolute
value which is hardly useful if you are calculating square roots of
smallish values. That is a serious fault because it makes a quite
unwarranted assumption.</p>
<p>This next function caused me considerable surprise. What is it
for? Yes I know what it does, but why has the author written it.
Only someone who was substantially ignorant of what the C Standard
Library provides would waste time writing something like thi
(particularly with a reserved name in C).</p>
<pre class="programlisting">
double abs(double x) {
  return (x &gt;= 0) ? x : -x;
}
</pre>
<p>So those three lines should be replaced by:</p>
<pre class="programlisting">
#include &lt;cmath&gt;
// Use double fabs(double) from the library
</pre>
<p>Now the next bit looks OK though we will have to patch it up to
handle the poor choice of the value for <tt class=
"constant">tolerance</tt> and to replace <tt class=
"function">abs</tt> with <tt class="function">fabs</tt>.</p>
<pre class="programlisting">
double sqroot(double x) {
</pre>
<p>Note that the writer assumes that x will be positive. We need to
add a line:</p>
<pre class="programlisting">
if(x &lt; 0) throw range_error(
&quot;cannot find square root of negative number&quot;)
</pre>
<p>Which means we will also need to add:</p>
<pre class="programlisting">
#include &lt;exception&gt;
  double guess = x/2;
</pre>
<p>and we better add something to mend that tolerance calculation
by scaling it to the actual value of x:</p>
<pre class="programlisting">
double const tolerance = ::tolerance*x;
</pre>
<p>Yes, you are right, I am being lazy and should really use
another name, but it reminds people of the way we can use a local
version of such a value which depends on the global one.</p>
<pre class="programlisting">
  do {
    guess = (guess + x / guess) / 2;
  }while(abs(guess * guess - x ) &gt; TOLERANCE);
</pre>
<p>Patching that line gives us:</p>
<pre class="programlisting">
} while (fabs(guess * guess - x) &gt; tolerance);
  return guess;
}
</pre>
<p>I assume that the rest of the code is a test harness to
demonstrate that the above function works. I hope that you hate
functions that continue for ever without giving you a hint that you
are not providing what you want. Imagine the poor user who enters
-1. It is a perfectly good number and nowhere has this function
stated that it only accepts positive floating point numbers.
Actually, I consider this sort of function the kind of utility
function that will handle the other kind of input error where the
user types something like &quot;minus one&quot;. Now the function can never
end.</p>
<pre class="programlisting">
double getNumber() {
  double x;
  do {
    cout &lt;&lt; &quot;Enter a number:  &quot;;
    cin &gt;&gt; x;
  } while (x &lt; 0);
  return x;
}
</pre>
<p>The above function should be replaced with something like:</p>
<pre class="programlisting">
double getdouble(char const * message){
  int retries 3;
  while(retries--){
    cout &lt;&lt; message ;
    cin &gt;&gt; x;
    if(!cin) {
      cout &lt;&lt; &quot;invalid input found \n&quot;;
      while(cin.get() != '\n');
      cin.clear();
    }
    else return x;
  }
  throw exception(&quot;repeated invalid input from console&quot;)
}
</pre>
<p>A bit more polish would be nice but the above should give you a
fair start.</p>
<pre class="programlisting">
main(){
  char c;
  double x, y;
  do {
    x = getNumber();
    y = sqroot(x);
    cout &lt;&lt; &quot;Sqrt (&quot;  &lt;&lt; x &lt;&lt;  &quot;) = &quot;
         &lt;&lt; y &lt;&lt; endl
      &lt;&lt; &quot;Enter another number?  (Y/N)  &quot;;
      cin &gt;&gt; c;
      cout &lt;&lt; endl;
  }  while (c == 'Y'  ||  c ==  'y' ) ;
  return 0;
}
</pre>
<p>Well this is what I would write to achieve more or less the
above test functionality. First we need an input function to deal
with the yes/no question and ensure the input stream is left in a
clean state:</p>
<pre class="programlisting">
bool yesno(char const * message)
  cout&lt;&lt; message;
  char c = cin.get();
// flush the input
  while(cin.get() != '\n');
  return(c=='Y' || c=='y');
}
int main (){ // note the original forgot 'int'
  try {
    do {
      double x = getdouble(
            &quot;Type in a positive number&quot;);
      if(x,0){
        cout&lt;&lt; &quot;A positive number,&quot;
            &lt;&lt; &quot; input ignored \n&quot;;
        continue;
      }
      double y = sqroot(x);
      cout &lt;&lt; &quot;Sqrt (&quot;  &lt;&lt; x &lt;&lt;  &quot;) = &quot;
           &lt;&lt; y &lt;&lt; endl;
    while (yesno(
        &quot;Enter another number? (Y/N): &quot;));
  }
  catch(exception e){ cout &lt;&lt; e.what(); }
  return 0;
}
</pre>
<p>There are quite a few rough edges in my code that could be
further smoothed. For example I have twice flushed the input
stream, it would be worth writing a simple inline function to do
this. However I think that this code is a great improvement on the
original though it does not take much more space.</p>
<p>I suspect the lack of entries to this competition is because
many did not see the faults. Training your eye to recognise poor
code is a valuable skill. If you did not see at least half the
flaws in the above code then you need to hone your code inspection
skills, you are too trusting of published code.</p>
</div>
<div class="sect2" lang="en">
<div class="titlepage">
<h3><a name="d0e194" id="d0e194"></a>The Winning
Critique by Catriona O'Connell</h3>
</div>
<div class="sect3" lang="en">
<div class="titlepage">
<h3><a name="d0e197" id="d0e197"></a>Set Option
NoVitriol.</h4>
</div>
<p>There are major and minor problems with the code as written.
When looking at the code I have tried to bear in mind the nature of
its presentation and what might be expected from an introductory
text.</p>
<p>The program doesn't start well when the old-style iostream.h
header file is used instead of the C++ standard header iostream.
The iostream.h header is really only provided for backwards
compatibility and most new code should be using the standard
headers. The contents of may be non-standard and non-conformant,
whereas iostream is portable and conformant. The iostream header
puts the definitions into the <tt class="literal">std</tt>
namespace whereas iostream.h puts them into the global
namespace.</p>
<p>The next problem is the definition of the <tt class=
"function">abs()</tt> function. The author could have used the
<tt class="function">fabs()</tt> function, but this would have
meant including math.h (to be consistent with his usage of
headers). To be fair, the mathematical functions may not have been
introduced at this stage so to avoid confusing the reader with
side-issues a simple <tt class="function">abs()</tt> function was
created. In general though, library functions should be used where
possible.</p>
<p>The other faults are:</p>
<div class="orderedlist">
<ol type="1">
<li>
<p>There are no function prototypes. The code relies on functions
being declared/defined before <tt class="function">main()</tt>.</p>
</li>
<li>
<p>There is little error checking. For example, the code will fail
with a divide by zero error if the square root of zero is
calculated.</p>
</li>
<li>
<p>The program will fail to meet the tolerance criteria if a very
large value is entered. Convergence criteria are always difficult
and generally require some thought.</p>
</li>
<li>
<p>A lack of comments - although these may have been incorporated
into the text of the book.</p>
</li>
</ol>
</div>
<p>On a stylistic note, the author uses two different methods for
retrieving input from the user, after a prompting message. The
<tt class="function">getNumber</tt> function and the <tt class=
"classname">cout</tt>/<tt class="classname">cin</tt> method. This
is clearly calling for refactoring and is a suitable candidate for
a template - although again in an introductory book this might be
considered too advanced. I do however feel that the author should
have implemented <tt class="function">getChar</tt> in this
instance.</p>
<p>The author's use of <tt class="classname">cin</tt> to retrieve
numbers and characters from the user may be problematic as no care
is taken to flush the input stream or remove extraneous newline
characters. The use of <tt class="methodname">cin.ignore()</tt>
might be overly complicated for that stage of the book.</p>
</div>
<div class="sect3" lang="en">
<div class="titlepage">
<h3><a name="d0e258" id="d0e258"></a>Notes on my
code:</h4>
</div>
<p>The VC++6 compiler does not add functions/values from climit or
cmath to the std namespace. Actually as most of the values in
climit are likely to be macros they would be added to the global
namespace. Although the MSDN documentation implies that the
contents of the c* headers are added to the <tt class=
"literal">std</tt> namespace, an attempt to use <tt class=
"function">std::fabs()</tt> will fail to compile. If you are using
a more conforming compiler then you may have to use <tt class=
"function">std::fabs</tt>. An alternative is to use <tt class=
"literal">using namespace std;</tt> so that we do not have to worry
about which functions are in <tt class="literal">std</tt> and which
are in global namespaces - but I receive the impression that this
is regarded as poor form. (<i><span class="remark">It sort of
depends where you place such directives</span></i>)</p>
<p>A template function to retrieve input from a user has been
implemented. This is my first attempt at using a template so there
may be implementation issues (like its position) that an expert
might like to comment on.</p>
<p>The <tt class="function">sqroot</tt> function has multiple
return points. While some programmers regard this as a bad thing, I
think it makes sense to implement early exit conditions separately
from the main code of the routine. While it could be rewritten
using nested condition checking, I believe that my form is
acceptable.</p>
<p>The <tt class="function">sqroot</tt> function implements a
return status through the <i class="parameter"><tt>ifail</tt></i>
parameter. Some readers may detect an exposure to the NAG library
philosophy here. I felt it was better to pass back a status rather
than rely on special return values from the main function.</p>
<p>The <tt class="function">sqroot</tt> function implements
convergence checking by using a ratio rather than an absolute
comparison of the difference between the calculated and required
values. I believe that this caters better then the original code
for a wider range of input. In production code, a number of
different convergence criteria may be required for different ranges
of input values.</p>
<p class="c2"><span class="remark">The whole of this column and
Catriona's code should be posted to our website. While I try not to
split articles, the existence of a centre page spread this time
means that I need to. You wil find the code for the next
competition on the last page of this issue.</span></p>
</div>
</div>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e304" id="d0e304"></a>Student Code
Critique Competition 13</h2>
</div>
<p>Set by Francis Glassborow</p>
<p>Prize provided by Blackwells Bookshop in co-operation with
Addison-Wesley</p>
<p>Entries in by January 14 (send to
francis.glassborow@ntlworld.com)</p>
<p>The following code is intended to work out the value of a
blackjack hand. There is a specific problem with counting the
number of aces. In addition there are numerous places where the
general structure of the code could be improved.</p>
<pre class="programlisting">
#include&lt;cctype&gt;
#include&lt;iostream&gt;
using namespace std;
int card_val(int card_no);
int number(int num_cards);
int ace_count(int&amp; aces);
int hand_value(int total, int aces);

int main(){
  int card_no, num_cards;
  char again;
  int total=0;
  int aces=0;
  cout&lt;&lt;&quot;\nWelcome to the &quot;
      &lt;&lt;&quot;Blackjack Counter.\n&quot;;
  do {
    num_cards=number(num_cards);
    for(card_no=1; card_no &lt;= num_cards; card_no++)
      total+=card_val(card_no);
    if(total&lt;=21) 
      cout&lt;&lt;&quot;\nYour hand is: &quot;&lt;&lt;total&lt;&lt;&quot;.&quot;;
    else { 
      total=hand_value(total, aces);
      if (total&lt;=21) 
        cout &lt;&lt;&quot;\nYour hand is:&quot;
            &lt;&lt;total&lt;&lt;&quot;.&quot;;
      else cout  &lt;&lt;&quot;\nYou busted with &quot;
              &lt;&lt;total&lt;&lt;&quot;!&quot;;
    }
    total=0;
    cout&lt;&lt;&quot;\nDo you wish to continue?&quot;;
    cout&lt;&lt;&quot;\nEnter 'Y' (Yes) or 'N' (No):  &quot;;
    cin&gt;&gt;again;
  } while ((again == 'Y') || (again == 'y'));
  return 0;
}
int number(int num_cards){
  do {
    cout&lt;&lt;&quot;\nHow many cards do you have?  &quot;;
    cin&gt;&gt; num_cards;
    if ((num_cards &lt;=1) || (num_cards &gt;=6))
      cout&lt;&lt;&quot;You must have between&quot;
          &lt;&lt; &quot; 2 and 5 cards (inclusive).&quot;;
  } while((num_cards &lt;=1) || (num_cards &gt;=6));
  return num_cards;
}
int card_val(int card_no){
  char card_val; 
  bool invalid_card;
  int value;
  int aces =0;
  do {
    invalid_card=false;
    cout&lt;&lt;&quot;Enter value of card number &quot;
        &lt;&lt;card_no&lt;&lt;&quot;: &quot;;
    cin&gt;&gt;card_val;
    switch (tolower(card_val)){
      case 'a': value=ace_card(aces); 
        break;
      case '2': value=2; 
        break;
      case '3': value=3; 
        break;
      case '4': value=4; 
        break;
      case '5': value=5; 
        break;
      case '6': value=6; 
        break;
      case '7': value=7; 
        break;
      case '8': value=8; 
        break;
      case '9': value=9;
        break
      case 't':value=10; 
        break;
      case 'j':value=10; 
        break;
      case 'q':value=10; 
        break;
      case 'k': value=10;
         break;
      default:
        cout&lt;&lt;&quot;\nNot a valid entry.&quot;
          &lt;&lt;&quot; Please try again.\n&quot;;
        invalid_card=true;
    }
  } while (invalid_card);
  return value;
}

int ace_count(int&amp; aces) {
  aces++;
  return 11;
}

int new_value (int total, int aces){
  while ((total&gt;21) &amp;&amp; (ace_count&gt;=1)) {
    aces--;
    total-=10;
  }
  return total;
}
</pre></div>
</p>
<p><strong>Notes:</strong>&nbsp;</p>
<p><em>More fields may be available via dynamicdata ..</em></p>
</div>
</channel>
</rss>
