Ste
Ste

Reputation: 51

How to limit the number of characters to be printed per line in Fortran?

This is the program I am compiling in Fortran. It calculates two different formulas for even and odd numbers and it stops when you get 1 as result. If I choose N = 50 for example, I get all the values displayed in the same line. I would like maximum 40 characters (including numbers and commas) printed per line. I also need to store the last numbers (4,2,1), but I don't know how.

That's what I am getting when I compile the program.

50, 25, 76, 38, 19, 58, 29, 88, 44, 22, 11, 34, 17, 52, 26, 13, 40, 20, 10, 5, 16, 8, 4, 2, 1,

That's what I want (40 characters per line):

50, 25, 76, 38, 19, 58, 29, 88, 44, 22,

11, 34, 17, 52, 26, 13, 40, 20, 10, 5,

16, 8, 4, 2, 1,

program numbers
implicit none

integer(kind=4) :: i, n

print*,'Enter the N value'

read*, n

          do while (n.ne.1)
              if (mod(n,2) .eq.0) then
                    n = n/2
                    write(6,'(i0,a)',advance='no') n,','
               else if (mod(n,2) .ne.0) then
                    n = (3*n)+1
               write(6,'(i0,a)',advance='no') n,','
               else
                    cycle
               end if
          end do

end program numbers

Upvotes: 3

Views: 466

Answers (2)

Raul Laasner
Raul Laasner

Reputation: 1585

Here is a general solution that you can adopt for your code. Given an input string msg, it prints lines no longer than 40 characters in length (adjust MAX_LINE_LEN below if necessary). The lines are split only at spaces.

  implicit none
  character(:), allocatable :: msg
  msg = '50, 25, 76, 38, 19, 58, 29, 88, 44, 22, 11, 34, 17, 52, 26, 13, 40, &
       &20, 10, 5, 16, 8, 4, 2, 1,'
  call print_msg(msg)

contains
  recursive subroutine print_msg(msg)
    character(*), intent(in) :: msg
    integer, parameter :: MAX_LINE_LEN = 40
    integer :: length
    if (len(msg) <= MAX_LINE_LEN) then
       length = len(trim(msg))
    else if (index(msg(:MAX_LINE_LEN), ' ') > 0) then
       length = index(msg(:MAX_LINE_LEN), ' ', back=.true.)
    else
       length = MAX_LINE_LEN
    end if
    write(*, '(*(g0))') msg(:length)
    if (len(msg) > MAX_LINE_LEN) then
       call print_msg(msg(length+1:))
    end if
  end subroutine print_msg
end program

The output is

50, 25, 76, 38, 19, 58, 29, 88, 44, 22, 
11, 34, 17, 52, 26, 13, 40, 20, 10, 5, 
16, 8, 4, 2, 1,

Upvotes: 1

haraldkl
haraldkl

Reputation: 3819

You could tell the compiler break lines after a given number of characters, but that would also break them midnumber. If you want to avoid that, you could just count the number of characters. Maybe the easiest to do that would be to write to string and to use len_trim to figure out its length. For keeping the last three numbers around you could use an array of length three and put a number into index of current iteration modulo 3.

Something like this maybe:

program numbers
  implicit none

  integer :: i, n
  integer :: rowlen
  integer :: last(0:2)
  character(len=40) :: numstring = ''

  print*,'Enter the N value'

  read*, n

  last(0) = n
  write(numstring, '(i0)') n
  rowlen = len_trim(numstring)
  write(*,'(a)', advance='no') trim(numstring)

  do i=1,3*n
    if (mod(n,2) == 0) then
      n = n/2
    else
      n = (3*n)+1
    end if

    write(numstring, '(a,i0)') ', ', n
    rowlen = rowlen+len_trim(numstring)
    if (rowlen > 39) then
       write(*,'(a)') ','
       write(numstring, '(i0)') n
       rowlen = len_trim(numstring)
    end if
    write(*,'(a)', advance='no') trim(numstring)

    last(mod(i,3)) = n

    if (n == 1) EXIT
  end do

  write(*,*) ''
  if (i > 2) then
    write(*,*) 'Last three numbers:', last(mod(i-2,3)), &
      &                               last(mod(i-1,3)), &
      &                               last(mod(i,3))
  end if

end program numbers

Upvotes: 1

Related Questions