    <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  :: Code Review</title>
        <link>http://accu.org/index.php/journals/905</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>


        <h2>Journal Articles</h2>


<div class="xar-mod-head"><span class="xar-mod-title">CVu Journal Vol 11, #5 - Aug 1999 + Student Code Critiques from CVu journal.</span></div>

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

                                            <a href="http://accu.org/index.php/journals/">All</a>

                     &gt;                         <a href="http://accu.org/index.php/journals/c76/">Journals</a>

                     &gt;                         <a href="http://accu.org/index.php/journals/c77/">CVu</a>

                     &gt;                         <a href="http://accu.org/index.php/journals/c130/">115</a>
                    (21)
<br />

                                            <a href="http://accu.org/index.php/journals/">All</a>

                     &gt;                         <a href="http://accu.org/index.php/journals/c184/">Journal Columns</a>

                     &gt;                         <a href="http://accu.org/index.php/journals/c183/">Code Critique</a>
                    (39)
<br />

                                            <a href="http://accu.org/index.php/journals/c130-183/">Any of these categories</a>

                    -                        <a href="http://accu.org/index.php/journals/c130+183/">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;Code Review</h1>
<p><strong>Author:</strong>&nbsp;Administrator</p>
<p>
<strong>Date:</strong> 06 August 1999 13:15:32 +01:00 or Fri, 06 August 1999 13:15:32 +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="d0e20" id="d0e20"></a></h2>
</div>
<p class="c2"><span class="remark">Last issue I published some
(non-working) novice code for you to review. I am delighted that
there were several responses. When I came to format them for
publication I found that several had no attached name. Please
ensure that when you email material as an attachment that you
include your name in the attached file.</span></p>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e25" id="d0e25"></a>First Review by
anon</h2>
</div>
<p>The specification clearly states that the most important thing
is to initially get the program working. So this will be phase 1.
Initially I will not worry about program structure, program style.
That will be Phase 2.</p>
<div class="sect2" lang="en">
<div class="titlepage">
<h3><a name="d0e30" id="d0e30"></a>Phase 1</h3>
</div>
<div class="orderedlist">
<ol type="1">
<li>
<p>couldn't get it to compile. The only non standard calls were
<tt class="function">getch()</tt> and <tt class=
"function">clrscr()</tt> so I removed those, and also removed the
<tt class="literal">#include&lt;conio.h&gt;</tt> and <tt class=
"literal">#include&lt;io.h&gt;</tt></p>
</li>
<li>
<p>main problem is that in <tt class="function">lasin()</tt> you
call <tt class="function">meny()</tt> (which I presume is
<tt class="function">menu()</tt>) from within the while loop. Hence
recursion - you never get to the <tt class="function">fclose()</tt>
at the end of <tt class="function">lasin()</tt>. You can see the
effect of this. If you enter the details for two people and then
look at the size of the <tt class="filename">fil.txt</tt> file you
find it probably contains only 40 bytes, enough for one person. So,
restructure the main menu loop: add an option to quit, and, for
now, break out of the while loop rather than calling <tt class=
"function">menu()</tt> and remove the call to <tt class=
"function">meny()</tt> from the bottom of <tt class=
"function">utskrift()</tt></p>
</li>
<li>
<p>Now no need for <tt class="function">menu()</tt> to be in a
function on its own so fold it into <tt class=
"function">main</tt>.</p>
</li>
<li>
<p>Recheck that if we enter details for two people <tt class=
"filename">fil.txt</tt> is 80 bytes. It is.</p>
</li>
<li>
<p>Why force the user to type in <tt class="filename">fil.txt</tt>
as the filename if it must be <tt class=
"filename">fil.txt</tt>?</p>
<p>This matters because we are probably going to have to run the
program quite a few times while testing. So hardwire <tt class=
"filename">fil.txt</tt> and remove the lines</p>
<pre class="programlisting">
      char namn[10];
      printf(...);           // prompt
      scanf(&quot;%s&quot;, namn);     // entry
