Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Fortran > [General] Возвращение из функции массива


Автор: Гость_Sun 5.9.2004, 00:28
Народ! Кто нибудь знает как в фортране 90 вернуть из функции массив? qstn.gif

Автор: Cr@$h 6.4.2005, 00:08
Гость_Sun 
Цитата
Народ! Кто нибудь знает как в фортране 90 вернуть из функции массив? 

В фортране все по-божески. Массив также может быть результатом функции. Интерфейс к такой функции должен быть задан явно. Если функция не является ссылкой, то границы массива должны быть описательными выражениями, которые вычисляются при входе в функцию.
Пример.
Составить функцию, возвращающую массив из первых n положительных элементов передаваемого в нее массива.
Код

function fap( a, n )

    integer n, k, i
    real fap(n)
    real a(:)

    fap = 0
    k = 0
    do i = 1, size(a)
        if( a(i) > 0 ) then
            k = k + 1
            fap(k) = a(i)
            if( k== n)&
                exit
        end if
    end do
end function fap

Автор: Балабол 28.4.2008, 16:44
Функция созданная по аналогичным мотивам 
Код
      function scroll(
     >                  cm
 
     >                  cordbox


      real scroll(4)
      real cordbox(:)
      integer cm
           do i = 1, 4
              KA(i)=cordbox(i+cm)
              if(i.eq.4)cm = cm + i
           end do
      return
      end function scroll
      

Результат
Код
e:\lab\Курсач\60408\N_formdd__FORMDD.for(178): error FOR3099: deferred-shape specification for non-POINTER or non-ALLOCATABLE array CORDBOX

Автор: FatalError 29.4.2008, 10:51
А в чем проблема? Компилятор не хочет работать с этим deferred-shape массивом, если он не является динамическим. О чем всех честно предупреждает. Если этот массив тупо прописать как ALLOCATABLE, все возражения должны исчезнуть.

Автор: Балабол 30.4.2008, 14:08
Проблема естественно в голове, которая заточена под структурное программирование, но спасибо за наводку

Автор: popovda 15.5.2008, 21:17
Причем тут динамический массив?! 

Какой компилятор используется?

(: ) в массивах надо указывать только для динамических массивов, либо указателей на массив, либо МАССИВОВ-ФОРМАЛЬНЫХ ПАРАМЕТРОВ!!! 

Для остального есть автоматические массивы. Но это стандарт 90 и выше. А у вас расширение файла .for. Потому его и компилирует 77-компилятор. Расширение f90 и компилятор соответствующий. У меня код сразу проглотил.  

Автор: FatalError 16.5.2008, 14:07
С этими ( : ) массивами вообще дело не так просто. Они были введены в стандарт Фортрана77 именно для использования в качестве массивов-формальных параметров. А потом из стандарта Фортрана95 deferred-shape массивы были ИСКЛЮЧЕНЫ. Так что совсем современные компиляторы не обязаны с ними работать в качестве формальных параметров функций и подпрограмм. Кстати, случай, который компилировал Балабол, как раз под этот вариант подпадает. Понятное дело, эти массивы в свое время были прописаны в жутком количестве программ, и поддержка этой фишки теперешними компиляторами крайне желательна. Но не обязательна, поскольку они уже нестандартные. Вот мне и показалось, что компилятор у Балабола их напрямую и не поддерживает, и поэтому требует, чтобы массивы эти прописали как динамические. Тогда, мол, так уж и быть, откомпилирую. Но я был, скорее всего, не прав. Проблема, как мне теперь кажется, в "сишном" стиле написания заголовка функции в примере Балабола, как у Маяковского, лесенкой. Выпендреж это и ни к чему. В результате синтаксические ошибки: пропали запятые и закрывающая кавычка. При фиксированной форме записи получается, что функция имеет один параметр: cm, дальше конец строки и обрыв параметров, cordbox уже не входит. И кавычки нет на месте. Мне кажется, компилятор вообще не понял, что это такое, и просто выдал формальную придирку.

Автор: popovda 16.5.2008, 21:31
Конечно! В оформлении кода Вы абсолютно правы. Я его руками вводил и как надоsmile Пардон, массивы заданной конфигурации ИСКЛЮЧЕНЫ?!! Что-то не то вы говорите. Откройте хотя бы стандарт 2003. Он - наследник 95-го. Проблемы были с другими массивами, которые подразумевают размер и определяются вот так (10,20,40,*). Они и были в Ф77. Их-то использовать и не рекомендуется. А массивы заданной конфигурации в стандарте есть. Это современное и надежное средство.

Автор: FatalError 17.5.2008, 21:21
Ну, значит, не так понял.

Автор: popovda 19.5.2008, 21:14
Эти 2 термина почему-то часто путают.smile

Автор: Иванофф 20.5.2008, 01:10
задававшего вопрос ответ вроде и не интересует.
зачем массив неизвестной длины возвращать как значение функции, разбираться с отладкой и согласованием длин.
для передачи значений есть параметры. а значение функции допустим указывает на успешность или неуспешность операции.
приведенные примеры как занятие йогой. сложно и непонятно зачем.

Автор: popovda 20.5.2008, 11:16
Насчёт размеров возвращаемого функцией (а вопрос был именно про функцию, на него и отвечали ) массива - часто длина известна, например, как при произведении матриц (matmul), там используются автоматические массивы. А вот если размер вычисляется внутри функции, то гораздо удобнее вернуть размещаемый массив. Эта черта современных стандартов языка реализована практически во всех компиляторах

Код

function d_MyArrayFunc(M) result (res)
...................................
             real(8), allocatable, dimension( : ) :: res;


или так

Код

function MyArrayFunc(M)
            ...........................
             real(8), allocatable, dimension( : ) :: d_MyArrayFunc;


Хотя часто эффективнее и удобнее пользоваться процедурами.

Автор: Иванофф 20.5.2008, 11:53
а если вопрошавший прочитал только первую главу "функции" в учебнике и сразу задал этот вопрос, потом прочитал главу "подпрограммы" и решил его для себя. надо говорить не только как можно сделать, но и как привильнее сделать.

Автор: popovda 20.5.2008, 16:24
И всё же для этого надо правильно ставить вопрос. Потом, мне подход с функциями нравится больше. Тем более, что сам стандарт языка подразумевает такой подход - он более информативен, а хороший компилятор (плохим компилятором Фортрана просто нет смысла пользоваться) всё равно очень качественно оптимизирует вызов такой функции. Заметьте разницу - например в C при вызове функции можно опустить результат, т.е. 

a = func();

или просто

func();

сработают.
В Фортране это недопустимо. Только a = func(). Чтобы переменная результата была заранее определена и при оптимизации не создавалось доп. переменной (по сути вызовы функции и процедуры в этом случае не отличаются, отличается лишь вызов в коде). 

Потом, результат вызова функции можно сразу использовать в качестве фактического параметра, а процедуры - нет. 

Например, C = transpose(conjg(matmul(A,X)))

Что на мой взгляд короче, понятнее и удобнее. Тем более, если промежуточные матрицы не нужны.

Но это уже моё личное мнение.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)