    <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</title>
        <link>https://members.accu.org/index.php/journals/987</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 12, #2 - Mar 2000 + 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="https://members.accu.org/index.php/journals/">All</a>

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

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

                     &gt;                         <a href="https://members.accu.org/index.php/journals/c127/">122</a>
                    (18)
<br />

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

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

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

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

                    -                        <a href="https://members.accu.org/index.php/journals/c127+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;Student Code Critique Competition</h1>
<p><strong>Author:</strong>&nbsp;</p>
<p>
<strong>Date:</strong> 07 March 2000 13:15:36 +00:00 or Tue, 07 March 2000 13:15:36 +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="d0e20" id="d0e20"></a></h2>
</div>
<p class="c2"><span class="remark">Prizes for this competition are
provided by Blackwells Bookshops in co-operation with
Addison-Wesley. There was only a single entry for last issue's
critique which made the job of selecting a winner easy. Why not
make my task harder next time by looking at this issue's code at
the end of this column?</span></p>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e25" id="d0e25"></a>Last Issue's
Code:</h2>
</div>
<pre class="programlisting">
void comp_stu () {
  FILE *grades_data;
  int i;
  char name[20];  /*students name */
  int test_1[3];  /*grade test 1*/
  int test_2[3];  /*grade test 2*/
  int test_3[3];  /*grade test 3*/
  int asign[3];     /*grade assignment */
  int final[3];     /*grade from final exam */
  int a;
  int val;
  i = 0;
  grades_data = fopen (&quot;grades.data&quot;, &quot;r&quot;); 
/*file with names, grade for test1,2,and 3, and assignment, and final */
  val = fscanf (grades_data, &quot;%s%d%d%d%d%d&quot;, &amp;name[i], &amp;test_1[i], &amp;test_2[i], &amp;test_3[i], &amp;asign[i], &amp;final[i]);
  while (val != EOF) {
/*read file until end of file */
    a = strcmp(&amp;name[i],&amp;name[i+1]);
/*compare first and second students' names */
    if (a &gt; 0)
      printf (&quot;%s%5s%d%4s%d%4s%d%4s%d%4s%d\n&quot;, &amp;name[i], &quot; &quot;, &amp;test_1[i], &quot; &quot;, &amp;test_2[i], &quot; &quot;, &amp;test_3[i], &quot; &quot;, &amp;asign[i], &quot; &quot;,&amp;final[i]);
    if (a ==0) 
/* code to intended print both students' data */
    if (a &lt; 0) 
/* as above but in reverse order */
    i ++;
    val = fscanf (grades_data, &quot;%s%d%d%d%d%d&quot;, &amp;name[i], &amp;test_1[i], &amp;test_2[i], &amp;test_3[i], &amp;asign[i], &amp;final[i]);
  }
  return;
}
</pre>
<p>The first and last name of each student is contained in one
<tt class="type">string</tt>. <tt class="varname">name[i]</tt>
would contain the students first and last name. I have tried
running the program using the above function, but its not working.
I will get bits of the students' names and jumbled numbers.</p>
<div class="sect2" lang="en">
<div class="titlepage">
<h3><a name="d0e38" id="d0e38"></a>Winning
Critique</h3>
</div>
<div class="sect3" lang="en">
<div class="titlepage">
<h3><a name="d0e41" id="d0e41"></a>By Brett Fishburne
<tt class="email">&lt;<a href=
"mailto:wfishburne@atcnet.com">wfishburne@atcnet.com</a>&gt;</tt></h4>
</div>
<p>In an effort to understand the student code presented, I started
with the name of the function. <tt class="function">comp_stu</tt>.
My guess is that this refers to &quot;compare students.&quot; A quick look at
the declarations suggests that 3 students are to be compared (all
the grades are arrays that can hold 3 entries). This points out an
immediate problem with the <tt class="varname">name</tt> array,
which will only hold one name of up to 20 characters. The variable
should be correctly declared as:</p>
<pre class="programlisting">
char name[3][20] /* 3 names, up to 20
             characters each */
</pre>
<p>The file &quot;<tt class="filename">grades.data</tt>&quot; is opened
without confirming that the <tt class="function">fopen</tt> command
was successful. A check to see if the file is opened correctly
should be incorporated as:</p>
<pre class="programlisting">
if ((grades_data = fopen(&quot;grades.data&quot;, &quot;r&quot;))
               == (FILE *)NULL) {
 fprintf(stderr, 
    &quot;comp_stu: Unable to open grades_data\n&quot;);
 return; }
