Как ограничить количество символов, которые будут напечатаны на строке в Фортране? - PullRequest
3 голосов
/ 06 октября 2019

Это программа, которую я компилирую на Фортране. Он рассчитывает две разные формулы для четных и нечетных чисел и останавливается, когда вы получаете 1 в качестве результата. Например, если я выберу N = 50, я получу все значения, отображаемые в одной строке. Я хотел бы, чтобы в каждой строке было напечатано не более 40 символов (включая цифры и запятые). Мне также нужно хранить последние цифры (4,2,1), но я не знаю как.

Вот что я получаю при компиляции программы.

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,

Вот что я хочу (40 символов в строке):

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

Ответы [ 2 ]

1 голос
/ 06 октября 2019

Вот общее решение, которое вы можете принять для своего кода. Для входной строки msg она печатает строки длиной не более 40 символов (при необходимости настройте MAX_LINE_LEN ниже). Строки разделены только пробелами.

  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

Вывод

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,
1 голос
/ 06 октября 2019

Вы можете сказать, что компилятор разбивает строки после заданного количества символов, но это также разбивает их по среднему числу. Если вы хотите избежать этого, вы можете просто посчитать количество символов. Возможно, проще всего сделать это для записи в строку и использования len_trim для определения ее длины. Для хранения последних трех чисел вы можете использовать массив длины три и поместить число в индекс текущей итерации по модулю 3.

Что-то вроде этого может быть:

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...