</pre></li>
<li>
<p>Now we can concentrate on why the sorting isn't working. The
most obvious thing is that once again we have no <tt class=
"function">fclose()</tt> to match <tt class=
"function">fopen()</tt>, this time in <tt class=
"function">sortera()</tt>. So add that just before the call to
<tt class="function">utskrift()</tt> Rerun entering two people, and
it prints the three sets of details. So the problem is not just the
missing <tt class="function">fclose()</tt>. No way round it. have
to look at the logic of the code.</p>
</li>
<li>
<p>Looking at <tt class="function">sortera()</tt> the first thing I
notice is a <tt class="literal">for</tt>-loop that starts at one.
<span class="bold"><b>Klaxon klaxon warning warning</b></span>. 99%
of loops start at zero. I also notice that the second <tt class=
"literal">for</tt>-loop has a different test than the first one.
The First one is <tt class="literal">k&lt;storlek</tt>, the second
one is <tt class="literal">m&lt;=storlek</tt>. That doesn't look
too hopeful either. But apart from that the main problem is that
you are reading and writing to the same file, but opening the file
in read-only mode &quot;rb&quot;.</p>
</li>
<li>
<p>Fixed the two <tt class="literal">for</tt>-loops. Fixed the file
mode to &quot;r+b&quot;. Rerun. Still too much output. Perhaps that problem
is in the printing. Look at <tt class="function">utskrift()</tt>.
Once again a loop with while <tt class="literal">(n &lt;=
storlek)</tt> Try <tt class="literal">&lt;</tt> instead. Success.
Ok. Now lets see if the sorting is actually working. More input
tests. Try two numbers in the wrong order. Success.</p>
</li>
<li>
<p>Currently <tt class="function">lasin()</tt> will overwrite the
previous <tt class="filename">fil.txt</tt> file. I think <tt class=
"function">lasin()</tt> needs to append new people to <tt class=
"filename">fil.txt</tt> Change the <tt class="function">fopen</tt>
mode to &quot;a&quot;</p>
</li>
</ol>
</div>
</div>
<div class="sect2" lang="en">
<div class="titlepage">
<h3><a name="d0e180" id="d0e180"></a>Phase 2</h3>
</div>
<p>There may be bugs left but we're well on the road now. So I'm
going to turn to style. What can we do to improve the code without
radically changing the structure?</p>
<div class="orderedlist">
<ol type="1">
<li>
<p>The function prototypes are all missing void inside the
parentheses. Also there is no function called <tt class=
"function">avsluta()</tt> so we can remove the prototype for it.
And add the void to the function definitions too.</p>
</li>
<li>
<p>Inside <tt class="function">lasin()</tt> the <tt class=
"function">fseek</tt>'ing is not required. The <tt class=
"function">fwrite</tt>'s write sequentially anyway. So the variable
<tt class="varname">i</tt> is not required either. Note that inside
<tt class="function">utskrift()</tt> the fseek'ing is required.
This is because you have an <tt class="function">fseek()</tt>
before the first <tt class="function">fread()</tt>. This is just
one of those things you have to learn.</p>
</li>
<li>
<p>initialise <tt class="varname">my_fil</tt> at its declaration.
In <tt class="function">lasin()</tt>, <tt class=
"function">sortera()</tt> and <tt class="function">utskrift()</tt>.
Change it to <tt class="varname">my_file</tt> while we're at
it.</p>
</li>
<li>
<p>initialise <tt class="varname">sf</tt> at its declaration in
<tt class="function">sortera()</tt>. and make it <tt class=
"literal">const</tt>.</p>
</li>
<li>
<p>declare variables at their innermost scope.</p>
<div class="literallayout">
<p><tt class="varname">preg</tt> in <tt class=
"function">lasin()</tt><br>
<tt class="varname">pos1</tt>, <tt class="varname">pos2</tt>,
<tt class="varname">m</tt> in <tt class=
"function">sortera()</tt><br>
<tt class="varname">preg</tt> in <tt class=
"function">utskrift()</tt></p>
</div>
</li>
<li>
<p>There is duplication of the routine to calculate the size of the
file and divide it by the record size. Refactor this into a
function. Maybe later on look into using a POSIX function such as
<tt class="function">stat</tt>/<tt class="function">fstat</tt> to
find the file size in a more portable manner. Strictly speaking
<tt class="function">ftell()</tt> cannot be relied upon to do
this.</p>
</li>
<li>
<p>Change the <tt class="literal">while</tt>-loop in <tt class=
"function">utskrift()</tt> to a for-loop.</p>
</li>
<li>
<p>inside the menu we are using <tt class="function">printf</tt>
and <tt class="function">puts</tt> when we might as well just use
<tt class="function">puts</tt>. When we do this we must be careful
to remove the trailing \n from the old <tt class=
"function">printf</tt>'s. It is better to avoid variadic functions
if possible because there is no type checking on them.</p>
</li>
<li>
<p>we can create a bool typedef and use it in the menu. Makes the
code more declarative.</p>
</li>
<li>
<p>We can have separate options for sorting and displaying. We can
repeat the words register in each menu option</p>
</li>
<li>
<p>We can factor out the swapping of <span class=
"structname">perpost struct</span>s into a function</p>
</li>
<li>
<p>We can factor out writing a person to a particular record in a
binary file. We can factor out reading a person to a particular
record in a binary file</p>
</li>
<li>
<p>The author also wanted to separate out the last person as a
clean stop. I think the simplest solution is to indeed just do
that. To separate. Have an input that says &quot;another?&quot; and only if
you enter yes, are you promoted for the person's number.</p>
</li>
<li>
<p>Factor out writing a person to a text console Factor out reading
a person from a text console</p>
</li>
<li>
<p>Change other <tt class="function">printf</tt>'s to puts as
before.</p>
</li>
<li>
<p>Change the representation of <tt class="varname">pnumber</tt> to
an <tt class="type">int</tt>. Note that because of 21 and 23 we
have isolated the effect of this change We can also simplify the
comparison in <tt class="function">compare()</tt></p>
</li>
<li>
<p>It is better to use <tt class="function">fgets</tt> followed by
<tt class="function">sscanf</tt> rather than <tt class=
"function">scanf</tt>.</p>
</li>
</ol>
</div>
<p>This another of those tips you pick up eventually.</p>
<p>You could sort by slurping in all the records from the file into
a dynamic array, then sort in memory using <tt class=
"function">qsort()</tt>, then write them all back again. Splitting
the work across a few <tt class="filename">.h</tt> and <tt class=
"filename">.c</tt> files would be a good idea too. These last two
suggestions are left, as they say, as an exercise for the
reader.</p>
<pre class="programlisting">
#include &lt;ctype.h&gt;
#include &lt;stdio.h&gt;
#include &lt;string.h&gt;
#include &lt;stdlib.h&gt;
void input(void);
void sort(void);
void display(void);
typedef struct perspost perspost;
struct perspost {
  int pnumber;
  char forname[10];
  char lastname[15];
};

typedef enum { false, true } bool;
int main(void) {
  bool quit = false;
  
  do {
    char val_buffer[32];
    int val;
    puts(&quot;  MENU &quot;);
    puts(&quot;0......Quit&quot;);
    puts(&quot;1......Input people to register&quot;);
    puts(&quot;2......Sort the register&quot;);
    puts(&quot;3......Display the register&quot;);
    fputs(&quot;Val: &quot;, stdout);
  
    fgets(val_buffer, sizeof(val_buffer), stdin);
    sscanf(val_buffer, &quot;%d&quot;, &amp;val);
    switch (val) {
    case 0: quit = true;   break;
    case 1: input();       break;
    case 2: sort();        break;
    case 3: display();   break;
    }
  } 
  while (!quit);
  return 0;
}
//==============================
const char datafile[] = &quot;fil.txt&quot;;
void cwrite_person(const perspost * bod){
  printf(&quot;%d &quot;, bod-&gt;pnumber);  
  fputs(bod-&gt;forname, stdout);  
  fputs(&quot; &quot;, stdout);
  fputs(bod-&gt;lastname, stdout);
  putchar('\n');
}

void cread_person(perspost * bod) {
  char buffer[64];
  fputs(&quot;personnumner(personalnumber): &quot;, stdout);
  fgets(buffer, sizeof(buffer), stdin);
  sscanf(buffer, &quot;%d&quot;, &amp;bod-&gt;pnumber);
  
  fputs(&quot;Fornamn(forname): &quot;, stdout);
  fgets(buffer, sizeof(buffer), stdin);
  sscanf(buffer, &quot;%s&quot;, bod-&gt;forname);
  fputs(&quot;Efternamn(lastname): &quot;, stdout);
  fgets(buffer, sizeof(buffer), stdin);
  sscanf(buffer, &quot;%s&quot;, bod-&gt;lastname);
}

bool input_another(void){
  char buffer[32];
  fputs(&quot;Another person? (y/n) : &quot;, stdout);
  fgets(buffer, sizeof(buffer), stdin);
  return tolower(buffer[0]) == 'y';
}

void input(void) {
  FILE * my_file = fopen(datafile, &quot;ab&quot;);
  do {
    perspost bod;
    cread_person(&amp;bod);
    fwrite(&amp;bod, sizeof(bod), 1, my_file);
  }
  while (input_another());
  fclose(my_file);
}

int persons_in(FILE * src) {
  fseek(src, 0, SEEK_END);
  return ftell(src) / sizeof(perspost);
}

void swap_person(perspost * p1, perspost * p2) {
  perspost tmp = *p1;
  *p1 = *p2;
  *p2 = tmp;
}

void fwrite_person(const perspost * bod, int pos, FILE * dst) {
  fseek(dst, pos * sizeof(*bod), SEEK_SET);
  fwrite(bod, sizeof(*bod), 1, dst);
}

