16.6: Example Two
- Page ID
- 54371
\( \newcommand{\vecs}[1]{\overset { \scriptstyle \rightharpoonup} {\mathbf{#1}} } \)
\( \newcommand{\vecd}[1]{\overset{-\!-\!\rightharpoonup}{\vphantom{a}\smash {#1}}} \)
\( \newcommand{\dsum}{\displaystyle\sum\limits} \)
\( \newcommand{\dint}{\displaystyle\int\limits} \)
\( \newcommand{\dlim}{\displaystyle\lim\limits} \)
\( \newcommand{\id}{\mathrm{id}}\) \( \newcommand{\Span}{\mathrm{span}}\)
( \newcommand{\kernel}{\mathrm{null}\,}\) \( \newcommand{\range}{\mathrm{range}\,}\)
\( \newcommand{\RealPart}{\mathrm{Re}}\) \( \newcommand{\ImaginaryPart}{\mathrm{Im}}\)
\( \newcommand{\Argument}{\mathrm{Arg}}\) \( \newcommand{\norm}[1]{\| #1 \|}\)
\( \newcommand{\inner}[2]{\langle #1, #2 \rangle}\)
\( \newcommand{\Span}{\mathrm{span}}\)
\( \newcommand{\id}{\mathrm{id}}\)
\( \newcommand{\Span}{\mathrm{span}}\)
\( \newcommand{\kernel}{\mathrm{null}\,}\)
\( \newcommand{\range}{\mathrm{range}\,}\)
\( \newcommand{\RealPart}{\mathrm{Re}}\)
\( \newcommand{\ImaginaryPart}{\mathrm{Im}}\)
\( \newcommand{\Argument}{\mathrm{Arg}}\)
\( \newcommand{\norm}[1]{\| #1 \|}\)
\( \newcommand{\inner}[2]{\langle #1, #2 \rangle}\)
\( \newcommand{\Span}{\mathrm{span}}\) \( \newcommand{\AA}{\unicode[.8,0]{x212B}}\)
\( \newcommand{\vectorA}[1]{\vec{#1}} % arrow\)
\( \newcommand{\vectorAt}[1]{\vec{\text{#1}}} % arrow\)
\( \newcommand{\vectorB}[1]{\overset { \scriptstyle \rightharpoonup} {\mathbf{#1}} } \)
\( \newcommand{\vectorC}[1]{\textbf{#1}} \)
\( \newcommand{\vectorD}[1]{\overrightarrow{#1}} \)
\( \newcommand{\vectorDt}[1]{\overrightarrow{\text{#1}}} \)
\( \newcommand{\vectE}[1]{\overset{-\!-\!\rightharpoonup}{\vphantom{a}\smash{\mathbf {#1}}}} \)
\( \newcommand{\vecs}[1]{\overset { \scriptstyle \rightharpoonup} {\mathbf{#1}} } \)
\( \newcommand{\vecd}[1]{\overset{-\!-\!\rightharpoonup}{\vphantom{a}\smash {#1}}} \)
\(\newcommand{\avec}{\mathbf a}\) \(\newcommand{\bvec}{\mathbf b}\) \(\newcommand{\cvec}{\mathbf c}\) \(\newcommand{\dvec}{\mathbf d}\) \(\newcommand{\dtil}{\widetilde{\mathbf d}}\) \(\newcommand{\evec}{\mathbf e}\) \(\newcommand{\fvec}{\mathbf f}\) \(\newcommand{\nvec}{\mathbf n}\) \(\newcommand{\pvec}{\mathbf p}\) \(\newcommand{\qvec}{\mathbf q}\) \(\newcommand{\svec}{\mathbf s}\) \(\newcommand{\tvec}{\mathbf t}\) \(\newcommand{\uvec}{\mathbf u}\) \(\newcommand{\vvec}{\mathbf v}\) \(\newcommand{\wvec}{\mathbf w}\) \(\newcommand{\xvec}{\mathbf x}\) \(\newcommand{\yvec}{\mathbf y}\) \(\newcommand{\zvec}{\mathbf z}\) \(\newcommand{\rvec}{\mathbf r}\) \(\newcommand{\mvec}{\mathbf m}\) \(\newcommand{\zerovec}{\mathbf 0}\) \(\newcommand{\onevec}{\mathbf 1}\) \(\newcommand{\real}{\mathbb R}\) \(\newcommand{\twovec}[2]{\left[\begin{array}{r}#1 \\ #2 \end{array}\right]}\) \(\newcommand{\ctwovec}[2]{\left[\begin{array}{c}#1 \\ #2 \end{array}\right]}\) \(\newcommand{\threevec}[3]{\left[\begin{array}{r}#1 \\ #2 \\ #3 \end{array}\right]}\) \(\newcommand{\cthreevec}[3]{\left[\begin{array}{c}#1 \\ #2 \\ #3 \end{array}\right]}\) \(\newcommand{\fourvec}[4]{\left[\begin{array}{r}#1 \\ #2 \\ #3 \\ #4 \end{array}\right]}\) \(\newcommand{\cfourvec}[4]{\left[\begin{array}{c}#1 \\ #2 \\ #3 \\ #4 \end{array}\right]}\) \(\newcommand{\fivevec}[5]{\left[\begin{array}{r}#1 \\ #2 \\ #3 \\ #4 \\ #5 \\ \end{array}\right]}\) \(\newcommand{\cfivevec}[5]{\left[\begin{array}{c}#1 \\ #2 \\ #3 \\ #4 \\ #5 \\ \end{array}\right]}\) \(\newcommand{\mattwo}[4]{\left[\begin{array}{rr}#1 \amp #2 \\ #3 \amp #4 \\ \end{array}\right]}\) \(\newcommand{\laspan}[1]{\text{Span}\{#1\}}\) \(\newcommand{\bcal}{\cal B}\) \(\newcommand{\ccal}{\cal C}\) \(\newcommand{\scal}{\cal S}\) \(\newcommand{\wcal}{\cal W}\) \(\newcommand{\ecal}{\cal E}\) \(\newcommand{\coords}[2]{\left\{#1\right\}_{#2}}\) \(\newcommand{\gray}[1]{\color{gray}{#1}}\) \(\newcommand{\lgray}[1]{\color{lightgray}{#1}}\) \(\newcommand{\rank}{\operatorname{rank}}\) \(\newcommand{\row}{\text{Row}}\) \(\newcommand{\col}{\text{Col}}\) \(\renewcommand{\row}{\text{Row}}\) \(\newcommand{\nul}{\text{Nul}}\) \(\newcommand{\var}{\text{Var}}\) \(\newcommand{\corr}{\text{corr}}\) \(\newcommand{\len}[1]{\left|#1\right|}\) \(\newcommand{\bbar}{\overline{\bvec}}\) \(\newcommand{\bhat}{\widehat{\bvec}}\) \(\newcommand{\bperp}{\bvec^\perp}\) \(\newcommand{\xhat}{\widehat{\xvec}}\) \(\newcommand{\vhat}{\widehat{\vvec}}\) \(\newcommand{\uhat}{\widehat{\uvec}}\) \(\newcommand{\what}{\widehat{\wvec}}\) \(\newcommand{\Sighat}{\widehat{\Sigma}}\) \(\newcommand{\lt}{<}\) \(\newcommand{\gt}{>}\) \(\newcommand{\amp}{&}\) \(\definecolor{fillinmathshade}{gray}{0.9}\)In this example, we will write a simple program to perform some processing for students. The student information will be stored in an array of derived data types. There will be no more than 50 students per class. The main will call a subroutine to read student information (name and score) and another subroutine to set the student grades. Finally, the main will call a function to calculate the class average. The main will display the average. Routines for displaying the students are left as an exercise.
Understand the Problem
The main is expected to define the appropriate derived data type for student, declare some variables of that type and call the subroutines. The first subroutine will read student information, including a name (up to 60 characters) and score from the user. Names and scores should continue to be read until a blank name is entered. The score value must be between 0.0 and 100.0 (inclusive). For this simple example, we will re-prompt for incorrect data entry (until correct data is provided). The routine must return the count of students entered. The second subroutine sets the grades based on the following standard scale.
| A | B | C | D | F |
|---|---|---|---|---|
| \(\geq 90\) | \(80 - 89\) | \(70 - 79\) | \(60 - 69\) | \(\leq 59\) |
When determining the final grade, the program should round up when appropriate. The main will call a function to calculate and return the average of the scores. Additionally, the main will display the final average.
Create the Algorithm
For this example main, part for the main includes a declaration, display header, call read time subroutine, and the call the time summation subroutine. The basic steps for the main include:
! define derived data type for student ! must include → name, id, grade ! declare variables ! includes → array for up to 50 students ! display initial header ! call subroutine to read student information ! call subroutine to set grades ! use function to calculate average of scores ! display average
The basic steps for the read student information subroutine include:
! subroutine header and appropriate declarations ! loop ! prompt for student name ! read name ! if name is empty, exit loop ! loop ! prompt for student score ! read score ! check score entered ! if [score is between 0.0 and 100.0, inclusive] exit ! display error message ! end loop ! update count of students ! place values in student array ! end loop
The basic steps for the set grades subroutine include:
! subroutine header and appropriate declarations ! loop ! read score / set grade ! ≥ 90 → A; 80 - 89 → B; 70 – 79 → C; 60 - 69 → D; ≤ 59 → F ! end loop
When determining the final grade, the nearest integer intrinsic function, nint(), can be used to perform the appropriate rounding.
The basic steps for the calculate average score function include:
! function header and appropriate declarations ! loop ! sum scores ! end loop ! calculate and return average
For convenience, the steps are written as program comments.
Implement the Program
Based on the algorithm, the below program could be created.
program classScores
! define data type for student, includes → name, id, grade
implicit none
type student
character(60) :: name
real :: score
character(1) :: grade
end type
! declare variables, including → array for up to 50 students
type(student), dimension(50) :: class
integer :: count
real :: average
! display initial header
write (*,'(/,a,/)') "Student Information Example Program."
! call subroutine to read student information
call readStudents (class, count)
! call subroutine to set grades
call setStudentGrades (class, count)
! use function to calculate average of scores
average = classAverage (class, count)
! display average
write (*,'(/,a, f5.1)') "Final Class Average: ", average
contains
! *******************************************************
! Subroutine to read student information (name and score).
! A blank name will stop input
! The score must be between 0.0 and 100.0 (inclusive)
subroutine readStudents (class, count)
type(student), dimension(50), intent(out) :: class
integer, intent(out) :: count = 0
character(60) :: tempname
real :: tempscore
do
! prompt for student name and read name
write (*,'(a)',advance="no") "Enter Student Name: "
read (*,'(a60)') tempname
! if name is empty, exit loop
if ( len_trim(tempname) == 0 ) exit
do
! prompt for student score and read score
write (*,'(a)',advance="no") &
"Enter Student Score: "
read (*,*) tempscore
! check score entered
if ( tempscore >= 0.0 .and. &
tempscore <= 100.0 ) exit
! display error message
write (*,'(a,/,a)') &
"Error, invalid score.", &
"Please re-enter time."
end do
! update count of students and place in student array
count = count + 1
class(count)%name = tempname
class(count)%score = tempscore
end do
return
end subroutine readStudents
! *******************************************************
! Subroutine to set student grades.
! ≥90→A;80-89→B;70–79→C;60-69→D;≤59→F
subroutine setStudentGrades (class, count)
type(student), dimension(50), intent(inout) :: class
integer, intent(in) :: count
integer :: i
! check each score / set each grade
do i = 1, count
select case ( nint(class(i)%score) )
case (90:)
class(i)%grade = "A"
case (80:89)
class(i)%grade = "B"
case (70:79)
class(i)%grade = "C"
case (60:69)
class(i)%grade = "D"
case (:59)
class(i)%grade = "F"
end select
end do
return
end subroutine setStudentGrades
! *******************************************************
! Function to calculate average score.
real function classAverage (class, count)
type(student), dimension(50), intent(in) :: class
integer, intent(in) :: count
integer :: i
real :: sum = 0.0
! sum scores
do i = 1, count
sum = sum + class(i)%score
end do
! calculate and return average
classaverage = sum / real(count)
return
end function classAverage
end program classScores
If the program does not work at first, the comments can aid in determining the problem.
Test/Debug the Program
For this problem, the testing would involve executing the program and entering a series of student data values to ensure that the results are correct. If the program does not provide the correct results, each of the subroutines and the function results should be verified individually. Each can be checked by displaying the intermediate results to the screen. In this manner, the subroutine or function that is not working correctly can be quickly identified. Once identified, some additional write statements inside the subprogram can be used to help identify the specific problem. The testing and debugging process is left to the reader as an exercise.


