Ошибка: после дескриптора P в строке формата требуется запятая.

Когда я пытаюсь скомпилировать calrank.for (CALRANK_v7.0.0_L140912.zip) с помощью gfortran, я получаю эту ошибку:

> gfortran  -m64 -c -o calrank.o calrank.for
calrank.for:1922:32:
         write(io,'(2f10.3,1p1000(2x,e16.7,1x,2a10,1x))')
                                1
Error: Comma required after P descriptor in format string at (1)

Когда я ставлю запятую, я получаю ту же ошибку.
Замечу только, что код ранее был скомпилирован с помощью LF95.

   subroutine xycout(io,nrank,nsp)
      use userinf
      use header
      use rankdata

      implicit none

    integer :: io,nrank,nsp
      integer :: k,ir,is,i
      character(len=20)   :: head1,head2,head3
      character(len=40)   :: add1x,add2x,add3x
      character(len=40)   :: add1(nsp),add2(nsp)
      character(len=40)   :: add3(nsp)
 ......
 c --- Loop over receptors to write data records
      do ir=1,ntotrec(k)
         write(io,'(2f10.3,1p1000(2x,e16.7,1x,2a10,1x))')
     &                   xreckm(ir,k),yreckm(ir,k),
     &                  (xounit(is,k)*rankvalue(ir,is,nrank),
     &                   arankdate(ir,is,nrank),
     &                   aranktime(ir,is,nrank),is=1,nspout(k))
      enddo

      return
      end

Некоторые переменные определены в другом месте кода как:

c --- Real arrays for header (derived)
      allocate (xreckm(mxrec,k),yreckm(mxrec,k))
c --- Modified units multiplier
      allocate (xounit(mxspout,k))
      c --- Array of values (all species, receptors) for requested ranks
      allocate (rankvalue(ntotrec(k),nspout(k),n_ranks))
      allocate (arankdate(ntotrec(k),nspout(k),n_ranks))
      allocate (aranktime(ntotrec(k),nspout(k),n_ranks))
c --- Integer arrays for header
      deallocate (ndrec,nctrec,nspout,i2dmet,iutmzn)

person Moustabchir Rachid    schedule 01.03.2019    source источник
comment
Добро пожаловать, ознакомьтесь с туром. Всегда используйте fortran для всех вопросов по Fortran. Обычно нам нужно больше кода, чем показано в сообщении об ошибке. По крайней мере, все переменные в вашем образце должны быть объявлены.   -  person Vladimir F    schedule 01.03.2019
comment
прости за это. Не могу найти, как загрузить код. Я размещаю его на странице drive.google.com/file/d/1viIilSckdSSPUgoblgsupport/. Спасибо. Код взят из src.com/calpuff/download/mod7_codes.htm CALRANK Версия 7.0.0 (140912).   -  person Moustabchir Rachid    schedule 01.03.2019
comment
Вы не должны никуда загружать свой код. Вы должны скопировать и вставить соответствующий минимальный воспроизводимый пример (снова обратите внимание на слово минимальный) в свой вопрос в виде текста. отредактируйте вопрос, чтобы он содержал важные части кода.   -  person Vladimir F    schedule 01.03.2019
comment
Хорошо, спасибо большое, Владимир.   -  person Moustabchir Rachid    schedule 01.03.2019
comment
Не беспокойтесь об этом сейчас, посмотрите ответ.   -  person Vladimir F    schedule 01.03.2019


Ответы (2)


Вы должны сделать именно то, что написано в сообщении об ошибке, поставить запятую после дескриптора p:

write(io,'(2f10.3,1p,1000(2x,e16.7,1x,2a10,1x))')

Если вы не знаете, что такое дескриптор ap, см., Например, https://docs.oracle.com/cd/E19957-01/805-4939/z4000743a6e2/index.html или любое руководство по дескрипторам редактирования Fortran. Как комментирует Стивен Лайонел ниже, вы можете использовать дескриптор p без запятой перед обычными дескрипторами редактирования данных.

