There is little to criticize. As I commented above, you can also left adjust integers by the i0 format descriptor. I would also intend the main program.
As Fortran actually stands for Formula Translator, I think it would be more appealing to use a split into For and Tran. If you use Trans, you then would even replace the numbers by letters of the numbers values. I also use Doxygen for documentation of Fortran code, and think its syntax is rather unobtrusive. Thus, it usually does not hurt to use it. Finally it is good practice to put functionality into routines, and routines into modules. Though, this might be a little over the top for such a small example, I think it is illustrative to use it her as well. Therefore, here is my suggestion:
!> A module that implements the FizzBuzz series.
module fizzbuzz_module
use iso_fortran_env, only: output_unit
implicit none
private
public :: write_fizzbuzz
contains
!> Write a series of fizzbuzz to unit.
!!
!! This writes all the numbers from lb to ub to unit, but replaces:
!! - multiples of 3 by For
!! - multiples of 5 by Tran
!! - multiples of both, 5 and 3 by ForTran
subroutine write_fizzbuzz(ub, lb, unit)
!> Upper bound up to which the series is to be written.
integer, intent(in) :: ub
!> Lower bound, where the series should start, defaults to 1.
integer, optional, intent(in) :: lb
!> File unit to write the fizzbuzz series to, defaults to stdout.
!!
!! The file has to be opened as formatted file with sequential access
!! and an allowed action to write.
integer, optional, intent(in) :: unit
integer :: i
integer :: loc_lb
integer :: loc_unit
if (present(lb)) then
loc_lb = lb
else
loc_lb = 1
end if
if (present(unit)) then
loc_unit = unit
else
loc_unit = output_unit
end if
do i=loc_lb,ub
! 15 is the lowest common multiple of 3, and 5
! and thus is a shortcut to ForTran
if (modulo(i, 15) == 0) then
write (loc_unit,'(A7)') 'ForTran'
else if (modulo(i, 3) == 0) then
write (loc_unit,'(A3)') 'For'
else if (modulo(i, 5) == 0) then
write (loc_unit,'(A4)') 'Tran'
else
write (loc_unit,'(I0)') i
end if
end do
end subroutine write_fizzbuzz
end module fizzbuzz_module
!> Small program to illustrate and test the fizzbuzz module.
program test_fizzbuzz
use fizzbuzz_module, only: write_fizzbuzz
implicit none
! Write a fizzbuzz series from 1 to 100 to stdout:
call write_fizzbuzz(ub=100)
! Write the next 100 entries of the fizzbuzz series to stdout:
call write_fizzbuzz(lb=101, ub=200)
end program test_fizzbuzz
By using the private statement in the module, you do not export the output_unit to the using program units, but limit the parts that should be visible to those, you explicitly declare as public. The only clause in the use statement also restricts, what you import from the module, but I use it mainly to indicate, where what is coming from.