    <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  :: If your going to use it, learn it!</title>
        <link>https://members.accu.org/index.php/articles/932</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">Programming Topics + CVu Journal Vol 11, #6 - Oct 1999</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/c13/">Topics</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c65/">Programming</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/c129/">116</a>
<br />

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

                    -                        <a href="https://members.accu.org/index.php/articles/c65+129/">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;If your going to use it, learn it!</h1>
<p><strong>Author:</strong>&nbsp;</p>
<p>
<strong>Date:</strong> 03 October 1999 13:15:33 +01:00 or Sun, 03 October 1999 13:15:33 +01: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>I was recently asked if I could spot why this code was causing
some &quot;weird&quot; results. The code is intended to parse the following
configuration file:</p>
<pre class="literallayout">
#BOT USERINFO FILE 
#A # means a comment to the end of the line.
#As many entries as you wish can be added by editing this file.
#Format is: 
#&quot;&lt;bot number&gt; &lt;bot name&gt; &lt;bot model&gt; &lt;bot shirt color&gt; &lt;bot pants color&gt;&quot;
bot1 Onna onna 30 6
bot2 Hondo gordon 30 6
bot3 Dijmo gordon 30 6
bot4 Jack barney 150 150
bot5 Timmy gordon 30 6
bot6 Lisa femsci 30 6
bot7 Ryan barney 30 30
bot8 Johnny gordon 30 6
bot9 Jarvis gordon 30 6
bot10 Billy gordon 30 6
</pre>
<p>Which describes the attributes of some robots for a computer
game. The code is supposed to be in C++ however the author is
really a C programmer, and it was not really his choice to move to
C++. I would like to use this code for two things, the first is a
code review and critique of his approach, and the second is to look
at true C++ alternatives. So onto his code:</p>
<pre class="programlisting">
void SetNameByNum (char *name, char *model, char *top, char *btm) {
</pre>
<p>The function passes pointers to buffers defined elsewhere for
each of the attributes. A block of local variables are declared
next with assorted magic numbers appearing without
justification.</p>
<pre class="programlisting">
  char buffer;
  int charnum = 0;
  int norec;
  char filename[24];
  char bnumstr[4];
  char *readin = new char[8];
  char *comparer;
  FILE *f;
</pre>
<p>Next the file is opened with some error checking, which is not
ideal as the game dir is specified by the client and can typically
exceed the allocated space for filename.</p>
<pre class="programlisting">
  g_engfuncs.pfnGetGameDir(filename);
  sprintf(filename, &quot;%s\\bots.cfg&quot;, filename);
  f = fopen(filename, &quot;r&quot;);
  if (!f) return;
</pre>
<p>The next bit is the worst as it depends on the global variable
<tt class="varname">numbots</tt> and worst of all on a non-standard
function <tt class="function">_itoa</tt> (as the games code base is
commonly distributed on both Unix and Windows OS's).</p>
<pre class="programlisting">
  _itoa(numbots + 1, bnumstr, 10);
</pre>
<p>The next bit of code does the main parsing of the file. There
are several things that I don't like about this code, firstly the
way that the comments (in the data file) are handled with the
repeated tests on the variable <tt class="varname">norec</tt> and I
prefer conditional statements to be bracketed. I'm going to skip
the rest of the code and allow you to have a look, see if you can
spot the obvious mistakes.</p>
<pre class="programlisting">
  while (!feof(f)) {
    fscanf(f, &quot;%c&quot;, &amp;buffer);
    if (buffer == '#' &amp;&amp; norec != 1) norec = 1;

    if (buffer == '\n')   norec = 0;

    if (buffer == 'b' &amp;&amp; norec != 1) {     //Found what we want
      readin[charnum] = buffer;
      charnum++;
      fscanf(f, &quot;%c&quot;, &amp;buffer);
    }
    comparer = strstr(readin, bnumstr);
    if (comparer &amp;&amp; strcmp(comparer, bnumstr) == 0) {
      fscanf(f, &quot;%c&quot;, &amp;buffer);
      charnum = 0;
      while (buffer != ' ') {  name[charnum] = buffer; charnum++;  fscanf(f, &quot;%c&quot;, &amp;buffer);  }

      fscanf(f, &quot;%c&quot;, &amp;buffer);  charnum = 0;

      while (buffer != ' ') { model[charnum] = buffer; charnum++;   fscanf(f, &quot;%c&quot;, &amp;buffer); }

      fscanf(f, &quot;%c&quot;, &amp;buffer);  charnum = 0;

      while (buffer != ' ') { top[charnum] = buffer;  charnum++; fscanf(f, &quot;%c&quot;, &amp;buffer);  }

      fscanf(f, &quot;%c&quot;, &amp;buffer);  charnum = 0;

      while (buffer != '\n') {  btm[charnum] = buffer;  charnum++;   fscanf(f, &quot;%c&quot;, &amp;buffer);  }
      charnum = 0;
      break;
    }
    else {
      charnum = 0;
      while (buffer != '\n')  fscanf(f, &quot;%c&quot;, &amp;buffer);
    }
  }
}
  fclose(f);
}
</pre>
<p class="c2"><span class="remark">I seem to have a mismatch of
braces. Though I did a little reformatting I do not think that I
messed with the number of braces. I have also, in the interests of
space, altered the format of the author's code. Francis</span></p>
<p>Ok all done with their code, did you find the obvious top four
mistakes? Well just in case, here are my answers:</p>
<div class="itemizedlist">
<ul type="disc">
<li>
<p>None of the strings are nul ('\0') terminated once they have
been read in, this is the cause of the error the original coder was
having problems with.</p>
</li>
<li>
<p>There are potential buffer overruns all over the place.</p>
</li>
<li>
<p>Memory leaks, <tt class="literal">delete[] readin</tt> was
missing.</p>
</li>
<li>
<p>I'm never happy to see <tt class="function">fscanf</tt> used
where <tt class="function">fgetc</tt> or <tt class=
"function">fgets</tt> might be more appropriate.</p>
</li>
</ul>
</div>
<p>There are a number of other problems here too, such as coping
with extra whitespace, the <tt class="literal">break</tt> to exit
to <tt class="literal">while</tt> loop, and the fact that this code
re-reads the file for each new bot added. There are also a number
of stylistic issues too.</p>
<p>Now given that the game code base that this is taken from is
entirely C++ I feel that this problem should really have been
tackled using C++, besides the code you would produce is neater,
simpler and clearer, just the way I like code to be.</p>
<pre class="programlisting">
#include &lt;fstream&gt;
#include &lt;iostream&gt;
#include &lt;string&gt;
#include &lt;limits&gt;
const int max_bots = 10;