person Vladimir F    schedule 01.03.2019
comment
Спасибо большое, Владимир. это работает. Да, я никогда не использовал дескриптор p, я впервые его вижу. - person Moustabchir Rachid; 01.03.2019
comment
Это не очень полезно. Никогда не использую. Поэтому раньше я не отвечал, пришлось самому уточнять детали. - person Vladimir F; 01.03.2019
comment
Формат P полезен, но не совсем понятен. Правило об опускании запятых еще менее понятно. Запятая может быть опущена между дескриптором редактирования P и непосредственно следующим за дескриптором редактирования F, E, EN, ES, EX, D или G, возможно, которому предшествует спецификация повтора. В этом случае, однако, следующая группа заключена в скобки и не подходит. - person Steve Lionel; 01.03.2019
comment
Большое спасибо Владимиру Ф., Стиву Лайонелу и francescalus за эти разъяснения. Мне интересно, что означает число 1000 после 1p? это повторение 1000 раз? !!! - person Moustabchir Rachid; 01.03.2019
comment
Хорошо, может быть, мне следовало бы скорее сказать, что я считаю дескриптор P сложным в использовании и опасным. Особенно по вводу. @MoustabchirRachid да, 1000 - это повтор группы в скобках. Можно смело помещать туда очень большое число или даже неопределенное повторение *, если повторяющаяся группа находится в конце строки формата, и никто не хочет, чтобы произошло какое-либо изменение формата. - person Vladimir F; 01.03.2019

@francescalus предложил мне расширить свой комментарий.

Во-первых, Fortran обычно требует запятой между двумя «элементами формата». Элемент форматирования - это дескриптор редактирования (F, E и т. Д.) С предшествующим ему счетчиком повторов или без него, или заключенная в скобки группа элементов форматирования (у которых может быть свой собственный счетчик повторов; упоминается @Vladimir F * - это " неограниченное количество повторов "и может использоваться только с группой в скобках.

Запятую можно опустить:

  • между дескриптором редактирования P и непосредственно следующим за ним дескриптором редактирования F, E, EN, ES, EX, D или G, которому, возможно, предшествует повторная спецификация,
  • перед дескриптором редактирования косой черты, когда необязательная спецификация повтора не появляется,
  • после дескриптора редактирования косой черты, или
  • до или после дескриптора редактирования двоеточия

Что касается дескриптора редактирования P, он устанавливает коэффициент масштабирования, и это действительно странно и имеет очень разные эффекты в зависимости от того, какое редактирование вы делаете. Он также является «липким» и применяется ко всему последующему редактированию в этом формате.

При вводе считанное значение делится на 10 ** k, где k - масштабный коэффициент (2P означает k = 2 и т. Д.). Таким образом, если на входе введены символы 123 и действует 2P, значение читается как 1,23. Точно так же, если действует -2P, 123 будет читаться как 12300. Десятичная точка во входных данных не меняет этого, но показатель степени удаляет масштабирование. Таким образом, 1,23, прочитанное с 2P, равно 0,0123, а 1,23E0 - 1,23.

На выходе с редактированием F он заставляет выходное значение умножаться на 10 ** k, меняя схему ввода на обратную.

Вы спросите, ПОЧЕМУ ??? Ответ кроется в перфокартах, форме ввода (а иногда и вывода), использовавшейся в 1950–70-х годах. У них было 80 столбцов, и тратить столбец на десятичную точку могло быть проблемой. Таким образом, масштабный коэффициент позволял опускать десятичную точку, но все же получать дроби.

Но подождите, это становится еще более странным! При выводе с редактированием E и D масштабный коэффициент просто определяет количество ведущих цифр слева от десятичной точки (и последующее уменьшение показателя степени. Таким образом, для значения 1,23 и формата 2P, E11.3, вы получите b12.300E-01 (b = пусто, если не действует SP, что является ответом на другой день).

А для вывода с форматом G? Еще более странно. Если значение находится в диапазоне, в котором вы получаете эквивалент формата F, коэффициент масштабирования не влияет, в противном случае он ведет себя как E.

Наконец, масштабный коэффициент не влияет на редактирование EN, ES или EX. (EX? Это функция F2018 для вывода шестнадцатеричных чисел с плавающей запятой.)

Одним из хороших вариантов использования формата P является выполнение расчетов валют с целыми числами вместо действительных, поскольку последнее может потерять точность (например, 0,01 не имеет точного двоичного представления с плавающей запятой). Предполагая, что значения, с которыми вы имеете дело, не слишком big, вы можете переводить доллары и центы в целое число в формате -2P и не терять ни копейки при сложении, вычитании и умножении. Однажды я написал ипотечный калькулятор таким точным способом.

person Steve Lionel    schedule 02.03.2019