void fread_person(perspost * bod, int pos, FILE * src) {
  fseek(src, pos * sizeof(*bod), SEEK_SET);
  fread(bod, sizeof(*bod), 1, src);
}
//--------------------------------
void sort(void) {
  FILE * my_file = fopen(datafile, &quot;r+b&quot;);
  const int storlek = persons_in(my_file);
  int k;
  for (k = 0; k &lt; storlek; k++) {
    perspost pos1;
    int m;
    fread_person(&amp;pos1, k, my_file);
    for (m = k+1; m &lt; storlek; m++) {
      perspost pos2;
      fread_person(&amp;pos2, m, my_file);
      if (pos1.pnumber &gt; pos2.pnumber){
        swap_person(&amp;pos1, &amp;pos2);
        fwrite_person(&amp;pos1, k, my_file);
        fwrite_person(&amp;pos2, m, my_file);
      }
    }
  }
  fclose(my_file);
}

void display(void) {
  FILE * my_file = fopen(datafile, &quot;rb&quot;);
  const int storlek = persons_in(my_file);
  int n; 
  for (n = 0; n &lt; storlek; n++) {
    perspost bod;
    fread_person(&amp;bod, n, my_file);
    cwrite_person(&amp;bod);
  }
  puts(&quot;END\n\n&quot;);
}
</pre></div>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e374" id="d0e374"></a>Second Review
by anon</h2>
</div>
<p>My approach to the code presented in the Code Critique
Competition is intended to be as minimal as possible. I have tried
to explain why the code does not work and what needs to be done to
get it working with as few changes as possibly. I have specifically
avoided questions relating to the design of the program and to the
solution adopted by the author because I think it would be
unhelpful to talk about the use of qsort() or the finer points of
scanf() when the author is probably more interested in why his or
her code doesn't work the way it is written.</p>
<p>My initial concern with the problem as presented is that the
author does not seem to be clear about what he or she wants to do.
A certain amount of forethought is required before writing any
computer program and, if you can't express what you want to do
clearly in whatever your written language happens to be, you are
unlikely to be able to express it clearly in C. The first step is
to specify the problem precisely:</p>
<div class="blockquote">
<blockquote class="blockquote">
<p>'Write a program in C using the standard library as much as
possible to allow the user to enter information for a number of
people. The information consists of a personal number of up to 15
digits, a forename of up to 10 characters, and a last name of up to
15 characters. The personal number '0' is not valid but is used to
signal the end of input. The user should then be able to print a
list of personal information sorted by personal number. The
personal information should be sorted on-disk using a simple sort
algorithm and standard file I/O routines. The personal information
should be stored in a file named <tt class=
"filename">fil.txt</tt>.'</p>
</blockquote>
</div>
<p>Given the small size of the program, it is probably a good idea
to put this into the code as a comment.</p>
<p>The next step is to reformat the code to make it more readable.
This can be a very sensitive area involving endless debate about
such fascinating issues as where to put braces, how much to indent
by, and what naming convention to follow. The only rules that
everyone I know agree on are 'Use comments and blank lines to
divide your code into logical chunks' and 'Indent blocks of code
consistently'. In keeping with my minimalist approach, I have
attempted to follow the author's formatting and naming conventions
while making the code more readable<sup>[<a name="d0e391" href=
"#ftn.d0e391" id="d0e391">1</a>]</sup>.</p>
<p>After the code has been reformatted to make it more readable, it
is a good idea to get the data structures right. I have specified
the personal number as being 15 digits long but the structure as it
is defined in the code only allows for 14 digits. When declaring
character arrays in C, you must always reserve one space for the
null character at the end of a string. So the structure declaration
becomes:</p>
<pre class="programlisting">
#define S_PNUMBER 15
#define S_FORNAME 10
#define S_LASTNAME 15
struct t_perspost {
  char pnumber[S_PNUMBER+1];
  char forname[S_FORNAME+1];
  char lastname[S_LASTNAME+1];
  };