</pre>
<p>In this way, the programmer checks to be certain that the file
has been opened successfully.</p>
<p>The function contains two calls to <tt class=
"function">fscanf</tt>, that are both the same. By properly
structuring the loop, the two calls can be combined into one. The
loop as it exists, tests <tt class="varname">val</tt>, which is the
return from <tt class="function">fscanf</tt>. The return value of
<tt class="function">fscanf</tt> is the number of items scanned in
from the input stream (<tt class="literal">EOF</tt> only if the
input ends before the first conflict or conversion). Since the loop
really is checking for the end of the stream, it would be better to
use the <tt class="function">feof</tt> function. As noted above,
however, no more than 3 students can be compared, so this needs to
be incorporated into the loop as well. It should be obvious that if
more than 3 students are in the input file, it doesn't matter, as
no more than three will be evaluated. Thus, the new loop condition
should be:</p>
<pre class="programlisting">
while ((!feof(grades_data)) &amp;&amp; (i &lt; 3))
</pre>
<p>This checks for the end of file and checks the student count to
be sure no more than three students are processed. In general I
prefer a better variable naming convention than <tt class=
"varname">i</tt> but it is not terribly unreasonable as this
variable is actually a counter.</p>
<p>Looking at the existing while loop, it is clear that the student
wishes to compare students and print them out in order. It is
necessary, however, to read in all the students, then perform the
comparison. Thus, the comparison needs to be removed from the
loop.</p>
<p>Since the loop condition above addresses the file, it is clear
that the loop should read in the students. This suggests that the
next statement should scan in the student information. The scan
statement used in the existing program is basically fine for this
purpose if it is fair to assume that the data is presented exactly
in the form expected by the scan statement. In the last C Vu, Mr
Stroustrup went to great lengths to examine the difficulty of
reading in strings and explaining how difficult the C code for
doing so is. For the sake of simplicity (and the premise of this
being a true student project), I will assume that the teacher has
guaranteed that the data is in the correct format or it should be
considered a catastrophic error.</p>
<p>The first <tt class="function">fscanf</tt> shown in the program
needs a couple of simple modifications to perform more
appropriately. The number of characters in the name needs to be
constrained so that the array is not overrun. Thus the new call
would be:</p>
<pre class="programlisting">
val = fscanf(grades_data, &quot;%19s%d%d%d%d%d&quot;,
   &amp;(name[i][0]), &amp;(test_1[i]), &amp;(test_2[i]),
   &amp;(test_3[i]), &amp;(assign[i]), &amp;(final[i]));
</pre>
<p>It is important, however, to check the return value from
<tt class="function">fscanf</tt> to make sure that all the
variables were read in! This requires the following additional code
after the <tt class="function">fscanf</tt> function:</p>
<pre class="programlisting">
if (val != 6) {
 fprintf(stderr, 
  &quot;comp_stu: Error reading from grades data\n&quot;);
 (void)fclose(grades_data);
 return; }
</pre>
<p>The loop is almost complete, but it is necessary to increment
the counting variable, <tt class="varname">i</tt>, and that will
end the loop.</p>
<pre class="programlisting">
i++;
</pre>
<p>With the students read in, it is no longer necessary to keep the
input file open. I like to close files right away so that there are
no unused file descriptors hanging open inappropriately. fclose
returns a value (0 on success) and there is rarely anything to be
done if a file won't close, but just in case there is a problem, it
is worthwhile to check the return value and handle it properly:</p>
<pre class="programlisting">
if (fclose(grades_data) == EOF) {
 fprintf(stderr, 
&quot;comp_stu: Warning unable to close grades file\n&quot;);
 fprintf(stderr, 
  &quot;comp_stu: Error number %d\n&quot;, errno); }
</pre>
<p>Now it is time to compare the students. Possibly, however, fewer
than 3 students were read in, so it is important to check the
number of students read in and use that to guide the
comparison.</p>
<p>A different sorting function is performed depending on the
number of students read in. This calls for a <tt class=
"literal">switch</tt> statement which works based on the number of
students:</p>
<pre class="programlisting">
switch(i)
</pre>
<p>The first case is simple, if only 1 student was read in, then
only 1 student needs to be printed. While the <tt class=
"function">printf</tt> command in the student program has nothing
inherently wrong with it, printing single spaces <tt class=
"varname">n</tt> times using the <tt class="literal">%s</tt>
command is overkill. The spaces can be inserted directly. In
addition the array index must be used consistently and putting
sizing information for the width of the fields will keep columns
consistent (The -19 left justifies the string in a 19 character
field). Finally, the integer values should not be made into
pointers:</p>
<pre class="programlisting">
case 1: { printf(&quot;%-19s   %6d  %6d  %6d  %6d  
%6d\n&quot;, &amp;(name[0][0]), test_1[0], test_2[0], 
test_3[0], assign[0], final[0]);
     break; }
