5. Select-Case AND OOP
by
gg582 · 2026-05-27 05:15:34 · 36 views
1. Syntax Rules for Modern Fortran
- Case Insensitivity: Fortran keywords are case-insensitive. Modern coding conventions prefer lowercase for keywords (
if,select case). - Variable Declarations: Under
implicit none, all variables and function result variables must be explicitly typed.
2. Basic and Multi-Way Conditionals
IF Constructs
- Logical IF: Executes a single statement when the condition is true. No
thenorend ifrequired.
if (x < 0) x = -x
- IF Block: Used for multi-line or multi-condition branching.
if (x > 0) then
print *, "Positive"
else if (x < 0) then
print *, "Negative"
else
print *, "Zero"
end if
SELECT CASE Construct
Executes a specific block based on the evaluation of an expression.
- Supported Data Types:
integer,character,logical. - Constraint:
real(floating-point) types are strictly prohibited due to precision errors. - Constraint: The
caseselector does not accept arrays. It only accepts scalar constants, constant expressions, lists, or ranges.
select case (choice)
case (1) ! Single scalar constant
print *, "Option 1"
case (2, 3, 5) ! List of constants
print *, "Prime choices"
case (10:20) ! Range (10 <= choice <= 20)
print *, "Range match"
case (:9) ! Lower bounded range (choice <= 9)
print *, "Single digit"
case (21:) ! Upper bounded range (choice >= 21)
print *, "Above 20"
case default ! Fallback case
print *, "No match"
end select
3. Legacy and Obsolete Branching (Fortran 2018)
- Unconditional GO TO: Jumps directly to a statement label. Unsafe and breaks structural integrity.
10 continue
! processing
if (condition) go to 10
- Arithmetic IF (Obsolete): Branches to three different labels depending on whether the expression is negative, zero, or positive.
if (x - y) 10, 20, 30 ! <0: label 10, ==0: label 20, >0: label 30
- Computed GO TO (Obsolete): Jumps to a label in a list based on an integer value. Replaced by
select case.
go to (10, 20, 30) i ! i=1: label 10, i=2: label 20, i=3: label 30
- Shared Loop Termination (Deleted): Multiple
doloops ending on the same statement label are deleted in Fortran 2018. Each loop requires its ownend do.
4. Modern Specialized Conditionals
WHERE Construct
Applies a logical mask to execute element-wise array operations without explicit loops.
where (array > 0)
inverse = 1.0 / array
elsewhere
inverse = 0.0
end where
SELECT RANK (Fortran 2018+)
Branches based on the rank (number of dimensions) of an assumed-rank dummy argument.
select rank (array_arg)
rank (0)
print *, "Scalar"
rank (1)
print *, "1D Array"
end select
SELECT TYPE (Fortran 2003+)
Branches based on the dynamic type of a polymorphic entity. It requires the target variable to be a polymorphic class entity (class(*) or class(base_type)). It allows downcasting to access attributes unique to a child extension type.
5. Multi-File Object-Oriented Implementation
To avoid name collisions, the module name must differ from the derived type names inside it.
module/shape/shape.f90
module shape_mod
implicit none
private
public :: shape, circle, rectangle
! Parent abstract class
type, abstract :: shape
contains
procedure(get_area_proc), deferred :: get_area
end type shape
! Abstract interface for deferred method
abstract interface
function get_area_proc(this) result(area)
import :: shape
class(shape), intent(in) :: this
real :: area
end function get_area_proc
end interface
! Child class: Circle
type, extends(shape) :: circle
real :: radius
contains
procedure :: get_area => get_circle_area
end type circle
! Child class: Rectangle
type, extends(shape) :: rectangle
real :: width, height
contains
procedure :: get_area => get_rect_area
end type rectangle
contains
real function get_circle_area(this) result(area)
class(circle), intent(in) :: this
area = 3.14159 * this%radius**2
end function
real function get_rect_area(this) result(area)
class(rectangle), intent(in) :: this
area = this%width * this%height
end function
end module shape_mod
main.f90
program main
use shape_mod
implicit none
class(shape), allocatable :: my_shape
integer :: choice
print *, "select shape type (1: circle, 2: rectangle):"
read *, choice
if (choice == 1) then
allocate(circle :: my_shape)
select type (s => my_shape)
type is (circle)
s%radius = 5.0
end select
else if (choice == 2) then
allocate(rectangle :: my_shape)
select type (s => my_shape)
type is (rectangle)
s%width = 4.0
s%height = 6.0
end select
else
stop "invalid choice."
end if
call print_info(my_shape)
contains
subroutine print_info(s)
class(shape), intent(in) :: s
print *, "--- info ---"
print *, "calculated area:", s%get_area()
! Runtime type verification via select type
select type (item => s)
type is (circle)
print *, "type: circle / radius:", item%radius
type is (rectangle)
print *, "type: rectangle / size:", item%width, "x", item%height
end select
end subroutine print_info
end program main
6. Build Specification (Makefile)
FC = gfortran
FFLAGS = -I./module/shape
MOD_DIR = module/shape
SRC_MOD = $(MOD_DIR)/shape.f90
SRC_MAIN = main.f90
OBJ_MOD = shape.o
TARGET = main_exe
all: $(TARGET)
$(TARGET): $(OBJ_MOD) $(SRC_MAIN)
$(FC) $(FFLAGS) $(OBJ_MOD) $(SRC_MAIN) -o $(TARGET)
$(OBJ_MOD): $(SRC_MOD)
$(FC) -c $(SRC_MOD) -o $(OBJ_MOD)
clean:
rm -f *.o *.mod $(TARGET)