передача строки в качестве аргумента, когда манекен имеет указанную длину

если у меня есть этот код

module test
contains
   subroutine xx(name)
      character(len=20), intent(in), optional :: name

      if (present(name)) then
         print *, name
      else
         print *, "foo"
      endif
   end subroutine
end module
program x
   use test

   call xx()
   call xx("foo2")
end program

Он не будет компилироваться, поскольку длина "foo2" не равна 20, и компилятор жалуется

test.f90(17): error #7938: Character length argument mismatch.   ['foo2']
   call xx("foo2")
-----------^

Как я могу заставить эту вещь работать, не изменяя спецификацию фиктивного len подпрограммы? Обязательно ли объявить промежуточную переменную той же длины и передать ее во время вызова?


person Stefano Borini    schedule 24.01.2011    source источник


Ответы (3)


Стандартный язык может быть трудным для понимания. Я прочитал предложение, процитированное @kemiisto, как требующее длины (dummy arg) <= length (фактический аргумент). Здесь длина (dummy arg) = 20 и length (actual arg) = 4, поэтому длина (dummy arg) > length (actual arg), что не допускается предложением. В предложении говорится об усечении фактического значения, чтобы оно соответствовало фиктивному, если необходимо, а не заполнению его пробелами.

Код будет работать, если вы замените character(len = 20) на character(len = *). Есть ли здесь проблема, поскольку вы не хотели изменять длину спецификации фиктивного аргумента?

person M. S. B.    schedule 25.01.2011
comment
проблема в том, что подпрограмма с символом (len = 20) находится в части кода, которую я не должен изменять. - person Stefano Borini; 25.01.2011
comment
Затем я предлагаю написать функцию склеивания, которая преобразует свои аргументы в символ (len = 20) и применить эту функцию к любому аргументу xx, который может быть недостаточно длинным: call xx (makelen20 (foo2)) - person M. S. B.; 25.01.2011

Мне кажется, что это стандартное совместимое поведение.

Fortran 2003, 12.4.1.2 Фактические аргументы, связанные с фиктивными объектами данных

Если скалярный фиктивный аргумент имеет тип символа по умолчанию, длина len фиктивного аргумента должна быть меньше или равна длине фактического аргумента. Фиктивный аргумент становится ассоциированным с самыми левыми len символами фактического аргумента.

Однако gfortran просто поднимает предупреждающее сообщение

Предупреждение: длина символа фактического аргумента меньше, чем у фиктивного аргумента 'name' (4/20) в (1)

Кажется, что компилятор Intel Fortran в этом отношении более совместим со стандартами. Так что промежуточная переменная, вероятно, единственный вариант.

Или на самом деле просто объявление переменной - вариант, потому что у вас ее нет в вашем коде. У вас есть буквальная константа. В любом случае жестко запрограммированные значения - не лучшая идея. знак равно

person Wildcat    schedule 24.01.2011

Причина возникновения этой ошибки заключается в том, что вашему методу разрешено читать / записывать до len=20 символов в фиктивный аргумент name. Ваш строковый литерал меньше этого количества, и ваш компилятор предупреждает вас об этом факте. Несмотря на то, что он объявлен intent(in), вы можете прочитать значение, превышающее фактическую длину аргумента, и вызвать нарушение прав доступа и т. Д.

Вероятно, вам следует придерживаться len=* с фиктивными аргументами и использовать len или len_trim при определении того, сколько символов безопасно читать / писать.

Или, если вы должны сохранить len=20, вы должны использовать временную переменную, используемую для передачи значений в этот метод. Или что-то более уродливое, вроде "hello"//repeat(" ", 15).

person user7116    schedule 03.02.2011