</pre>
<p>If two students were read in, then the larger name should appear
first. This can be determined by looking at the &quot;<tt class=
"literal">a &lt; 0</tt>&quot; condition in the original program. If the
first string is smaller than the second string (<tt class=
"function">strcmp</tt> returns a negative), then the original
programmer prints the second string first (or at least starts to
print the second string first). The two student case is also easily
handled:</p>
<pre class="programlisting">
case 2: { 
if (strcmp(&amp;(name[0][0]), &amp;(name[1][0])) &lt; 0) {
  printf(&quot;%-19s   %6d  %6d  %6d  %6d  %6d\n&quot;,
    &amp;(name[1][0]), test_1[1], test_2[1], 
    test_3[1],assign[1], final[1]);
 printf(&quot;%-19s   %6d  %6d  %6d  %6d  %6d\n&quot;,
    &amp;(name[0][0]), test_1[0], test_2[0],
    test_3[0],assign[0], final[0]);
} else {
/* code in reverse of the above order snipped */
break; }
</pre>
<p>At this point, it is almost frustrating to continue to try to
use the style of code created by the student. On the other hand, it
seems that the student will learn more from the review process by
seeing the code back in his/her own style. Given that assumption,
the case of three students must be handled. Below is a table that
shows the possible permutations on three students:</p>
<div class="informaltable">
<table border="1" cellspacing="0">
&lt;colgroup&gt;
&lt;col&gt;
&lt;col&gt;
&lt;col&gt;
&lt;col&gt;&lt;/colgroup&gt;
&lt;thead&gt;
<tr>
<th>Student name / comparison</th>
<th align="center">1st &gt; 2nd</th>
<th align="center">2nd &gt; 3rd</th>
<th align="center">1st &gt; 3rd</th>
</tr>
&lt;/thead&gt;
&lt;tbody&gt;
<tr>
<td>a, b, c</td>
<td align="center">False</td>
<td align="center">False</td>
<td align="center">False</td>
</tr>
<tr>
<td>a, c, b</td>
<td align="center">False</td>
<td align="center">True</td>
<td align="center">False</td>
</tr>
<tr>
<td>b, a, c</td>
<td align="center">True</td>
<td align="center">False</td>
<td align="center">False</td>
</tr>
<tr>
<td>b, c, a</td>
<td align="center">False</td>
<td align="center">True</td>
<td align="center">True</td>
</tr>
<tr>
<td>c, a, b</td>
<td align="center">True</td>
<td align="center">False</td>
<td align="center">True</td>
</tr>
<tr>
<td>c, b, a</td>
<td align="center">True</td>
<td align="center">True</td>
<td align="center">True</td>
</tr>
&lt;/tbody&gt;
</table>
</div>
<p>Given the sequences in the table, it will be possible to find
the proper order of the students by doing up to three <tt class=
"function">strcmp</tt> calls. These permutations hold true even if
a and c, for example are the same (True, False, False and the
associated rearrangement would work). At this point, it should be
obvious that there will be six sets of <tt class=
"function">printf</tt> statements. There is no question that this
is inefficient code, but I think that using a sort call or
something like that would simply obfuscate the errors made by the
student programmer rather than elucidate them. Thus, the case
statement for three students is (the &quot;printf&quot; calls are omitted for
clarity):</p>
<pre class="programlisting">
case 3: { 
if (strcmp(&amp; (name[0][0]),&amp; (name[2][0])) &gt; 0){
  if (strcmp(&amp;(name[1][0]), &amp;(name[2][0])) &gt; 0) {
    if (strcmp(&amp;(name[0][0]), &amp;(name[1][0])) &gt; 0) {
        /* print 0 then 1 then 2 */
    } 
    else {
        /* print 1 then 0 then 2 */
    }
  } 
  else {
        /* print 0 then 2 then 1 */
  }
} 
else {
  if (strcmp(&amp;(name[1][0]), &amp;(name[2][0])) &gt; 0) {
       /* print 1 then 2 then 0 */
  } 
  else {
    if (strcmp(&amp;(name[0][0]), &amp;(name[1][0])) &gt; 0) {
        /* print 2 then 0 then 1 */
 } 
  else {
        /* print 2 then 1 then 0 */
  }
 }
}
break; 
}
</pre>
<p>There remains the possibility that no students were read in from
the grades file, so that should be handled by the default in the
<tt class="literal">switch</tt> statement:</p>
<pre class="programlisting">
default: { 
  fprintf(stderr,
        &quot;comp_stu: No students found\n&quot;);
  break; 
}
</pre>
<p>With this the case statement is complete and the function is
ended with a return statement.</p>
<p class="c2"><span class="remark">Sometime shortly Brett will be
receiving a copy of Standard C++ IOStreams and Locales by Angelika
Langer and Klaus Kreft (reviewed in the current issue of
Overload).</span></p>
</div>
</div>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e250" id="d0e250"></a>This Issue's
Student Code</h2>
</div>
<p>I have to process a set of files, one per employee, that
contains data about an employees working times. A typical file
would be:</p>
<pre class="programlisting">
Kaiser
18.12.1999 6.0 K1001 Praktikum GIP
17.12.1999 4.5 K0002 Fachbereichssitzung
19.12.1999 2.0 K1001 Vorlesung GIP
19.12.1996 3.0 K0001 Weihnachtsfeier
01.01.2000 2.5 K3001 Klausur GIP erstellen
</pre>
<p>I am required to read the data into a structure and sort it by a
bubblesort on the dates. I should also be able to generate a list
for a specific time period (e.g. provide a list from 19.12.1999
till 30.01.2000)</p>
<p>Here is the C code. As I am German, the identifiers are in that
language.</p>
<p>This is my structure in the header file:</p>
<pre class="programlisting">
/*** Datenstrukturen ***/
struct stunden {
 float std;
 char kostenstelle[6];  char datum[11];
 char name[21];  char arbeit[41];
};
/*** Globale Variablen ***/
extern struct stunden std[100];
extern int anz_daten;
</pre>
<p>Here I will read my data from a file into the structure:</p>
<pre class="programlisting">
int datei_einlesen(char datei[13]) {
FILE *pf;
  char name[21];
  pf = fopen(datei, &quot;r&quot;);
  if(!pf)  return 0;
  fscanf(pf, &quot;%s&quot;, name);
  while(!feof(pf)){
     fscanf(pf, &quot;%s %f %s&quot;, std[anz_daten].datum,
               &amp;std[anz_daten].std,
               std[anz_daten].kostenstelle);
    fgets(std[anz_daten].arbeit, 40, pf);
    if(strpbrk(std[anz_daten].arbeit, &quot;\n&quot;))
          std[anz_daten].arbeit[strlen(
      std[anz_daten].arbeit)- 1] = 0;
    strcpy(std[anz_daten].name, name);
    anz_daten++;
  }
  fclose(pf);
  return 1;
}
</pre>
<p>And here I want to list a period of time:</p>
<pre class="programlisting">
void datum_zerlegen(char datum[11], int *tag
            , int *monat, int *jahr) {
     char t[3], m[3], j[5];
     strncpy(t, datum, 2);
     t[2] = 0;
     strncpy(m , datum + 3, 2);
     m[2] = 0;
     strncpy(j, datum + 6, 4);
     j[4] = 0;
     *tag = atoi(t);
     *monat = atoi(m);
     *jahr = atoi(j);
}
void zeitraum_ausgeben(char von[11], char bis[11]) {
  int x, vtag, vmonat, vjahr;
  int btag, bmonat, bjah, xtag, xmonat, xjahr;
  datum_zerlegen(von, &amp;vtag, &amp;vmonat, &amp;vjahr);
  datum_zerlegen(bis, &amp;btag, &amp;bmonat, &amp;bjahr);
  for(x = 0; x &lt; anz_daten; x++){
    datum_zerlegen(std[x].datum, &amp;xtag, &amp;xmonat, &amp;xjahr);
     if( (xjahr  &gt;= vjahr ) &amp;&amp; (xjahr  &lt;= bjahr ) &amp;&amp;
  (xmonat &gt;= vmonat) &amp;&amp; (xmonat &lt;= bmonat) &amp;&amp;  (xtag
   &gt;= vtag  ) &amp;&amp; (xtag   &lt;= btag  ))   {
      printf(&quot;%s %5.2f %s %-10s %s\n&quot;,
      std[x].datum, std[x].std,
 std[x].kostenstelle, std[x].name, std[x].arbeit);
    }
  }
  printf(&quot;\n&quot;);
}
</pre>
<p>Please critique the above code. Please do not comment on layout.
You may judiciously comment on the quality of the problem set.</p>
</div>
</p>
<p><strong>Notes:</strong>&nbsp;</p>
<p><em>More fields may be available via dynamicdata ..</em></p>
</div>
</channel>
</rss>
