home *** CD-ROM | disk | FTP | other *** search
/ Oakland CPM Archive / oakcpm.iso / sigm / vol132 / student.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1984-04-29  |  18.7 KB  |  744 lines

  1. PROGRAM Student;
  2.  
  3. {---------------------------------------------------------------}
  4. { PROGRAM TITLE:    STUDENT    version 2.0            }
  5. { WRITTEN BY:        Raymond E. Penley            }
  6. { DATE WRITTEN:        Dec 18, 1982                }
  7. {                                }
  8. { INPUT/OUTPUT FILES:           *** ACCESS METHOD ***    }
  9. {   STUDENT.NDX - Misc data        <sequential>        }
  10. {   STUDENT.DAT - Name & Address    <random>        }
  11. {   STUDENT.GDS    - Grade data        <sequential>        }
  12. {                                }
  13. { COMMANDS:                            }
  14. {  New student    - Adds a new entry if file not filled.        }
  15. {  Find        - Searches & displays a student            }
  16. {  Change    - Allows changes on address/grades        }
  17. {  List        - Displays data for all students        }
  18. {  Quit        - Terminate program/close all files        }
  19. {                                }
  20. { SUMMARY:                            }
  21. { Writes a name & address file and a grade file on all students.}
  22. { Also a file of misc. data; # of rcds on file and date file    }
  23. { was last updated.                        }
  24. {                                }
  25. { 01/29/83 -- EXTENSIVE ERROR CORRECTING ADDED:            }
  26. {                                }
  27. { NOTES:                            }
  28. {  utility procedures from the Pascal/Z User's Group        }
  29. {  Library diskette.                        }
  30. {---------------------------------------------------------------}
  31.  
  32.  
  33. CONST
  34.   MaxStudents = 50; { determines maximum # of data records in file }
  35.   enter = 'ENTER NEW DATA OR PRESS RETURN TO KEEP PRESENT DATA';
  36.   escape = 27;        { ASCII escape character }
  37.  
  38. TYPE
  39.  
  40.    {-------------------------------------------------------------}
  41.    { create a binary search tree in memory to hold our index     }
  42.    {-------------------------------------------------------------}
  43.  
  44.    link = ^ip;            { pointer to the B-tree }
  45.    ip = RECORD            { the B-tree record }
  46.       item : integer;    { KEY FIELD. student's id number }
  47.       rcd  : integer;    { data file record pointer }
  48.       left,right: link    { pointers to left/right nodes }
  49.     END;
  50.  
  51.   byte        = 0..255;
  52.   charset    = SET OF CHAR;
  53.   strng2    = string 2;
  54.   strng5    = string 5;
  55.   strng20    = string 20;
  56.   strng        = string 20;
  57.  
  58.  
  59.   {-------------------------------------------------------------}
  60.   { sturec - identifies the data to be stored for each student    }
  61.   {-------------------------------------------------------------}
  62.  
  63.   sturec  = RECORD        { field name, type, length        }
  64.            id    : integer;    { id,     n,  5     <KEY FIELD>    }
  65.            name,        { name,   c, 20            }
  66.            street,        { street, c, 20            }
  67.            city   : strng20;{ city,   c, 20            }
  68.            state  : strng2;    { state,  c,  2            }
  69.            zipcode: strng5    { zipcode,c,  5            }
  70.         END;
  71.   { total number of bytes = 77 per record.
  72.     72 bytes + 1 FOR each string }
  73.  
  74.  
  75.   {-------------------------------------------------------------}
  76.   { Allow for ten grades and the student ID. Please note that    }
  77.   { this may be changed to suit your particular requirements.    }
  78.   { NOTE: the enumerated type has been setup such that        }
  79.   { ORD(exam1) = 1.                        }
  80.   {-------------------------------------------------------------}
  81.  
  82.   gradetype = ( id,    { id field is link between all data files }
  83.         exam1,    { 1st exam grade }
  84.         exam2,    { 2nd exam grade }
  85.         exam3,    { 3rd exam grade }
  86.         exam4,    { 4th exam grade }
  87.         exam5,    { 5th exam grade }
  88.         exam6,    { 6th exam grade }
  89.         exam7,    { 7th exam grade }
  90.         quiz1,    { quiz 1 }
  91.         quiz2,    { quiz 2 }
  92.         final);    { FINAL grade }
  93.  
  94.   {-------------------------------------------------------------}
  95.   gradestore    = array [gradetype] of integer;
  96.  
  97.   {-------------------------------------------------------------}
  98.   StuGds    = array [1..MaxStudents] of gradestore;
  99.  
  100.   {-------------------------------------------------------------}
  101.   FTYPE        = FILE OF StuRec;
  102.  
  103.   string0    = string 0;
  104.   string255    = string 255;
  105.  
  106. VAR
  107.   bell        : char;        { console bell }
  108.   command    : char;        { command character }
  109.   console    : TEXT;        { direct output to console }
  110.   date        : packed array [1..8] of char; { date of last update }
  111.   g        : gradetype;
  112.   Grades    : StuGds;
  113.   ioresult    : boolean;
  114.   listhead    : link;
  115.   more        : boolean;    { done processing flag }
  116.   R        : integer;    { global var for record number }
  117.   rof        : integer;    { total Records On File }
  118.   stucount    : integer;    { # of students in class }
  119.   Student    : StuRec;    { A single student }
  120.   StuFile    : FTYPE;    { name & address file }
  121.   taken        : integer;    { # of tests taken thus far }
  122.   updated    : boolean;    { flag for updated items }
  123.  
  124. {$R-}
  125.  
  126. {$iPRIMS.PZ }
  127.  
  128.  
  129. { pause - allows one to stop until ready to continue }
  130. PROCEDURE pause;
  131. VAR    ch : char;
  132. BEGIN
  133.    writeln;
  134.    write ('Press any key to continue ');
  135.    keyin(ch); writeln
  136. END{ pause };
  137.  
  138.  
  139. { ClearScreen - routine to clear the console device }
  140. PROCEDURE ClearScreen;
  141. VAR    i: 1..25;
  142. BEGIN
  143.    FOR i:=1 TO 25 DO writeln
  144. END{ ClearScreen };
  145.  
  146.  
  147. { Q - prints a text message and accepts only the characters }
  148. { passed via goodchars. returns the char input in ch        }
  149.  
  150. PROCEDURE Q( message: string255; goodchars: charset; VAR ch: char );
  151. VAR    ctemp: char;
  152. BEGIN
  153.    write( message );
  154.    REPEAT
  155.      keyin(ctemp); ch := toupper(ctemp);
  156.      IF ch IN goodchars
  157.     THEN writeln(ctemp)
  158.     ELSE write (bell)
  159.    UNTIL ch in goodchars
  160. END{ Q };
  161.  
  162.  
  163. { readint -                         }
  164.  
  165. FUNCTION readint ( VAR i: integer; lower,upper: integer ): boolean;
  166. VAR    answer: strng20;
  167. BEGIN
  168.       readint := true;
  169.       readln(answer);
  170.       IF length(answer) > 0 THEN BEGIN
  171.      i := ival ( answer,1 );
  172.      if (i < lower) OR (upper < i ) THEN {do it again}
  173.         readint := false;
  174.       END
  175. END{ readint };
  176.  
  177.  
  178. { gde - converts an integer to the enumerated type gradetype }
  179.  
  180. FUNCTION gde ( exam: integer ): gradetype;
  181. BEGIN
  182.      CASE exam OF
  183.     0: gde := id;
  184.     1: gde := exam1;
  185.     2: gde := exam2;
  186.     3: gde := exam3;
  187.     4: gde := exam4;
  188.     5: gde := exam5;
  189.     6: gde := exam6;
  190.     7: gde := exam7;
  191.     8: gde := quiz1;
  192.     9: gde := quiz2;
  193.        10: gde := final
  194.      END
  195. END{ gde };
  196.  
  197. {$R+}
  198.  
  199. { insert - adds a node TO the binary search tree, preserving the ordering }
  200.  
  201. PROCEDURE insert( VAR node: link; ident, R: integer );
  202. BEGIN
  203.   IF node=nil THEN BEGIN
  204.      new(node);        { create a new storage location }
  205.      WITH node^ DO BEGIN
  206.         left := nil;
  207.         right := nil;
  208.         item := ident;    { store the student's ID }
  209.         rcd := R    { store the location record # }
  210.      END{with}
  211.   END
  212.   ELSE
  213.      WITH node^ DO
  214.         IF ident<item THEN
  215.            insert ( left,ident,R )
  216.         ELSE IF ident>item THEN
  217.            insert ( right,ident,R )
  218.         ELSE
  219.        { DUPLICATE ENTRY }{ not handled }
  220. END{ insert };
  221.  
  222.  
  223. { search - returns a pointer TO a node in the tree containing
  224.   the given data, or nil if there is no such node. }
  225.  
  226. FUNCTION search ( node: link; ident: integer ): link;
  227. BEGIN
  228.   IF node=nil THEN
  229.      search := nil
  230.   ELSE
  231.      WITH node^ DO
  232.         IF ident<item THEN
  233.            search := search(left,ident)
  234.         ELSE IF ident>item THEN
  235.            search := search(right,ident)
  236.         ELSE
  237.            search := node
  238. END{ search };
  239.  
  240.  
  241.   {-------------------------------------------------------------}
  242.   { ListRange -                            }
  243.   {    enter with first = lower bound; last = uppermost bound.    }
  244.   {    returns first/last per operator specifications        }
  245.   {-------------------------------------------------------------}
  246.  
  247. PROCEDURE ListRange ( VAR first, last: integer );
  248. VAR
  249.     ch: char;
  250.     t1,t2: integer;
  251. BEGIN
  252.   t1 := first;
  253.   t2 := last;
  254.   writeln;
  255.   Q( 'ENTER LIST RANGE: A(ll, O(ne, R(ange ->', ['A','O','R'], ch );
  256.   CASE ch of
  257.      'A':
  258.     BEGIN
  259.       first := t1;
  260.       last := t2
  261.     END
  262.      'O':
  263.     REPEAT
  264.       write ( 'WHICH ONE? '); readln(first);
  265.       last := first;
  266.     UNTIL (first<=t2) or (first>=t1);
  267.      'R':
  268.     REPEAT
  269.        write ( 'Enter lower bound ->'); readln(first);
  270.        write ( 'Enter upper bound ->'); readln(last)
  271.     UNTIL first <= last
  272.   end{CASE}
  273. END{ ListRange };
  274.  
  275.  
  276. { fread - reads the address file and sets the global record pointer }
  277.  
  278. PROCEDURE fread ( VAR StuFile: FTYPE; VAR node: link );
  279. BEGIN
  280.    R := node^.rcd;        { returns the record # in "R" }
  281.    read ( StuFile:R, student )    { read student record "R" }
  282. END{ fread };
  283.  
  284.  
  285. PROCEDURE ChangeAddress ( VAR student: sturec; VAR goodstatus: boolean );
  286. LABEL
  287.    1;    { early exit }
  288. CONST
  289.    ok = true;
  290. VAR
  291.    answer: strng20;
  292.    i     : integer;
  293.    node  : link;
  294.    valid : boolean;
  295.  
  296.     PROCEDURE disp ( message, value: string255 );
  297.     BEGIN
  298.        writeln;
  299.        IF length(value) > 0 THEN BEGIN
  300.           writeln ( message, value );
  301.           write ( ' ':19 )
  302.        END
  303.        ELSE
  304.           write ( message );
  305.     END{ disp };
  306.  
  307. BEGIN {ChangeAddress}
  308.    goodstatus := ok;
  309.    IF command = 'C' THEN BEGIN
  310.       writeln;
  311.       writeln ( enter )
  312.    END;    
  313.    writeln;writeln;
  314.    WITH student DO BEGIN
  315.     IF id=0
  316.        THEN setlength ( answer,0 )
  317.        ELSE STR ( id,answer );
  318.  
  319.         { NOTE: do not allow ID TO be changed after initial input }
  320.     IF command = 'N' THEN BEGIN { adding New records }
  321.        REPEAT
  322.           disp ( 'ID Number      ... ', answer )
  323.        UNTIL readint ( id,1,9999 );
  324.  
  325.        node := search ( listhead,id );    { id already on file? }
  326.        IF node<>nil THEN BEGIN { already on file }
  327.           fread ( StuFile, node );    { read record FOR show & tell }
  328.           ClearScreen;
  329.           writeln ( bell, id, ' already on file!');
  330.           goodstatus := not ok;
  331.           {EXIT}goto 1;
  332.        END
  333.     END{IF command='N'...}
  334.     ELSE
  335.        writeln ( 'ID Number      ... ', answer );
  336.  
  337.     disp ( 'Name           ... ', name ); readln(answer);
  338.     IF length(answer)>0 THEN
  339.        name := answer;
  340.     disp ( 'Street Address ... ', street ); readln(answer);
  341.     IF length(answer)>0 THEN
  342.        street := answer;
  343.     disp ( 'City           ... ', city ); readln(answer);
  344.     IF length(answer)>0 THEN
  345.        city := answer;
  346.     disp ( 'State          ... ', state ); readln(answer);
  347.     IF length(answer)>0 THEN BEGIN
  348.        state[1] := toupper ( answer[1] );
  349.        state[2] := toupper ( answer[2] );
  350.        setlength ( state,2 )
  351.     END;
  352.     REPEAT
  353.        valid := true;
  354.        disp ( 'Zip code       ... ', zipcode ); readln(answer);
  355.        IF length(answer)>0 THEN BEGIN
  356.           zipcode := '     ';{ insure no garbage in answer }
  357.           IF isdigit(answer[1]) THEN { good chance is digit }
  358.              FOR i:=1 TO 5 DO
  359.             zipcode[i] := answer[i]
  360.           ELSE BEGIN
  361.          write(bell); valid := false
  362.           END
  363.        END
  364.     UNTIL valid;
  365.    END;
  366.    updated := true;
  367. 1:{early exit}
  368. END{ ChangeAddress };
  369.  
  370.  
  371. PROCEDURE ChangeGrades ( VAR student: sturec );
  372. CONST
  373.    low = 0;    { lowest grade acceptable }
  374.    high = 110;    { highest grade acceptable }
  375. VAR
  376.    answer    : strng20;
  377.    first,last    : gradetype;
  378.    lower,upper    : integer;
  379. BEGIN
  380.    lower := 1;
  381.    upper := taken;
  382.    ListRange ( lower,upper );
  383.    first := gde(lower);
  384.    last := gde(upper);
  385.    writeln;
  386.    writeln ( enter );
  387.    writeln;writeln;
  388.    writeln ( 'STUDENT: ', student.name );
  389.    writeln;
  390.    FOR g:=first TO last DO BEGIN
  391.       REPEAT
  392.      write ( ord(g):3, grades[R,g]:6, ' ?' )
  393.       UNTIL readint ( grades[R,g],low,high )
  394.    END
  395. END{ ChangeGrades };
  396.  
  397.  
  398. PROCEDURE display ( VAR output: TEXT; VAR student: sturec );
  399. { GLOBAL    R : integer; <record #>   }
  400. CONST
  401.    width = 35;
  402. BEGIN
  403.    writeln ( output);
  404.    writeln ( output);
  405.    WITH student DO BEGIN
  406.     writeln (output, 'STUDENT ID: ', id:1 );
  407.     writeln (output, name, ' ':width-length(name), street );
  408.     writeln (output, ' ':width, city, ', ', state, ' ', zipcode );
  409.     writeln ( output, 'GRADES');
  410.     writeln ( output, ' < first half year >< second half year >');
  411.     FOR g:=exam1 TO final DO BEGIN
  412.        write(output, grades[R,g]:4 )
  413.     END;
  414.     writeln ( output);
  415.     writeln ( output);
  416.     writeln ( output)
  417.    END
  418. END{ display };
  419.  
  420.  
  421. PROCEDURE MODIFY;
  422. VAR
  423.     node : link;
  424.     ident: integer;
  425.     ch    : char;
  426.     goodstatus    : boolean;
  427. BEGIN
  428.    IF command='N' THEN BEGIN { arrived here from ADD }
  429.       command := 'C';         { so, switch to CHANGE  }
  430.       ident := student.id { already in memory }
  431.    END
  432.    ELSE BEGIN
  433.       writeln;
  434.       REPEAT
  435.      write ('Enter student id number ... ')
  436.       UNTIL readint ( ident,1,9999 )
  437.    END;
  438.  
  439.    node := search ( listhead,ident );
  440.    IF node<>nil THEN BEGIN
  441.       fread ( StuFile, node );
  442.       CASE command of
  443.     'C':
  444.        BEGIN {CHANGE}
  445.        writeln;
  446.        Q( 'Do you wish to change A(ddress, or G(rades? <escape=quit> ',
  447.             [chr(escape),'A','G'], ch );
  448.        if ord(ch)=escape then
  449.           {all done}
  450.        else begin
  451.           CASE ch of
  452.          'A':
  453.             ChangeAddress ( student,goodstatus );
  454.         'G':
  455.            ChangeGrades ( student )
  456.           END{CASE};
  457.           display ( console,student );
  458.           if ch='A' THEN { update address file }
  459.          write ( StuFile:R, student )
  460.        end
  461.        END{ CHANGE };
  462.     'F':
  463.         display ( console,student );{ send the picture to the console }
  464.       END{CASE}
  465.    END
  466.    ELSE
  467.       writeln ( bell, ident:1,' not on file!')
  468. END{ MODIFY };
  469.  
  470.  
  471. PROCEDURE ADD;
  472. VAR    goodstatus: boolean;
  473. BEGIN
  474.    IF rof >= MaxStudents THEN
  475.       writeln ( 'Sorry can''t add file is full.' )
  476.    ELSE BEGIN { OK to add more records }
  477.       IF rof=0
  478.      THEN R := 1
  479.      ELSE R := rof + 1;
  480.       WITH student DO BEGIN { initialize all fields to zero }
  481.      id := 0;
  482.      setlength ( name,0 );
  483.      setlength ( street,0 );
  484.      setlength ( city,0 );
  485.      setlength ( state,0 );
  486.      setlength ( zipcode,0 )
  487.       END;
  488.       writeln;
  489.       writeln ( 'RECORD #', R:1 );
  490.       ChangeAddress ( student,goodstatus );
  491.       display ( console, student );
  492.  
  493.       IF goodstatus THEN BEGIN
  494.      grades[R,id] := student.id;    { update grades matrix }
  495.      insert ( listhead,student.id,R );
  496.      write ( StuFile:R, student );    { update address file }
  497.      updated := true;        { flag we updated the file }
  498.      rof := R;            { increment records on file }
  499.      stucount := rof;        { and student count         }
  500.      { move right into edit mode...change address/grades }
  501.      MODIFY
  502.       END{IF goodstatus then...};
  503.       pause
  504.    END{ELSE}
  505. END{ ADD };
  506.  
  507.  
  508. { list - lists ALL records on file }
  509.  
  510. PROCEDURE LIST;
  511. VAR    output : TEXT;
  512.  
  513.     { printlist - writes the entire tree recursively }
  514.     PROCEDURE PrintList ( node: link );
  515.     BEGIN
  516.        IF node<>nil THEN
  517.           WITH node^ DO BEGIN
  518.              PrintList (left);
  519.          fread ( StuFile, node ); { read address file }
  520.          display ( output, student );
  521.          IF command<>'P' THEN pause;
  522.              PrintList ( right )
  523.           END{with}
  524.     END{ PrintList };
  525.  
  526. BEGIN
  527.    writeln;
  528.    Q('Output to C(onsole or P(rinter? <escape=quit> ',
  529.         [chr(escape),'C','P'], command );
  530.    IF ord(command)=escape THEN
  531.       {all done}
  532.    ELSE BEGIN 
  533.       CASE command OF
  534.      'P': { direct output to the list device }
  535.         REWRITE( 'LST:',output );
  536.      'C': { direct output to the console device }
  537.           REWRITE( 'CON:',output )
  538.       end{CASE};
  539.       PrintList(listhead)
  540.    END
  541. END{ LIST }{ CLOSE(output); };
  542.  
  543.  
  544. PROCEDURE mathmult;
  545. LABEL
  546.     1; {quick exit}
  547. CONST
  548.     fw = 6;
  549. TYPE
  550.     etype = (total,avg);
  551. VAR
  552.     g,first,last: gradetype;
  553.     a : integer;
  554.     accum : array [total..avg,gradetype] of integer;
  555.     output : TEXT;
  556.  
  557.     PROCEDURE print ( message: string255; i: etype );
  558.     BEGIN
  559.        write( output,message );
  560.        FOR g:=first TO last DO
  561.           write( output,accum[i,g]:fw );
  562.        writeln ( output)
  563.     END;
  564.  
  565. BEGIN{ mathmult }
  566.    writeln;
  567.    Q('Output to C(onsole or P(rinter? <escape=quit> ',
  568.         [chr(escape),'C','P'], command );
  569.    IF ord(command)=escape THEN
  570.       goto 1; {all done}
  571.    CASE command OF
  572.       'P': { direct output to the list device }
  573.          REWRITE( 'LST:',output );
  574.       'C': { direct output to the console device }
  575.          REWRITE( 'CON:',output )
  576.    END{CASE};
  577.  
  578.    first := exam1;    { first = 1st exam grade, last = last exam taken }
  579.    last := gde(taken);
  580.  
  581.    writeln ( output);
  582.    write(output,' STUDENT');
  583.    FOR g:=first TO last DO BEGIN
  584.       write( output,ord(g):fw );
  585.       accum[total,g] := 0;    { zero accumulators }
  586.       accum[avg,g] := 0
  587.    END;
  588.    writeln ( output,'  AVERAGE');
  589.  
  590.    FOR r:=1 TO stucount DO BEGIN
  591.       write(output,grades[r,id]:fw,' :'); { print the student's id number }
  592.       a := 0;                   { "a" = grade accumulator }
  593.       FOR g:=first TO last DO BEGIN
  594.          write(output,grades[r,g]:fw);
  595.          a := a + grades[r,g];
  596.          accum[total,g] := accum[total,g] + grades[r,g]
  597.       END{FOR g};
  598.       { print the rounded average of this student's grades }
  599.       writeln (output, round(a/taken):fw )
  600.    END{FOR r};
  601.  
  602.    { compute the average FOR all the student's grades & underline }
  603.    write(output,'        ');
  604.    FOR g:=first TO last DO BEGIN
  605.     accum[avg,g] := accum[total,g] DIV stucount;
  606.     write(output,'   ---');
  607.    end;
  608.    write(output,'   ---');
  609.    writeln ( output);
  610.  
  611.    print ( '  TOTAL:', total );{ for each graded exam }
  612.    print ( '    AVG:', avg );{ for each graded exam }
  613.    writeln ( output);
  614. 1:{quick exit}
  615. END{ mathmult }{ CLOSE(output); };
  616.  
  617.  
  618. PROCEDURE STATS;
  619. VAR
  620.     answer    : strng20;
  621.     valid    : boolean;
  622. BEGIN
  623.    writeln;
  624.    writeln ( 'NUMBER OF STUDENTS ... ', stucount:3 );
  625.    REPEAT
  626.     write  ('NUMBER OF TESTS ...... ', taken:3,' ?' );
  627.     readln ( answer );
  628.     IF length(answer)>0 THEN
  629.        taken := ival ( answer,1 );
  630.     valid := (taken>=0)
  631.    UNTIL valid
  632. END{ STATS };
  633.  
  634.  
  635. PROCEDURE fclose;
  636. VAR
  637.     StuGrades: FILE OF gradestore;    { grade data on each student }
  638.     StuNdx   : TEXT;        { index file }
  639. BEGIN
  640.    rewrite('STUDENT.NDX',StuNdx);
  641.    writeln ( StuNdx, rof );
  642.    writeln ( StuNdx, date );
  643.    writeln ( StuNdx, stucount ); { # of students in class }
  644.    writeln ( StuNdx, taken );    { # of tests taken thus far }
  645.  
  646.    rewrite('STUDENT.GDS',StuGrades);
  647.    FOR R:=1 TO rof DO
  648.       write ( StuGrades, grades[R] )
  649. END{ fclose }{ CLOSE(StuNdx); CLOSE(StuGrades); };
  650.  
  651.  
  652. PROCEDURE Initialize;
  653. VAR
  654.     i    : integer;
  655.     ch    : char;
  656.     StuGrades: FILE OF gradestore;    { grade data on each student }
  657.     StuNdx   : TEXT;        { index file }
  658. BEGIN
  659.    ClearScreen;
  660.    writeln ( ' ':32, 'STUDENT SYSTEM');
  661.    writeln;
  662.    writeln;
  663.    bell := chr(7);
  664.    listhead := nil;    { make the list empty }
  665.    updated := false;    { say file has not been updated }
  666.    
  667.    { insure that all cells in grades matrix are 0 }
  668.    FOR g:=id TO final DO
  669.       grades[1,g] := 0;
  670.    FOR R:=2 TO MaxStudents DO
  671.       grades[R] := grades[1];
  672.    rewrite('CON:',console);
  673.    reset('STUDENT.NDX',StuNdx);
  674.  
  675.    IF eof(StuNdx) THEN BEGIN {create all files}
  676.     writeln ( 'Please standby while I create data files ...' );
  677.        rewrite('STUDENT.NDX',StuNdx);
  678.        rewrite('STUDENT.DAT',StuFile);
  679.        rewrite('STUDENT.GDS',StuGrades);
  680.  
  681.     rof := 0;
  682.     stucount := 0;
  683.     taken := 10;    { setup to 10 then can lower at any time }
  684.     date := 'MM/DD/YY'
  685.    END
  686.    ELSE BEGIN { finish opening files and read record count }
  687.     reset('STUDENT.DAT',StuFile);
  688.     reset('STUDENT.GDS',StuGrades);
  689.     readln ( StuNdx, rof );
  690.     readln ( StuNdx, date );
  691.     readln ( StuNdx, stucount );    { # of students in class }
  692.     readln ( StuNdx, taken );    { # of tests taken thus far }
  693.     writeln;
  694.     FOR R:=1 TO rof DO BEGIN
  695.        write( chr(13), 'RECORD #', R:1 );
  696.        read ( StuGrades, grades[R] );
  697.        read ( StuFile:R,student );        { create the B-tree in memory }
  698.        insert ( listhead,student.id,R )
  699.     END;
  700.     writeln
  701.    END;
  702.  
  703.    IF rof>0 THEN BEGIN
  704.       writeln;
  705.       writeln ( 'There are ',rof:1,' records on file as of ', date )
  706.    END;
  707.    writeln;
  708.    write ( 'ENTER TODAY''S DATE <MM/DD/YY>  ->');
  709.    FOR i:=1 TO 8 DO BEGIN
  710.       IF (i=3) or (i=6)
  711.      THEN ch := '/'
  712.      ELSE keyin(ch);
  713.        write(ch);
  714.        date[i] := ch
  715.    END;
  716.    writeln
  717. END{ Initialize }{ CLOSE(StuNdx); CLOSE(StuGrades); };
  718.  
  719.  
  720. BEGIN    (*** MAIN PROGRAM ***)
  721.    Initialize;
  722.    more := true;
  723.    WHILE more DO BEGIN
  724.     writeln;
  725.     Q('N(ew student, F(ind, C(hange, G(rades, L(ist, S(tats, Q(uit ...?',
  726.         ['N','C','F','G','L','S','Q'], command );
  727.     CASE command of
  728.        'N':
  729.           ADD;
  730.        'C','F':
  731.           MODIFY;
  732.        'G':
  733.           mathmult;
  734.        'L':
  735.           LIST;
  736.        'S':
  737.           STATS;
  738.        'Q':
  739.           more := false
  740.     end{CASE}
  741.    END{while};
  742.    IF updated THEN fclose
  743. END.
  744.