|
DataMuseum.dkPresents historical artifacts from the history of: CP/M |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about CP/M Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - download
Length: 19968 (0x4e00) Types: TextFile Names: »STUDENT.PAS«
└─⟦dd59903ef⟧ Bits:30005887 Klub diskette for udveksling af software └─ ⟦this⟧ »STUDENT.PAS«
PROGRAM Student; æ---------------------------------------------------------------å æ PROGRAM TITLE: STUDENT version 2.0 å æ WRITTEN BY: Raymond E. Penley å æ DATE WRITTEN: Dec 18, 1982 å æ å æ INPUT/OUTPUT FILES: *** ACCESS METHOD *** å æ STUDENT.NDX - Misc data <sequential> å æ STUDENT.DAT - Name & Address <random> å æ STUDENT.GDS - Grade data <sequential> å æ å æ COMMANDS: å æ New student - Adds a new entry if file not filled. å æ Find - Searches & displays a student å æ Change - Allows changes on address/grades å æ List - Displays data for all students å æ Quit - Terminate program/close all files å æ å æ SUMMARY: å æ Writes a name & address file and a grade file on all students.å æ Also a file of misc. data; # of rcds on file and date file å æ was last updated. å æ å æ 01/29/83 -- EXTENSIVE ERROR CORRECTING ADDED: å æ å æ NOTES: å æ utility procedures from the Pascal/Z User's Group å æ Library diskette. å æ---------------------------------------------------------------å CONST MaxStudents = 50; æ determines maximum # of data records in file å enter = 'ENTER NEW DATA OR PRESS RETURN TO KEEP PRESENT DATA'; escape = 27; æ ASCII escape character å TYPE æ-------------------------------------------------------------å æ create a binary search tree in memory to hold our index å æ-------------------------------------------------------------å link = ^ip; æ pointer to the B-tree å ip = RECORD æ the B-tree record å item : integer; æ KEY FIELD. student's id number å rcd : integer; æ data file record pointer å left,right: link æ pointers to left/right nodes å END; byte = 0..255; charset = SET OF CHAR; strng2 = string 2; strng5 = string 5; strng20 = string 20; strng = string 20; æ-------------------------------------------------------------å æ sturec - identifies the data to be stored for each student å æ-------------------------------------------------------------å sturec = RECORD æ field name, type, length å id : integer; æ id, n, 5 <KEY FIELD> å name, æ name, c, 20 å street, æ street, c, 20 å city : strng20;æ city, c, 20 å state : strng2; æ state, c, 2 å zipcode: strng5 æ zipcode,c, 5 å END; æ total number of bytes = 77 per record. 72 bytes + 1 FOR each string å æ-------------------------------------------------------------å æ Allow for ten grades and the student ID. Please note that å æ this may be changed to suit your particular requirements. å æ NOTE: the enumerated type has been setup such that å æ ORD(exam1) = 1. å æ-------------------------------------------------------------å gradetype = ( id, æ id field is link between all data files å exam1, æ 1st exam grade å exam2, æ 2nd exam grade å exam3, æ 3rd exam grade å exam4, æ 4th exam grade å exam5, æ 5th exam grade å exam6, æ 6th exam grade å exam7, æ 7th exam grade å quiz1, æ quiz 1 å quiz2, æ quiz 2 å final); æ FINAL grade å æ-------------------------------------------------------------å gradestore = array ÆgradetypeÅ of integer; æ-------------------------------------------------------------å StuGds = array Æ1..MaxStudentsÅ of gradestore; æ-------------------------------------------------------------å FTYPE = FILE OF StuRec; string0 = string 0; string255 = string 255; VAR bell : char; æ console bell å command : char; æ command character å console : TEXT; æ direct output to console å date : packed array Æ1..8Å of char; æ date of last update å g : gradetype; Grades : StuGds; ioresult : boolean; listhead : link; more : boolean; æ done processing flag å R : integer; æ global var for record number å rof : integer; æ total Records On File å stucount : integer; æ # of students in class å Student : StuRec; æ A single student å StuFile : FTYPE; æ name & address file å taken : integer; æ # of tests taken thus far å updated : boolean; æ flag for updated items å æ$R-å æ$iPRIMS.PZ å æ pause - allows one to stop until ready to continue å PROCEDURE pause; VAR ch : char; BEGIN writeln; write ('Press any key to continue '); keyin(ch); writeln ENDæ pause å; æ ClearScreen - routine to clear the console device å PROCEDURE ClearScreen; VAR i: 1..25; BEGIN FOR i:=1 TO 25 DO writeln ENDæ ClearScreen å; æ Q - prints a text message and accepts only the characters å æ passed via goodchars. returns the char input in ch å PROCEDURE Q( message: string255; goodchars: charset; VAR ch: char ); VAR ctemp: char; BEGIN write( message ); REPEAT keyin(ctemp); ch := toupper(ctemp); IF ch IN goodchars THEN writeln(ctemp) ELSE write (bell) UNTIL ch in goodchars ENDæ Q å; æ readint - å FUNCTION readint ( VAR i: integer; lower,upper: integer ): boolean; VAR answer: strng20; BEGIN readint := true; readln(answer); IF length(answer) > 0 THEN BEGIN i := ival ( answer,1 ); if (i < lower) OR (upper < i ) THEN ædo it againå readint := false; END ENDæ readint å; æ gde - converts an integer to the enumerated type gradetype å FUNCTION gde ( exam: integer ): gradetype; BEGIN CASE exam OF 0: gde := id; 1: gde := exam1; 2: gde := exam2; 3: gde := exam3; 4: gde := exam4; 5: gde := exam5; 6: gde := exam6; 7: gde := exam7; 8: gde := quiz1; 9: gde := quiz2; 10: gde := final END ENDæ gde å; æ$R+å æ insert - adds a node TO the binary search tree, preserving the ordering å PROCEDURE insert( VAR node: link; ident, R: integer ); BEGIN IF node=nil THEN BEGIN new(node); æ create a new storage location å WITH node^ DO BEGIN left := nil; right := nil; item := ident; æ store the student's ID å rcd := R æ store the location record # å ENDæwithå END ELSE WITH node^ DO IF ident<item THEN insert ( left,ident,R ) ELSE IF ident>item THEN insert ( right,ident,R ) ELSE æ DUPLICATE ENTRY åæ not handled å ENDæ insert å; æ search - returns a pointer TO a node in the tree containing the given data, or nil if there is no such node. å FUNCTION search ( node: link; ident: integer ): link; BEGIN IF node=nil THEN search := nil ELSE WITH node^ DO IF ident<item THEN search := search(left,ident) ELSE IF ident>item THEN search := search(right,ident) ELSE search := node ENDæ search å; æ-------------------------------------------------------------å æ ListRange - å æ enter with first = lower bound; last = uppermost bound. å æ returns first/last per operator specifications å æ-------------------------------------------------------------å PROCEDURE ListRange ( VAR first, last: integer ); VAR ch: char; t1,t2: integer; BEGIN t1 := first; t2 := last; writeln; Q( 'ENTER LIST RANGE: A(ll, O(ne, R(ange ->', Æ'A','O','R'Å, ch ); CASE ch of 'A': BEGIN first := t1; last := t2 END 'O': REPEAT write ( 'WHICH ONE? '); readln(first); last := first; UNTIL (first<=t2) or (first>=t1); 'R': REPEAT write ( 'Enter lower bound ->'); readln(first); write ( 'Enter upper bound ->'); readln(last) UNTIL first <= last endæCASEå ENDæ ListRange å; æ fread - reads the address file and sets the global record pointer å PROCEDURE fread ( VAR StuFile: FTYPE; VAR node: link ); BEGIN R := node^.rcd; æ returns the record # in "R" å read ( StuFile:R, student ) æ read student record "R" å ENDæ fread å; PROCEDURE ChangeAddress ( VAR student: sturec; VAR goodstatus: boolean ); LABEL 1; æ early exit å CONST ok = true; VAR answer: strng20; i : integer; node : link; valid : boolean; PROCEDURE disp ( message, value: string255 ); BEGIN writeln; IF length(value) > 0 THEN BEGIN writeln ( message, value ); write ( ' ':19 ) END ELSE write ( message ); ENDæ disp å; BEGIN æChangeAddresså goodstatus := ok; IF command = 'C' THEN BEGIN writeln; writeln ( enter ) END; writeln;writeln; WITH student DO BEGIN IF id=0 THEN setlength ( answer,0 ) ELSE STR ( id,answer ); æ NOTE: do not allow ID TO be changed after initial input å IF command = 'N' THEN BEGIN æ adding New records å REPEAT disp ( 'ID Number ... ', answer ) UNTIL readint ( id,1,9999 ); node := search ( listhead,id ); æ id already on file? å IF node<>nil THEN BEGIN æ already on file å fread ( StuFile, node ); æ read record FOR show & tell å ClearScreen; writeln ( bell, id, ' already on file!'); goodstatus := not ok; æEXITågoto 1; END ENDæIF command='N'...å ELSE writeln ( 'ID Number ... ', answer ); disp ( 'Name ... ', name ); readln(answer); IF length(answer)>0 THEN name := answer; disp ( 'Street Address ... ', street ); readln(answer); IF length(answer)>0 THEN street := answer; disp ( 'City ... ', city ); readln(answer); IF length(answer)>0 THEN city := answer; disp ( 'State ... ', state ); readln(answer); IF length(answer)>0 THEN BEGIN stateÆ1Å := toupper ( answerÆ1Å ); stateÆ2Å := toupper ( answerÆ2Å ); setlength ( state,2 ) END; REPEAT valid := true; disp ( 'Zip code ... ', zipcode ); readln(answer); IF length(answer)>0 THEN BEGIN zipcode := ' ';æ insure no garbage in answer å IF isdigit(answerÆ1Å) THEN æ good chance is digit å FOR i:=1 TO 5 DO zipcodeÆiÅ := answerÆiÅ ELSE BEGIN write(bell); valid := false END END UNTIL valid; END; updated := true; 1:æearly exitå ENDæ ChangeAddress å; PROCEDURE ChangeGrades ( VAR student: sturec ); CONST low = 0; æ lowest grade acceptable å high = 110; æ highest grade acceptable å VAR answer : strng20; first,last : gradetype; lower,upper : integer; BEGIN lower := 1; upper := taken; ListRange ( lower,upper ); first := gde(lower); last := gde(upper); writeln; writeln ( enter ); writeln;writeln; writeln ( 'STUDENT: ', student.name ); writeln; FOR g:=first TO last DO BEGIN REPEAT write ( ord(g):3, gradesÆR,gÅ:6, ' ?' ) UNTIL readint ( gradesÆR,gÅ,low,high ) END ENDæ ChangeGrades å; PROCEDURE display ( VAR output: TEXT; VAR student: sturec ); æ GLOBAL R : integer; <record #> å CONST width = 35; BEGIN writeln ( output); writeln ( output); WITH student DO BEGIN writeln (output, 'STUDENT ID: ', id:1 ); writeln (output, name, ' ':width-length(name), street ); writeln (output, ' ':width, city, ', ', state, ' ', zipcode ); writeln ( output, 'GRADES'); writeln ( output, ' < first half year >< second half year >'); FOR g:=exam1 TO final DO BEGIN write(output, gradesÆR,gÅ:4 ) END; writeln ( output); writeln ( output); writeln ( output) END ENDæ display å; PROCEDURE MODIFY; VAR node : link; ident: integer; ch : char; goodstatus : boolean; BEGIN IF command='N' THEN BEGIN æ arrived here from ADD å command := 'C'; æ so, switch to CHANGE å ident := student.id æ already in memory å END ELSE BEGIN writeln; REPEAT write ('Enter student id number ... ') UNTIL readint ( ident,1,9999 ) END; node := search ( listhead,ident ); IF node<>nil THEN BEGIN fread ( StuFile, node ); CASE command of 'C': BEGIN æCHANGEå writeln; Q( 'Do you wish to change A(ddress, or G(rades? <escape=quit> ', Æchr(escape),'A','G'Å, ch ); if ord(ch)=escape then æall doneå else begin CASE ch of 'A': ChangeAddress ( student,goodstatus ); 'G': ChangeGrades ( student ) ENDæCASEå; display ( console,student ); if ch='A' THEN æ update address file å write ( StuFile:R, student ) end ENDæ CHANGE å; 'F': display ( console,student );æ send the picture to the console å ENDæCASEå END ELSE writeln ( bell, ident:1,' not on file!') ENDæ MODIFY å; PROCEDURE ADD; VAR goodstatus: boolean; BEGIN IF rof >= MaxStudents THEN writeln ( 'Sorry can''t add file is full.' ) ELSE BEGIN æ OK to add more records å IF rof=0 THEN R := 1 ELSE R := rof + 1; WITH student DO BEGIN æ initialize all fields to zero å id := 0; setlength ( name,0 ); setlength ( street,0 ); setlength ( city,0 ); setlength ( state,0 ); setlength ( zipcode,0 ) END; writeln; writeln ( 'RECORD #', R:1 ); ChangeAddress ( student,goodstatus ); display ( console, student ); IF goodstatus THEN BEGIN gradesÆR,idÅ := student.id; æ update grades matrix å insert ( listhead,student.id,R ); write ( StuFile:R, student ); æ update address file å updated := true; æ flag we updated the file å rof := R; æ increment records on file å stucount := rof; æ and student count å æ move right into edit mode...change address/grades å MODIFY ENDæIF goodstatus then...å; pause ENDæELSEå ENDæ ADD å; æ list - lists ALL records on file å PROCEDURE LIST; VAR output : TEXT; æ printlist - writes the entire tree recursively å PROCEDURE PrintList ( node: link ); BEGIN IF node<>nil THEN WITH node^ DO BEGIN PrintList (left); fread ( StuFile, node ); æ read address file å display ( output, student ); IF command<>'P' THEN pause; PrintList ( right ) ENDæwithå ENDæ PrintList å; BEGIN writeln; Q('Output to C(onsole or P(rinter? <escape=quit> ', Æchr(escape),'C','P'Å, command ); IF ord(command)=escape THEN æall doneå ELSE BEGIN CASE command OF 'P': æ direct output to the list device å REWRITE( 'LST:',output ); 'C': æ direct output to the console device å REWRITE( 'CON:',output ) endæCASEå; PrintList(listhead) END ENDæ LIST åæ CLOSE(output); å; PROCEDURE mathmult; LABEL 1; æquick exitå CONST fw = 6; TYPE etype = (total,avg); VAR g,first,last: gradetype; a : integer; accum : array Ætotal..avg,gradetypeÅ of integer; output : TEXT; PROCEDURE print ( message: string255; i: etype ); BEGIN write( output,message ); FOR g:=first TO last DO write( output,accumÆi,gÅ:fw ); writeln ( output) END; BEGINæ mathmult å writeln; Q('Output to C(onsole or P(rinter? <escape=quit> ', Æchr(escape),'C','P'Å, command ); IF ord(command)=escape THEN goto 1; æall doneå CASE command OF 'P': æ direct output to the list device å REWRITE( 'LST:',output ); 'C': æ direct output to the console device å REWRITE( 'CON:',output ) ENDæCASEå; first := exam1; æ first = 1st exam grade, last = last exam taken å last := gde(taken); writeln ( output); write(output,' STUDENT'); FOR g:=first TO last DO BEGIN write( output,ord(g):fw ); accumÆtotal,gÅ := 0; æ zero accumulators å accumÆavg,gÅ := 0 END; writeln ( output,' AVERAGE'); FOR r:=1 TO stucount DO BEGIN write(output,gradesÆr,idÅ:fw,' :'); æ print the student's id number å a := 0; æ "a" = grade accumulator å FOR g:=first TO last DO BEGIN write(output,gradesÆr,gÅ:fw); a := a + gradesÆr,gÅ; accumÆtotal,gÅ := accumÆtotal,gÅ + gradesÆr,gÅ ENDæFOR gå; æ print the rounded average of this student's grades å writeln (output, round(a/taken):fw ) ENDæFOR rå; æ compute the average FOR all the student's grades & underline å write(output,' '); FOR g:=first TO last DO BEGIN accumÆavg,gÅ := accumÆtotal,gÅ DIV stucount; write(output,' ---'); end; write(output,' ---'); writeln ( output); print ( ' TOTAL:', total );æ for each graded exam å print ( ' AVG:', avg );æ for each graded exam å writeln ( output); 1:æquick exitå ENDæ mathmult åæ CLOSE(output); å; PROCEDURE STATS; VAR answer : strng20; valid : boolean; BEGIN writeln; writeln ( 'NUMBER OF STUDENTS ... ', stucount:3 ); REPEAT write ('NUMBER OF TESTS ...... ', taken:3,' ?' ); readln ( answer ); IF length(answer)>0 THEN taken := ival ( answer,1 ); valid := (taken>=0) UNTIL valid ENDæ STATS å; PROCEDURE fclose; VAR StuGrades: FILE OF gradestore; æ grade data on each student å StuNdx : TEXT; æ index file å BEGIN rewrite('STUDENT.NDX',StuNdx); writeln ( StuNdx, rof ); writeln ( StuNdx, date ); writeln ( StuNdx, stucount ); æ # of students in class å writeln ( StuNdx, taken ); æ # of tests taken thus far å rewrite('STUDENT.GDS',StuGrades); FOR R:=1 TO rof DO write ( StuGrades, gradesÆRÅ ) ENDæ fclose åæ CLOSE(StuNdx); CLOSE(StuGrades); å; PROCEDURE Initialize; VAR i : integer; ch : char; StuGrades: FILE OF gradestore; æ grade data on each student å StuNdx : TEXT; æ index file å BEGIN ClearScreen; writeln ( ' ':32, 'STUDENT SYSTEM'); writeln; writeln; bell := chr(7); listhead := nil; æ make the list empty å updated := false; æ say file has not been updated å æ insure that all cells in grades matrix are 0 å FOR g:=id TO final DO gradesÆ1,gÅ := 0; FOR R:=2 TO MaxStudents DO gradesÆRÅ := gradesÆ1Å; rewrite('CON:',console); reset('STUDENT.NDX',StuNdx); IF eof(StuNdx) THEN BEGIN æcreate all fileså writeln ( 'Please standby while I create data files ...' ); rewrite('STUDENT.NDX',StuNdx); rewrite('STUDENT.DAT',StuFile); rewrite('STUDENT.GDS',StuGrades); rof := 0; stucount := 0; taken := 10; æ setup to 10 then can lower at any time å date := 'MM/DD/YY' END ELSE BEGIN æ finish opening files and read record count å reset('STUDENT.DAT',StuFile); reset('STUDENT.GDS',StuGrades); readln ( StuNdx, rof ); readln ( StuNdx, date ); readln ( StuNdx, stucount ); æ # of students in class å readln ( StuNdx, taken ); æ # of tests taken thus far å writeln; FOR R:=1 TO rof DO BEGIN write( chr(13), 'RECORD #', R:1 ); read ( StuGrades, gradesÆRÅ ); read ( StuFile:R,student ); æ create the B-tree in memory å insert ( listhead,student.id,R ) END; writeln END; IF rof>0 THEN BEGIN writeln; writeln ( 'There are ',rof:1,' records on file as of ', date ) END; writeln; write ( 'ENTER TODAY''S DATE <MM/DD/YY> ->'); FOR i:=1 TO 8 DO BEGIN IF (i=3) or (i=6) THEN ch := '/' ELSE keyin(ch); write(ch); dateÆiÅ := ch END; writeln ENDæ Initialize åæ CLOSE(StuNdx); CLOSE(StuGrades); å; BEGIN (*** MAIN PROGRAM ***) Initialize; more := true; WHILE more DO BEGIN writeln; Q('N(ew student, F(ind, C(hange, G(rades, L(ist, S(tats, Q(uit ...?', Æ'N','C','F','G','L','S','Q'Å, command ); CASE command of 'N': ADD; 'C','F': MODIFY; 'G': mathmult; 'L': LIST; 'S': STATS; 'Q': more := false endæCASEå ENDæwhileå; IF updated THEN fclose END. «eof»