Grade Calculator 2 Solution: Problem decomposition |
|
Author: Jordan Kidney ( kidney@cpsc.ucalgary.ca ) Date: Feb 24, 2006 | |
Functions or procedures are used for 2 main reasons:
To solve this problem you have to break the program up into one of the two categories as described above. This can be done by looking for common tasks that could be extracted or for logical breaks between sections in the code. For example you could have one set of procedures or functions for reading in information from the user, and another set for making the calculations. When breaking this code up, or just in the general creation of functions and procedures there are a couple things that should be taken into account:
Below you will find a step by step explanation of the breaking up of the GradeCalculator program into different procedures and functions. Here is a link to the file with the solution in it: GradeCalculator2.p | |
Change 1: extracting code that reads in information from the user | |
Code |
Explanation of changes made |
(* ============================================================================== * File: GradeCalculator2.p * Purpose: Simple program to calculate the percentage and letter grade * with procedures and functions * Author: Jordan Kidney ( kidney@cpsc.ucalgary.ca ) * Created on: Feb 24, 2006 ============================================================================== *) program GradeCalculator2 (input,output); (*----------------------- readTotalMarks ---------------------------------------- * Purpose: prompts the user to enter in the total marks for the test. This * function also does some basic error checking on the number entered. * returns: the number entered by the user as a real *------------------------------------------------------------------------------ *) function readTotalMarks : real; begin var marks : real; var EndLoop : boolean; (* Used as a flag to end loops for error checking *) EndLoop := false; repeat write('Enter the total number of marks : '); readln(marks); if (marks <= 0) then writeln('Error: The number must be greater then zero.') else EndLoop := true until EndLoop = true; readTotalMarks := marks; end; (*----------------------- readUsersMark ---------------------------------------- * Purpose: prompts the user to enter the mark they got for the test. This * function also does some basic error checking on the number entered. * Parameters: TotalMarks - the total number of possible marks on the test. This * value is used for error checking. * returns: the number entered by the user as a real * ------------------------------------------------------------------------------ *) function readUsersMark(TotalMarks : real) : real; begin var mark : real; var EndLoop : boolean; (* Used as a flag to end loops for error checking *) EndLoop := false; repeat write('Enter your mark : '); readln(mark); if ((mark < 0) or (mark > TotalMarks)) then writeln('Error: inncorect input') else EndLoop := true until EndLoop = true; readusersMark := mark; end; (* ========================== MAIN ============================================== *) begin var Mark : real; (* The mark the user got *) var TotalMarks : real; (* Total number of possible marks *) var Percentage : real; (* Used to store the calculated percentage value *) var LetterGrade : char; (* Used to store the letter cade for the mark *) var LetterSign : char; (* Used to store the sign for the letter grade *) TotalMarks := readTotalMarks; Mark := readUsersMark(TotalMarks); (* Calculate the percentage value for the user *) Percentage := (Mark * 100.0)/TotalMarks; (* Find the letter grade based upon the percentage value found *) if (Percentage < 39.0) then begin LetterGrade := 'F'; LetterSign := ' '; end else if (Percentage < 44.0) then begin LetterGrade := 'D'; LetterSign := '-'; end else if (Percentage < 49.0) then begin LetterGrade := 'D'; LetterSign := ' '; end else if (Percentage < 54.0) then begin LetterGrade := 'D'; LetterSign := '+'; end else if (Percentage < 59.0) then begin LetterGrade := 'C'; LetterSign := '-'; end else if (Percentage < 64.0) then begin LetterGrade := 'C'; LetterSign := ' '; end else if (Percentage < 69.0) then begin LetterGrade := 'C'; LetterSign := '+'; end else if (Percentage < 74.0) then begin LetterGrade := 'B'; LetterSign := '-'; end else if (Percentage < 79.0) then begin LetterGrade := 'B'; LetterSign := ' '; end else if (Percentage < 84.0) then begin LetterGrade := 'B'; LetterSign := '+'; end else if (Percentage < 89.0) then begin LetterGrade := 'A'; LetterSign := '-'; end else begin LetterGrade := 'A'; LetterSign := ' '; end; (* Write information to the console *) writeln('You got ', Percentage:0:2, '% on the test which gives you a letter grade of ' ,LetterGrade,LetterSign); end. (* ============================================================================== *) |
Here to two tasks of reading in the users marks and and the total marks for a test
were extracted into two functions. Functions were created because each section of code
will be required to return the information they gathered.
|
Change 2: extracting code that calculates the percentage | |
Code |
Explanation of changes made |
(* ============================================================================== * File: GradeCalculator2.p * Purpose: Simple program to calculate the percentage and letter grade * with procedures and functions * Author: Jordan Kidney ( kidney@cpsc.ucalgary.ca ) * Created on: Feb 24, 2006 ============================================================================== *) program GradeCalculator2 (input,output); (*----------------------- readTotalMarks ---------------------------------------- * Purpose: prompts the user to enter in the total marks for the test. This * function also does some basic error checking on the number entered. * returns: the number entered by the user as a real *------------------------------------------------------------------------------ *) function readTotalMarks : real; begin var marks : real; var EndLoop : boolean; (* Used as a flag to end loops for error checking *) EndLoop := false; repeat write('Enter the total number of marks : '); readln(marks); if (marks <= 0) then writeln('Error: The number must be greater then zero.') else EndLoop := true until EndLoop = true; readTotalMarks := marks; end; (*----------------------- readUsersMark ----------------------------------------- * Purpose: prompts the user to enter the mark they got for the test. This * function also does some basic error checking on the number entered. * Parameters: TotalMarks - the total number of possible marks on the test. This * value is used for error checking. * returns: the number entered by ther use as a real * ------------------------------------------------------------------------------ *) function readUsersMark(TotalMarks : real) : real; begin var mark : real; var EndLoop : boolean; (* Used as a flag to end loops for error checking *) EndLoop := false; repeat write('Enter your mark : '); readln(mark); if ((mark < 0) or (mark > TotalMarks)) then writeln('Error: inncorect input') else EndLoop := true until EndLoop = true; readusersMark := mark; end; (*----------------------- computePercentage --------------------------------------- * Purpose: computes the percentage the user got * Parameters: TotalMarks - the total number of possible marks on the test. * returns: the number entered by ther use as a real * ------------------------------------------------------------------------------ *) function computePercentage(TotalMarks , Mark : real ) : real; begin computePercentage := (Mark * 100.0)/TotalMarks; end; (* ========================== MAIN ============================================== *) begin var Mark : real; (* The mark the user got *) var TotalMarks : real; (* Total number of possible marks *) var Percentage : real; (* Used to store the calculated percentage value *) var LetterGrade : char; (* Used to store the letter cade for the mark *) var LetterSign : char; (* Used to store the sign for the letter grade *) TotalMarks := readTotalMarks; Mark := readUsersMark(TotalMarks); Percentage := computePercentage(TotalMarks,Mark); (* Find the letter grade based upon the percentage value found *) if (Percentage < 39.0) then begin LetterGrade := 'F'; LetterSign := ' '; end else if (Percentage < 44.0) then begin LetterGrade := 'D'; LetterSign := '-'; end else if (Percentage < 49.0) then begin LetterGrade := 'D'; LetterSign := ' '; end else if (Percentage < 54.0) then begin LetterGrade := 'D'; LetterSign := '+'; end else if (Percentage < 59.0) then begin LetterGrade := 'C'; LetterSign := '-'; end else if (Percentage < 64.0) then begin LetterGrade := 'C'; LetterSign := ' '; end else if (Percentage < 69.0) then begin LetterGrade := 'C'; LetterSign := '+'; end else if (Percentage < 74.0) then begin LetterGrade := 'B'; LetterSign := '-'; end else if (Percentage < 79.0) then begin LetterGrade := 'B'; LetterSign := ' '; end else if (Percentage < 84.0) then begin LetterGrade := 'B'; LetterSign := '+'; end else if (Percentage < 89.0) then begin LetterGrade := 'A'; LetterSign := '-'; end else begin LetterGrade := 'A'; LetterSign := ' '; end; (* Write information to the console *) writeln('You got ', Percentage:0:2, '% on the test which gives you a letter grade of ' ,LetterGrade,LetterSign); end. (* ============================================================================== *) |
Here now, a simple function was created to calculate the percentage given the two values entered by the user. The information from the user is now passed in as parameters to the function. |
Change 3: extracting code that finds the letter grade | |
Code |
Explanation of changes made |
(* ============================================================================== * File: GradeCalculator2.p * Purpose: Simple program to calculate the percentage and letter grade * with procedures and functions * Author: Jordan Kidney ( kidney@cpsc.ucalgary.ca ) * Created on: Feb 12, 2006 ============================================================================== *) program GradeCalculator2 (input,output); (*----------------------- readTotalMarks ---------------------------------------- * Purpose: prompts the user to enter in the total marks for the test. This * function also does some basic error checking on the number entered. * returns: the number entered by the user as a real *------------------------------------------------------------------------------ *) function readTotalMarks : real; begin var marks : real; var EndLoop : boolean; (* Used as a flag to end loops for error checking *) EndLoop := false; repeat write('Enter the total number of marks : '); readln(marks); if (marks <= 0) then writeln('Error: The number must be greater then zero.') else EndLoop := true until EndLoop = true; readTotalMarks := marks; end; (*----------------------- readUsersMark ----------------------------------------- * Purpose: prompts the user to enter the mark they got for the test. This * function also does some basic error checking on the number entered. * Parameters: TotalMarks - the total number of possible marks on the test. This * value is used for error checking. * returns: the number entered by ther use as a real * ------------------------------------------------------------------------------ *) function readUsersMark(TotalMarks : real) : real; begin var mark : real; var EndLoop : boolean; (* Used as a flag to end loops for error checking *) EndLoop := false; repeat write('Enter your mark : '); readln(mark); if ((mark < 0) or (mark > TotalMarks)) then writeln('Error: inncorect input') else EndLoop := true until EndLoop = true; readusersMark := mark; end; (*----------------------- computePercentage ------------------------------------ * Purpose: computes the percentage the user got * Parameters: TotalMarks - the total number of possible marks on the test. * Mark - the mark the user got on the test * returns: the number entered by ther use as a real *----------------------------------------------------------------------------- *) function computePercentage(TotalMarks , Mark : real ) : real; begin computePercentage := (Mark * 100.0)/TotalMarks; end; (*----------------------- findLetterGrade ----------------------------------------- * Purpose: find the letter grade based upon a given percentage value * Parameters: percentage - the percentage used to find the letter grade * returns: the letter grade as a string *------------------------------------------------------------------------------- *) function findLetterGrade(percentage : real ) : string; begin var LetterGrade : string[3]; if (Percentage < 39.0) then LetterGrade := 'F' else if (Percentage < 44.0) then LetterGrade := 'D-' else if (Percentage < 49.0) then LetterGrade := 'D' else if (Percentage < 54.0) then LetterGrade := 'D+' else if (Percentage < 59.0) then LetterGrade := 'C-' else if (Percentage < 64.0) then LetterGrade := 'C' else if (Percentage < 69.0) then LetterGrade := 'C+' else if (Percentage < 74.0) then LetterGrade := 'B-' else if (Percentage < 79.0) then LetterGrade := 'B' else if (Percentage < 84.0) then LetterGrade := 'B+' else if (Percentage < 89.0) then LetterGrade := 'A-' else LetterGrade := 'A'; findLetterGrade := LetterGrade; end; (* ========================== MAIN ============================================== *) begin var Mark : real; (* The mark the user got *) var TotalMarks : real; (* Total number of possible marks *) var Percentage : real; (* Used to store the calculated percentage value *) var LetterGrade : string[3]; (* Used to store the letter cade for the mark *) TotalMarks := readTotalMarks; Mark := readUsersMark(TotalMarks); Percentage := computePercentage(TotalMarks,Mark); LetterGrade := findLetterGrade(Percentage); (* Write information to the console *) writeln('You got ', Percentage:0:2, '% on the test which gives you a letter grade of ',LetterGrade); end. (* ============================================================================== *) |
Finally the code for finding the letter grade is extracted and put into another function. Now in this case since we can only return one variable from a function the data type is change to a string instead of two individual character variables. |