struct BotRecord {
  std::string bot;
  std::string name;
  std::string model;
  int top_colour;
  int bottom_colour;
};
BotRecord g_bot_records[max_bots]; 
int g_bot_count = 0;
bool ReadBotFile(const char* filename) {
  std::fstream in;
  // open the data file
  in.open(filename, std::ios::in);
  if (!in.is_open())   return false;
  // now set up the input stream
  std::istream in_stream(in);
  // read to end of file
  while(!in_stream.eof()) {
    // if its a comment
    if ((in_stream.peek() == '#') || (in_stream.peek() == '\n')) {
      // ignore to the next newline
      in_stream.ignore(std::numeric_limits&lt;int&gt;::max(), '\n');
    }
    else   {             // ok should be a bot config now
      in_stream &gt;&gt; g_bot_records[g_bot_count].bot;
      in_stream &gt;&gt; g_bot_records[g_bot_count].name;
      in_stream &gt;&gt; g_bot_records[g_bot_count].model;
      in_stream &gt;&gt; g_bot_records[g_bot_count].top_colour;
      in_stream &gt;&gt; g_bot_records[g_bot_count].bottom_colour;
      // now ignore the rest of the line
      in_stream.ignore(std::numeric_limits&lt;int&gt;::max(), '\n');
      // increment the bot count
      g_bot_count++;
    }
  }
  return true;
}
</pre>
<p>The above code is meant to be a simplified example, and I'd
suggest some improvements for any production code. I see no reason
to use arrays normally and only use one above as I know the size is
fixed, however I'd prefer a vector in almost all cases. So if you
are going to use C++, make a little effort to learn it, you will
save in the long run.</p>
<i><span class="remark">True, but I am not impressed by the
original coders C. I am also unimpressed by monolithic functions.
Anyone want to redesign this and rewrite the code? I think it might
be worth the effort.</span></i></div>
</p>
<p><strong>Notes:</strong>&nbsp;</p>
<p><em>More fields may be available via dynamicdata ..</em></p>
</div>
</channel>
</rss>