typedef struct t_perspost PERSPOST;
#define S_PERSPOST sizeof(PERSPOST)
</pre>
<p>Once this has been done, references to <span class=
"structname">perspost</span>' can be replaced with <span class=
"structname">PERSPOST</span>' which makes it clear that this is a
user-defined structure. References to <tt class=
"literal">sizeof(persoft)</tt>, <tt class=
"literal">sizeof(preg)</tt>, and <tt class="literal">sf</tt> can be
replaced with <tt class="literal">S_PERSPOST</tt> which is at least
consistent throughout the code.</p>
<p>Next we move on to the functions that make up the program.
<tt class="function">main()</tt> calls the function <tt class=
"function">meny()</tt> which displays a menu to the user. On return
from <tt class="function">meny()</tt>, however, there is a very
disconcerting call to <tt class="function">getch()</tt> which will
hang the program until the user remembers to hit enter. Presumably
the user has indicated his or her intention to exit the program
within the function <tt class="function">meny()</tt> so this call
can be removed.</p>
<p>The function <tt class="function">meny()</tt> displays a menu to
the user prompting him or her for an action. At present, the
function runs once and then drops through to return to main. It
might be better to allow the user to select several operations
before exiting and to provide an explicit option to exit the
program rather than just dumping him or her back at the system
prompt particularly if an invalid option is selected. This implies
some kind of menu loop that will prompt the user for an option
until a specified exit option is selected. I would also prefer to
see the selected option being read as a character rather than a
number because this allows the exit option to be given an obvious
mnemonic such as 'q' instead of having to assign it to '0' and
putting it first in the list or last in the list (which looks
awkward) or having to assign it to '3' and then changing the number
every time a new menu option is added. The modified <tt class=
"function">meny()</tt> is as follows:</p>
<pre class="programlisting">
// meny - user menu
void meny() {
int val;

do  {
  clrscr();
  printf(&quot; MENY&quot; );
  puts(&quot;&quot;);
  puts(&quot;&quot;);
  printf(&quot;1......Add people to the register\n&quot;);
  printf(&quot;2......Print\n&quot;);
  printf(&quot;&quot;q......Exit\n&quot;);
  printf(&quot;Val: &quot;);
  val = getch();
  switch(val) {
    case '1':  lasin();   break;
    case '2':  sortera(); break;
  }
} while( (val != 'q') &amp;&amp; (val != 'Q') );
return;
} // end meny
</pre>
<p>At this point I should note that the functions '<tt class=
"function">asin()</tt> and <tt class="function">utskrift()</tt>
both make calls to <tt class="function">meny()</tt>. I think that
the author's intention is to return to the main menu at these
points whereas what will actually happen is that a new menu will be
created recursively. These calls should be eliminated and the flow
of control should be allowed to return to the original menu.</p>
<p>The function <tt class="function">lasin()</tt> prompts the user
to enter a filename but, since the name <tt class=
"filename">fil.txt</tt> has been hard-coded into both <tt class=
"function">sortera()</tt> and <tt class="function">utskrift()</tt>,
I think it better to specify that the program will always work with
a file called <tt class="filename">fil.txt</tt> for the moment. An
extension to the specification might be to allow the user to work
with different files and to decide whether to enter the file name
on the command line or to prompt the user for a file name before
entering <tt class="function">meny()</tt> or to allow the user to
change the file name via a menu option but, as the program stands,
it can only work with a single file called <tt class=
"filename">fil.txt</tt>. The simplest solution is to use the
pre-processor to define <tt class="literal">REGISTER-FILE</tt> as
<tt class="filename">fil.txt</tt> and to get the program working
before adding bells and whistles. (It also gets rid of the rather
curious declaration of <tt class="varname">namn[]</tt> in
<tt class="function">lasin()</tt>. If this is a DOS program then
the length of <tt class="varname">namn[]</tt> must be at least 13
to hold an 8.3 format filename.)</p>
<p>At present, <tt class="function">lasin()</tt> opens the register
file using the mode &quot;wb&quot; which means that, every time the file is
opened, it will overwrite an existing file of the same name if one
exists. If the author intends to add more people to an existing
file, the correct mode is &quot;ab+&quot; which opens the file to append data
to the end if it exists or creates a new file if it does not. Given
that records can now be appended to the file using calls to
<tt class="function">fwrite()</tt>, we can eliminate the call to
<tt class="function">fseek()</tt> as the internal file positioning
is automatically taken care of by the standard library. It is also
a good idea to check return codes from standard library calls just
to make sure that nothing has gone wrong.</p>
<p>In order to determine whether the user has finished entering
personal details, the author converts the personal number into an
integer using <tt class="function">atoi()</tt> and compares this
value with zero. Since a personal number can consist of up to
fifteen digits and the behaviour of <tt class=
"function">atoi()</tt> is undefined if it is given a number that is
too big, this could lead to unexpected results. It would be better
to compare the personal number as a string with &quot;0&quot;.</p>
<p>The modified version of <tt class="function">lasin()</tt> looks
like this:</p>
<pre class="programlisting">
//. lasin - input and store personal information
void lasin(){
PERSPOST preg;
FILE *my_fil;
size_t n_written;

clrscr();
my_fil=fopen(REGISTER_FILE,&quot;ab+&quot;);
if ( my_fil ){
  do {
    printf(&quot;personnummer(personalnumber): &quot;);
    scanf(&quot;%s&quot;,preg.pnumber);
    if( strcmp( preg.pnumber, &quot;0&quot; ) != 0 ){
      printf(&quot;Fornamn(forname): &quot;);
      scanf(&quot;%s&quot;,preg.forname);
      printf(&quot;Efternamn(lastname:&quot;);
      scanf(&quot;%s&quot;,preg.lastname);

      n_written = fwrite(&amp;preg,S_PERSPOST,1,my_fil);
      if ( n_written != 1 ){
        printf( &quot;error: n_written %d\n&quot;,  
                      n_written );
        }
      }
    } while( strcmp( preg.pnumber, &quot;0&quot; ) != 0 );
  fclose(my_fil);
  }
return;
} // end lasin
</pre>
<p>In order to check that the file has been written correctly, it
would be useful to be able to print it out without trying to sort
it. For testing purposes, I added an extra option to the menu which
calls the function <tt class="function">utskrift()</tt> to print
the file directly to the screen. This function makes a lot of calls
to <tt class="function">fseek()</tt> that are not strictly
necessary because, after a call to <tt class=
"function">fread()</tt>, the file will be left ready to read the
next record. So the main loop of <tt class=
"function">utskrift()</tt> can be replaced by a loop which calls
<tt class="function">fread()</tt> until there is nothing more to
read:</p>
<pre class="programlisting">
// utskrift - print personal information
void utskrift(){
FILE *my_fil;
PERSPOST preg;

clrscr();
my_fil=fopen(REGISTER_FILE,&quot;rb&quot;);
if ( my_fil ){
  while(fread(&amp;preg,S_PERSPOST,1,my_fil)){
    printf(&quot;%s\n&quot;,preg.pnumber);
    printf(&quot;%s\n&quot;,preg.forname);
    printf(&quot;%s\n&quot;,preg.lastname);
    }
  fclose(my_fil);
  }
getch();
return;
} // end utskrift
</pre>
<p>Last of all there is <tt class="function">sortera()</tt> the
function that sorts the file. I am not certain which sorting
algorithm the author intended to use - a comment would have been
helpful - but I have decided to implement a selection sort which
scans through the file repeatedly, finds the smallest record, and
moves it to its correct position in the file.</p>
<p>The first problem with <tt class="function">sortera()</tt> is
that it opens the file in read-only mode. Since the intention is to
read and write the file, the correct mode in &quot;rb+&quot;. The function
then correctly determines the number of records in the file and
stores the value in the variable <tt class="function">storlek</tt>.
The outer loop of the sort algorithm contains two off-by-one
errors; the first record in the file is actually at offset 0 and,
since the inner loop will move forward through the file from the
position after the current offset of the outer loop, the outer loop
does not need to iterate to the very end of the file. The inner
loop of the sort algorithm contains a similar error and will
attempt to read beyond the end of the file.</p>
<p>The basis of the selection sort algorithm is to find the
smallest remaining record on each pass through the inner loop and
to swap it with the record currently pointed to by the outer loop.
In order to do this, the algorithm must store both the current
smallest record and its position in the file. The inner loop scans
from the position after the current outer loop position to the end
of the file and, whenever it finds a record smaller than the
current smallest record, it saves the new smallest record and its
position. After the inner loop is complete, the algorithm checks
whether the current outer loop record is the smallest and, if it is
not, swaps the current record with the smallest record.</p>
<p>The final version of <tt class="function">sortera()</tt> omits
error checks on the library calls to keep the length of the code
short enough to print:</p>
<pre class="programlisting">
// sortera - sort and print personal information
void sortera(){
FILE *my_fil;
int storlek,k,m;
long ft;
PERSPOST pos_current;
PERSPOST pos_smallest;
PERSPOST pos_new;
int smallest;

my_fil=fopen(REGISTER_FILE,&quot;rb+&quot;);
if ( my_fil ){
  fseek(my_fil,0,SEEK_END);
  ft=ftell(my_fil);
  storlek=((int)ft)/S_PERSPOST;

  // Selection sort
  for(k=0;k&lt;storlek-1;k++){
    // Read the first of the remaining records
    fseek(my_fil,k*S_PERSPOST,SEEK_SET);
    fread(&amp;pos_current,S_PERSPOST,1,my_fil);

// Scan forward through the file looking for the
//  smallest record
    pos_smallest = pos_current;
    smallest = k;
    for(m=k+1;m&lt;storlek;m++){
      fread(&amp;pos_new,S_PERSPOST,1,my_fil);

      // If this record is the smallest, 
      // save it and remember where it is in the file
      if(strcmp(pos_smallest.pnumber,
                       pos_new.pnumber)&gt;0){
        pos_smallest=pos_new;
        smallest=m;
        }
      }

    // If the first record isn't the smallest, 
    // swap it with the smallest
    if (smallest != k ){
      fseek(my_fil,k*S_PERSPOST,SEEK_SET);
      fwrite(&amp;pos_smallest, S_PERSPOST, 1,
                                       my_fil);
      fseek(my_fil, smallest*S_PERSPOST,
                              SEEK_SET);
      fwrite(&amp;pos_current, S_PERSPOST, 1, 
                                       my_fil);
      }
    }
  fclose( my_fil );
  }

utskrift();
} // end sortera
</pre></div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e562" id="d0e562"></a>Third Review
by James Holland</h2>
</div>
<p>Dear Francis,</p>
<p>I thought I would have a go at the Code Critique Competition you
set in C Vu Volume 11 No 4. I have done the best I can in the time
available but please do not hesitate to show me where I have gone
wrong.</p>
<p>As you suggest it is helpful to rewrite the code to correctly
show the program structure. Such things as indentation and the
position of braces are a matter of personal taste. I prefer to have
the opening and closing braces vertically aligned at the same
indentation as the controlling statement. The code within the
braces is then indented by two spaces. I notice that the student
puts the opening brace at the end of the controlling statement, as
do many experts, but I have never been very happy with this
approach.</p>
<p>It also makes the code easier to read if there are appropriately
placed spaces within the statements. It gets a bit heavy going when
the code is constructed without spaces to separate the various
terms and clauses<sup>[<a name="d0e573" href="#ftn.d0e573" id=
"d0e573">2</a>]</sup>.</p>
<p>I think one reason the student has got in a bit of a muddle is
the way he or she is trying to return to the menu function. Instead
of returning from a called function the student is indirectly
recursively calling <tt class="function">menu()</tt>. Recursive
calls are confusing at the best of times and, in this case, it is
not what is required.</p>
<p>Two things have to be done to correct the problem. The first is
to remove the recursive calls to <tt class="function">menu()</tt>.
The correct way to return to the <tt class="function">menu()</tt>
function is to place a return instruction in the called function.
We now have the following situation. The <tt class=
"function">menu()</tt> function calls, say, <tt class=
"function">lasin()</tt>. When <tt class="function">lasin()</tt> has
finished doing its work the program will return to <tt class=
"function">menu()</tt> in an orderly fashion. The <tt class=
"function">menu()</tt> function will finish its work and return to
<tt class="function">main()</tt> where the program will terminate.
The program is retracing its steps, it returns the way it came.</p>
<p>The only problem now is that only one <tt class=
"function">menu()</tt> function is executed before the program
ends. We now have to make the second amendment to the program. The
<tt class="function">menu()</tt> function needs to execute again
and again. I have surrounded the <tt class="function">menu()</tt>
code with a <tt class="literal">while(1)</tt> loop. I have also
added an 'exit' option to the menu. The user now has to choose the
additional option to exit the program. An <tt class=
"literal">if</tt>-statement returns the program to <tt class=
"function">main()</tt> only if the 'exit' option is selected. This
prevents the program from exiting after the selection of only one
menu option.</p>
<p>I have provided a way of detecting a value of '0' for the
personnel number. I have placed a <tt class=
"literal">while</tt>-loop around the data entry code. The loop will
only execute when the variable <tt class="varname">proceed</tt> is
true. The variable <tt class="varname">proceed</tt> is first set
<tt class="literal">true</tt> outside the loop so the loop will
always execute the first time. If, within the loop, the user enters
a '0' for the personnel number the <tt class="varname">proceed</tt>
variable will be set to <tt class="literal">false</tt>. There is
also no need for the user to enter any more personnel information
so the rest of the data entry code is skipped. When the program
next executes the <tt class="literal">while</tt>-statement the
<tt class="varname">proceed</tt> variable will be <tt class=
"literal">false</tt> and so the loop will not execute. The register
file is closed and the program returns to <tt class=
"function">main()</tt>. In this way the loop will execute
repeatedly allowing the user to add many records until a '0' for
the personnel number is entered.</p>
<p>When rewriting the code I noticed that the function prototypes
have empty prototype lists. This causes the (C) compiler not to
recognise them as prototypes. The compiler issues a warning stating
that there is a call to a function with no prototype. The parameter
list (in a C program) must contain the parameter types, even if
they are of type <tt class="literal">void</tt>.</p>
<p>There seems to be some very strange spelling used for variable
names<sup>[<a name="d0e667" href="#ftn.d0e667" id=
"d0e667">3</a>]</sup>. There were quite a few I could not fathom.
To aid my understanding of what is going on I decided to rename
most of the variables. I gave them names that would be more
informative to me. I think it is important to give clear and
concise names to variables. This not only helps the program writer
but other people when they come to review the code.</p>
<p>It is not necessary to use <tt class="function">printf()</tt> to
print simple text strings, use <tt class="function">puts()</tt>
instead. <tt class="function">puts()</tt> automatically inserts a
carriage return after the string so we can now remove the \n from
some of the text strings. Successive carriage returns can be
achieved by the use of successive \n in the text string of
<tt class="function">puts()</tt>.</p>
<p>I think the text of the menu prompt is a little enigmatic. It
would be best to state clearly what the user is expected to do.
This time <tt class="function">printf()</tt> is used because we do
not want a carriage return at the end of the prompt<sup>[<a name=
"d0e690" href="#ftn.d0e690" id="d0e690">4</a>]</sup>.</p>
<p>The menu is now in a reasonable state. There is still one
problem. If the user types a non numerical value <tt class=
"function">scanf()</tt> will not remove the user input from its
buffer. The program will loop around to <tt class=
"function">scanf()</tt> which will again see a non numerical value.
The program will loop forever. To prevent this behaviour all we
have to do is remove any characters from the input buffer. This is
carried out by the <tt class="function">fflush(stdin)</tt>
statement. (<i><span class="remark">I wonder if the writer checked
this. <tt class="function">fflush</tt> is specifically for output
streams or for bi-directional streams where output is the most
recent event. Francis</span></i>)</p>
<p>We can now turn our attentions to the <tt class=
"function">lasin()</tt> function. I have renamed this function
<tt class="function">add_record</tt>.</p>
<p>When adding a record, the program asks for a file name. The
prompt states that the name of the file must be <tt class=
"filename">fil.txt</tt>. If the file name must be a fixed value
there is no need for the user to enter it. The name of the file can
be embedded within the code. This removes the need for the
<tt class="varname">namn[10]</tt> array. I have changed the name of
the file to <tt class="filename">register.dat</tt> as I think it
more appropriate. The file is not a text file, it is a binary
file.</p>
<p>When adding a record to the register file I assume the idea is
to append a record to the end of the file if the file already
exists or, if the file does not exist, create a new register file
and then add the record. To do this we need to open the file in &quot;a&quot;
mode and not &quot;w&quot; (write) mode as in the student's program.</p>
<p>When adding records to the register file it does not matter
whether the record is inserted at the start of the file or at the
end. The file will be sorted before it is printed in any case.
There is, therefore, no need to use the <tt class=
"function">fseek()</tt> function to place the new record at the
beginning of the file. A simple <tt class="function">fwrite()</tt>
will suffice.</p>
<p>We are now in a position to look at the functions that display
the register file. Sorting routines are always a bit difficult to
get working, so I will get the printing function working first. I
have changed the name of function that displays the contents of the
register file from <tt class="function">utskrift</tt> to <tt class=
"function">display</tt>.</p>
<p>The <tt class="function">utskrift()</tt> function is far too
complicated. There is no need to work out the length of the file,
calculate the number of records in the file and then seek each
record. Simply open the file and write out successive records until
the end of file is reached. The method I have chosen is to create a
loop with a <tt class="literal">while(1)</tt>-statement. This would
loop forever if it were not for the <tt class=
"literal">if</tt>-statement within the loop. The program breaks out
of the loop when the end-of-file marker is <tt class=
"literal">true</tt>. This arrangement caters for the condition when
the file is empty.</p>
<p>It is now time to tackle the sort routine. I thought this
routine would need a lot of reworking to get it into shape. As it
turns out there is not much wrong with it. It would be helpful if a
comment is added describing the type of sort used. In this case a
bubble sort is used.</p>
<p>A bubble sort is not very efficient for a large number of
records but will be acceptable in this case. The header file
<tt class="filename">stdlib.h</tt> enables a sorting routine called
<tt class="function">qsort</tt> to be used<sup>[<a name="d0e774"
href="#ftn.d0e774" id="d0e774">5</a>]</sup>. It would have probably
been better to use <tt class="function">qsort</tt> from the
beginning but developing your own sort routine will be
instructive.</p>
<p>The first problem is that the sorting routine opens the file for
reading only. We will need to open it for update (reading and
writing) and so the mode string should be &quot;r+b&quot;.</p>
<p>When sorting we need to consider the first record so <tt class=
"varname">k</tt> should be initialised to 0 in the <tt class=
"literal">for</tt>-loop. The inner loop should iterate between
<tt class="literal">m+k</tt>, and the last record in the file. The
student tries to go one beyond the last record. The limiting
condition should be <tt class="literal">m &lt; storlek</tt>. The
student also omitted to close the file at the end of the sort
routine.</p>
<p>With these corrections in place the program should work as
intended. There will always be various improvements and alterations
that could be made to a program. In the student's program, for
example, there is a lot of opening and closing of the register
file. The program could be designed to open the file once at the
beginning of the program and then close it at the end of the
program. The method adopted by the student is perfectly acceptable,
though.</p>
<p>It is worth noting that the sort routing does not sort in
numerical order. It sorts in lexicographical, or dictionary, order.
If this is what the student intended all well and good. The
personnel number is stored as a character string and so there is
nothing to prevent any character from being entered. The same
applies for the forename and last name.</p>
<p>I have made one important modification to the student's program.
I have attempted to prevent excessive user input from overflowing
the character arrays. I have limit the <tt class=
"function">scanf()</tt> function to accepting up to one character
less than the length of the array. The last character of the arrays
is needed for the null terminator character. Any additional
characters are purged from the input buffer by the <tt class=
"function">fflush(stdin)</tt> statements (<i><span class=
"remark">did you test that assertion?</span></i>). It is always
important to guard against the abuses of the user.</p>
<p>There is no need to include the header file <tt class=
"filename">io.h</tt>. I have also removed the <tt class=
"function">getch()</tt> from just before the <tt class=
"literal">return</tt> statement in <tt class=
"function">main</tt><sup>[<a name="d0e828" href="#ftn.d0e828" id=
"d0e828">6</a>]</sup>. This makes the program exit when
expected.</p>
<p>It is always a good idea to test for the successful opening of a
file. This can save a lot of time when debugging the program. It
will also prevent the program from continuing when there are
problems such as a full disc.</p>
<p>To check for the successful file opening simply compare the
value of the file pointer after the attempt to open the file. This
can be achieved by an <tt class="literal">if</tt>-statement wrapped
around the <tt class="function">ffopen</tt> statement as shown in
the listing. <tt class="function">ffopen()</tt> will assign to the
file pointer a <tt class="literal">NULL</tt> value if the attempt
to open the file failed. This value is tested in the <tt class=
"literal">if</tt>-statement. If the file pointer has the value
<tt class="literal">NULL</tt> a short warning message is displayed
and the program exits.</p>
<p>I provide my version of the program on the disc enclosed. Please
keep the disc.</p>
<p>I have enjoyed tackling this problem and hope my efforts are of
some interest<sup>[<a name="d0e861" href="#ftn.d0e861" id=
"d0e861">7</a>]</sup>.</p>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e865" id="d0e865"></a>Fourth Review
by Fred Johnson</h2>
</div>
<p>As you rightly point out, it is time for someone other than the
few regular contributors to do all the work. Attached is my
critique of the code from C Vu 11 No.4. It has been an interesting
exercise and I feel that I have learned a few extra things on the
way. Thanks for the opportunity.</p>
<p>Fred Johnson. <tt class="email">&lt;<a href=
"mailto:fred@fredshome.freeserve.co.uk">fred@fredshome.freeserve.co.uk</a>&gt;</tt></p>
<div class="sect2" lang="en">
<div class="titlepage">
<h3><a name="d0e874" id="d0e874"></a>First
comments</h3>
</div>
<p>Layout of code. There are a number of ways of improving this to
give a clearer indication of functions and routines within
functions - braces etc. I have changed the layout to my own
preferred style (though other styles are equally valid) to clarify
program flow. Whilst this is not essential, it can often help
visualise the program or function being written. It can also help
to keep track of matching conditions in loops etc.</p>
<p>Prototypes ought to be in a suitable header rather than in the
program body. If no parameters are to be returned, then prototypes
should reflect this e.g. void lasin(void) (I have tried two
different compilers, Borland C v5.02 on a PC and Hisoft C on an
Atari, both of which reject<sup>[<a name="d0e881" href=
"#ftn.d0e881" id="d0e881">8</a>]</sup> empty braces in declaration
of prototypes.)</p>
<p>Magic numbers used in the record structure. Give the member
sizes names and define them in header . Future changes are much
easier if you don't need to search all your source code for
numbers</p>
<p>Main function declared as having no return value.</p>
<p>Better to return a value for system use if necessary (Some
systems require a return value or they produce an error message).
Speaking of returns, many 'C' functions return useful data. Make
use of these returns for passing back any possible errors. There is
nothing worse than a program which fails and gives no indication of
the failure.</p>
<p>Use of <tt class="function">scanf</tt>. Although it can be used
to limit the number of characters input (<tt class=
"literal">scanf(&quot;%9s&quot;</tt> will input nine characters and then
append '\0') into a string, it will happily swallow many more
characters with no warning of what it is doing, and then truncate
input to the length requested. What is worse, on some
compilers<sup>[<a name="d0e899" href="#ftn.d0e899" id=
"d0e899">9</a>]</sup> (I don't know what the ISO standard has to
say), any remaining characters are put into the next string when
<tt class="function">scanf</tt> is called again! This function is
much like the renowned Swiss Army knife. An excellent tool for the
expert, with its uses limited by imagination but not the sort of
thing for the average householder to put on a table to eat
dinner.</p>
<p>A better way would be to write your own input function where you
can specify maximum string length as well as only allowing valid
characters and issuing warnings of strings which are too long. Bear
in mind that many software users are not computer experts and may
(Probably will at some time) enter invalid input such as numbers
instead of letters and vice versa.</p>
<p>(For more, see C Vu Vol 8 No 6, &quot;Under a hundred&quot;, particularly
the replies by the Harpist to my letter, and the letter from Kevlin
Henney.)</p>
<p>An incidental advantage of this procedure would be to allow you
to fill the unused characters after the '\0' in your structure with
spaces so that files can also be examined using a text editor .</p>
<p>Menu function has no way to end the program if needed.</p>
<p><tt class="function">scanf</tt> function for input in menu would
be better replaced with a function which only allows <tt class=
"type">int</tt> values to be input. Using <tt class=
"function">getch()</tt> allows a menu with as many entries as keys
on the keyboard.</p>
<p>Use of <tt class="type">int</tt> for all sizes not advised -
<tt class="function">ftell</tt> returns long int on MSDOS
systems<sup>[<a name="d0e932" href="#ftn.d0e932" id=
"d0e932">10</a>]</sup> but we don't all use MSDOS, also not all
versions of <tt class="type">int</tt> are 32 bits long!.</p>
<p>Please don't mix <tt class="type">long</tt> and <tt class=
"type">int</tt>s in calculations unless you are certain that no
overflow will take place. Keep to using all <tt class=
"type">long</tt>'s in this case, or use <tt class=
"type">size_t</tt> for variables. See &quot;<i class="citetitle">The
Standard C Library</i>&quot; by P.J.Plauger. If you haven't got this
publication, it is worth obtaining a copy as soon as possible.</p>
<p>Use of variable names. Whilst keeping to short names, it is
preferable to use more meaningful names rather than single or two
letters. For example, use <tt class="varname">file_length</tt>
instead of <tt class="varname">ft</tt>.</p>
<p>For general helpful commentary, see C u Vol 10 No 6, &quot;A critique
of some code&quot;.</p>
<p>I have re-written the menu in a manner which may be more useful,
separating <tt class="function">paintscreen</tt> function to allow
this to be called before returning to the menu.</p>
<p>Now to the rest of your code.</p>
<pre class="programlisting">
lasin();
my_fil = fopen(namn,&quot;wb&quot;);
</pre>
<p>If you wish to overwrite any existing file named <tt class=
"filename">fil.txt</tt>, then fine. If you wish to add to an
existing file, then open using &quot;rb+&quot;, first checking whether file
exists. See next item.</p>
<p>When opening a file, it can be an advantage to check that the
file is opened before proceeding further, to allow appropriate
action to be taken in case of failure, such as file not existing,
or lack of disk space to create it.</p>
<p>Use of <tt class="function">atoi</tt> on <i class=
"structfield"><tt>preg.pnumber</tt></i> seems to indicate that you
should have this part of the structure as an integer rather than a
string of 15 chars (which incidentally can produce a number too
large to be represented as a single quantity if you are limited to
32 bit longs (Maximun 2,147,483,648).</p>
<p>This value may be defined on some compilers as <tt class=
"literal">MAXLONG</tt>.</p>
<p>If a number is required, then a function <tt class=
"function">getint</tt> should be written to fulfil the requirements
of your program.</p>
<p>Loop changed to terminate on input &quot;-1&quot;, close file, and return
to calling function after re drawing screen rather than
incorporating recursive calls to <tt class=
"function">meny</tt>.</p>
<p>Extra <tt class="function">puts</tt> calls simply to indicate
progress of program during testing.</p>
<pre class="programlisting">
sortera()
</pre>
<p>File opened in mode &quot;rb&quot;. This should not allow any writes to
the opened file. Using the return value of <tt class=
"function">fwrite</tt> would have shown this problem. Use instead,
mode &quot;rb+&quot; which does allow writes.</p>
<p>The sort routine starts with <tt class="literal">k=1</tt>. This
is actually the second record in the file. Should start with
<tt class="literal">k=0</tt>.</p>
<pre class="programlisting">
if(strcmp(pos1.pnumber, pos2.pnumber) &gt; 0)
</pre>
<p>If an integer had been used for <tt class=
"varname">pnumber</tt>, a simple comparison could have been used
here. If a character based <tt class="varname">pnumber</tt> is
needed, then be aware that <tt class="function">strcmp()</tt>
returns on the first different character thus, &quot;12&quot; is shown as
less than &quot;9&quot; since &quot;1&quot; of the &quot;12&quot; is less than &quot;9&quot;, and this is
where <tt class="function">strcmp()</tt> will return.</p>
<p>Sorry if all this seems a bit severe, but I have tried to point
out as many possible traps for the unwary as I can. I am not an
expert programmer and no doubt there are better ways than I have
indicated but I hope I have not sent you down any false paths.</p>
<p>File 1, code.h</p>
<pre class="programlisting">
#ifndef mycode    /* suppress multiple includes */
int main(void);
int lasin(void);
int meny(void);
void paintscreen(void);
int sortera(void);
int avsluta();
int utskrift(void);

#define pnumberlength 15
#define fornamelength 10
#define lastnamelength 15

const int esckey = 27; 
/* ascii escape char. change for other conventions */
</pre>
<p>As you intend to use this as a compile time constant why did you
not either #define it or use an enum?</p>
<pre class="programlisting">
#define mycode
</pre>
<p>It is more conventional to put this in as the second line of a
header file.</p>
<pre class="programlisting">
#endif
</pre>
<p>File 2</p>
<pre class="programlisting">
#include &lt;stdio.h&gt;
#include &lt;string.h&gt;
#include &lt;conio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;io.h&gt;
#include &quot;code.h&quot;
#ifndef ATARI
  #include &lt;dos.h&gt;
#else
  #include &quot;d:\csource\tcheader\turbo.h&quot;
  #include &quot;d:\csource\tcheader\vtscreen.h&quot;
#endif

typedef struct{
  char pnumber[pnumberlength];
  char forname[fornamelength];
  char lastname[lastnamelength];
} perspost;

int main(void){
  meny();
  return 0;
}

int meny(void){
  int val =0;
  paintscreen();
  do {
    val = getch();
    if(val==esckey) break
/* Trap esckey here since defined values*/ 
/* can't be used in case statements */
</pre>
<p>I cannot imagine why not, as the pre-processor has substituted
before the compiler sees your code, but you chose to use a const
int insteadJ</p>
<pre class="programlisting">
    switch(val) {
    case '1': lasin(); break;
    case '2':   sortera(); break;
    default:
      printf(&quot;Invalid Input ** %c **  \n&quot;,val);
      sleep(1);
      paintscreen();
       break;
    }
  } while (val!=esckey); 
    return 0;
}

int lasin(void){
perspost preg;
FILE *my_fil;
char namn[11];/* 10 char filename + extra for '\0' at end of name */
long i=0,ptr=1;
  clrscr();
  printf(
    &quot;Filename(must be named 'fil.txt :-)?:&quot;);
  scanf(&quot;%10s&quot;, namn); 
/* allow 10 chars only */
  if((my_fil=fopen(namn,&quot;wb&quot;)) == NULL){
      puts(&quot;Failed to open file&quot;);
      sleep(1);
      paintscreen();
      return 0;
    }
  fseek(my_fil,0,SEEK_SET);
  clrscr();

/*  while(ptr !=0) */
  do  {
    puts(&quot;Personnummer(personalnumber): &quot;);
     puts(&quot;Enter -1 to end &quot;);
    scanf(&quot;%14s&quot;,preg.pnumber);
    ptr = atoi(preg.pnumber);
    if(ptr == -1)
      break;
    printf(&quot;Frnamn(forname): &quot;);
    scanf(&quot;%9s&quot;, preg.forname);
    printf(&quot;Efternamn(lastname: &quot;);
    scanf(&quot;%14s&quot;,preg.lastname);
/* fseek(my_fil,i*sizeof(perspost),
                   SEEK_SET);  not needed */
        fwrite(&amp;preg,sizeof(perspost),1,my_fil);
    i++;
  }
    while(ptr!=-1);
  printf(&quot;Last entry\n&quot;);
  fclose(my_fil);
  sleep(1);
  paintscreen();
  return 0;
}

int sortera(void){
  FILE *my_fil;
  char myinput;
  size_t data_length, file_length, storlek,   outercount,innercount;
  perspost pos1, pos2, tmp;
  /* open file for read and write without truncating file */
  my_fil = fopen(&quot;fil.txt&quot;,&quot;rb+&quot;); 
  puts(&quot;File opened&quot;);
  fseek(my_fil,0,SEEK_END);  
/* go to end of file */
  file_length = ftell(my_fil);  /* find filelength */
  data_length = sizeof(perspost);
  storlek = file_length/data_length;
  puts(&quot;Starting sort &quot;); 
/* counter should start from 0 for first entry */ 
  for(outercount = 0; outercount&lt;storlek; 
                  outercount++){
    fseek(my_fil, outercount*data_length, 
                    SEEK_SET);
    fread(&amp;pos1,data_length,1,my_fil);
    for(innercount = outercount+1;
             innercount&lt;storlek; innercount++){
      fseek(my_fil, innercount*data_length, 
                      SEEK_SET);
      fread(&amp;pos2,data_length,1,my_fil);
      if(strcmp(pos1.pnumber, 
                    pos2.pnumber)&gt;0){
        tmp=pos1;pos1=pos2;pos2=tmp;
        fseek(my_fil, outercount*data_length, 
                      SEEK_SET);
        fwrite(&amp;pos1,data_length,1,my_fil);
        fseek(my_fil, innercount*data_length, 
                      SEEK_SET);
        fwrite(&amp;pos2,data_length,1,my_fil);
      }
    }
  }
  puts(&quot;End of sortera&quot;); 
  fclose(my_fil);
  sleep(1);
  utskrift();
  paintscreen();
  return 0;
}

int utskrift(){
  FILE *my_fil;
  long counter=0
  long data_length, file_length, storlek;
  perspost preg;
  clrscr();
  my_fil = fopen(&quot;fil.txt&quot;,&quot;rb&quot;);
  fseek(my_fil,0,SEEK_END); 
  file_length = ftell(my_fil);
  data_length=sizeof(perspost);
  storlek=file_length/data_length;
  while(counter&lt;storlek) {
/* note, you do not need to recalculate size of preg, 
   use data_length which has already been calculated */ 
  
    fseek(my_fil,counter*data_length,
                       SEEK_SET);
    fread(&amp;preg,data_length,1,my_fil);
    puts(preg.pnumber);
    puts(preg.forname);
    puts(preg.lastname);
    counter++;
  }
  fclose(my_fil);
  puts(&quot;END of print, press any key&quot;);
  getch(); /* stop here to read screen */
  return 0;
}

void paintscreen(void) {
  clrscr();
  printf(&quot;MENY&quot;);
  puts(&quot;&quot;);
  puts(&quot;&quot;);
  puts(&quot;Select required function&quot;);
   puts(&quot;1......Add People to the register&quot;);
  puts(&quot;2......Print&quot;);
  puts(&quot;ESC....Exit&quot;);
}
</pre></div>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e1066" id="d0e1066"></a>The
Winner</h2>
</div>
<p>Four reviews, four different approaches and each one highlights
different aspects. Each also has some flaws (in some places I have
added footnotes or inserted comments, but not always, and only to
steer novice readers away from some miss-understandings). I wonder
which one you would award the prize to. Well, if the writer of the
first item will contact me we can discuss a prize.</p>
<p>My thanks to the other three contributors for their efforts. If
anyone would like to review the reviews please do so.</p>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e1073" id="d0e1073"></a>Next Review
Competition</h2>
</div>
<p>Elsewhere you will find an article on writing a program to
validate ISBNs. The writer prepared this program as a student
project. Please review his code and prepare an alternative
solution. Extra credit will be given for providing solutions in
more than one language and commenting on the relevant merits of
each language to the problem.</p>
</div>
<div class="footnotes"><br>
<hr class="c3" width="100">
<div class="footnote">
<p><sup>[<a name="ftn.d0e391" href="#d0e391" id=
"ftn.d0e391">1</a>]</sup> Because of space constraints I have
modified the format to the C Vu standard.</p>
</div>
<div class="footnote">
<p><sup>[<a name="ftn.d0e573" href="#d0e573" id=
"ftn.d0e573">2</a>]</sup> While I agree with you, there is a
problem when preparing source code for publication. The format I
use for C Vu is to minimise 'wasted' space. In addition too much
internal whitespace leads to lines wrapping and there are few
things I hate more than code in books where lines have wrapped at
some arbitrary point.</p>
</div>
<div class="footnote">
<p><sup>[<a name="ftn.d0e667" href="#d0e667" id=
"ftn.d0e667">3</a>]</sup> I think the student is not a native
English speaker</p>
</div>
<div class="footnote">
<p><sup>[<a name="ftn.d0e690" href="#d0e690" id=
"ftn.d0e690">4</a>]</sup> <tt class="function">fputs()</tt> is an
alternative solution.</p>
</div>
<div class="footnote">
<p><sup>[<a name="ftn.d0e774" href="#d0e774" id=
"ftn.d0e774">5</a>]</sup> However <tt class="function">qsort</tt>
requires the data to be held in an array in 'RAM'</p>
</div>
<div class="footnote">
<p><sup>[<a name="ftn.d0e828" href="#d0e828" id=
"ftn.d0e828">6</a>]</sup> I suspect that <tt class=
"function">getch</tt> was being used to prevent early closure of a
console window.</p>
</div>
<div class="footnote">
<p><sup>[<a name="ftn.d0e861" href="#d0e861" id=
"ftn.d0e861">7</a>]</sup> The writer's source code is on this
issue's disk</p>
</div>
<div class="footnote">
<p><sup>[<a name="ftn.d0e881" href="#d0e881" id=
"ftn.d0e881">8</a>]</sup> And correctly do so as long as they are C
rather than C++ mode.</p>
</div>
<div class="footnote">
<p><sup>[<a name="ftn.d0e899" href="#d0e899" id=
"ftn.d0e899">9</a>]</sup> Correctly, because the request is to read
up to nine characters and no more, so the rest must be for the next
input.</p>
</div>
<div class="footnote">
<p><sup>[<a name="ftn.d0e932" href="#d0e932" id=
"ftn.d0e932">10</a>]</sup> It is required to return a <tt class=
"type">long int</tt> by the ISO standard.</p>
</div>
</div>
</p>
<p><strong>Notes:</strong>&nbsp;</p>
<p><em>More fields may be available via dynamicdata ..</em></p>
</div>
</channel>
</rss>
