Skip to main content
Engineering LibreTexts

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{\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}}\)

    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.


    This page titled 16.6: Example Two is shared under a CC BY-NC-SA 3.0 license and was authored, remixed, and/or curated by Ed Jorgensen via source content that was edited to the style and standards of the LibreTexts platform; a detailed edit history is available upon request.

    • Was this article helpful?