Поиск:

Ответ в темуСоздание новой темы Создание опроса
> [General] Разобраться в синтаксисе, Старая программа синтаксис не ясен 
V
    Опции темы
artjomp
Дата 1.2.2009, 23:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 8
Регистрация: 1.2.2009

Репутация: нет
Всего: нет



Здравсвуйте, Уважаемые Знатоки Fortran!
Имеется в наличие код на фотране. Необходимо высянить, что эта прога делает. Файлов до фига и в принципе после долгих ковыряний структуру я уяснил, но не понял некоторых, возможно для знающего банальных вещей.
Пример:
Код

      DIMENSION S(10,10),KF(4)
      COMMON /W3/ C(6,10),NP(10)
      COMMON /W4/ L(4),MY(4),A(4)
    1 FORMAT(9I3)
    2 FORMAT(1X,F3.0,10F6.0)
    3 FORMAT(3X,9I6)
      read(5,1) (L(I),I=1,4),(KF(J),J=1,4),KK
      write(6,3)(L(I),I=1,4),(KF(J),J=1,4),KK
      DO 70 K=1,10
      GOTO(10,12,14,16,18,20,22,25,28,32),K [color=red]**[/color]
   10 CALL D10 (KP)
      D=10      
      GOTO 40
   12 CALL D12 (KP)
      D=12
      GOTO 40
   14 CALL D14 (KP)
      D=14
      GOTO 40
   16 CALL D16 (KP)
      D=16
      GOTO 40
   18 CALL D18 (KP)
      D=18
      GOTO 40
   20 CALL D20 (KP)
      D=20
      GOTO 40
   22 CALL D22 (KP)
      D=22
      GOTO 40
   25 CALL D25 (KP)
      D=25
      GOTO 40
   28 CALL D28 (KP)
      D=28
      GOTO 40
   32 CALL D32 (KP)
      D=32
   40 DO 60 I=1,KP
      IF(KK-24)49,49,42       [color=red]***[/color]
   42 S(K,I)=25000./NP(I)
      GOTO 60
   49 DO 50 J=1,4
   50 MY(J)=C(KF(J),I)
      CALL PRM
      S(K,I)=F(KK)
   60 CONTINUE 
      write(6,2)D,(S(K,I),I=1,KP)     [color=red]*[/color]
   70 CONTINUE
      STOP
      END

PRM и F это процедура и функция они описаны тут всё в порядке smile
* что значит тут I=1? В файл запишется правда или ложь этого логического выражения или в файл запишется число 1?
** что означает эта конструкция? По-очереди вызвать все перечисленные в скобках метки? А зачем после скобок буква K?
*** как это вообще понимать? Два раза вызывается метка 49 и один раз 42 или тут завуалирован else?
И ещё непонятный кусок кода:
Код

  140 DO 142 J=1,KP
      X(J)=OK(I(3)*H*100/(CK(J)/1.E8*I(2)*CP+1+CO))
      XX(K,J)=X(J)
      Y(J)=OK(NP(J)*1274/D/D)
  142 YY(K,J)=Y(J)

Значит ли это, что это цикл от сточки с меткой 140 до строчки с меткой 142? А где же слово CONTINUE? Или оно необязательно?
Что такое 1.Е8 в формуле?

PM MAIL   Вверх
Фантом
Дата 2.2.2009, 00:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Вы это прекратите!
***


Профиль
Группа: Участник Клуба
Сообщений: 1516
Регистрация: 23.3.2008

Репутация: 5
Всего: 49



В строчке, помеченной одной звездочкой, сидит скрытый цикл. 

Конструкция write(6,2)D,(S(K,I),I=1,KP) - это печать в 6-ой файл (как правило, это по умолчанию вывод на консоль, 5-й файл, соответственно, чтение с консоли) по формату с меткой "2" (он там где-то сверху описан) сначала содержимого переменной D, а потом элементов массива S(K,I) для всех I от 1 до KP. 

Строчка с двумя звездочками - это переход на метку в зависимости от значения переменной K. Когда K=1  - переход на первую метку из списка (10), когда K=2 - на вторую (12) и т.д. Вся эта конструкция:
Код

      GOTO(10,12,14,16,18,20,22,25,28,32),K
   10 CALL D10 (KP)
      D=10      
      GOTO 40
   12 CALL D12 (KP)
      D=12
      GOTO 40
   14 CALL D14 (KP)
      D=14
      GOTO 40
   16 CALL D16 (KP)
      D=16
      GOTO 40
   18 CALL D18 (KP)
      D=18
      GOTO 40
   20 CALL D20 (KP)
      D=20
      GOTO 40
   22 CALL D22 (KP)
      D=22
      GOTO 40
   25 CALL D25 (KP)
      D=25
      GOTO 40
   28 CALL D28 (KP)
      D=28
      GOTO 40
   32 CALL D32 (KP)
      D=32

на самом деле является реализацией переключателя (switch в C/C++ или case в Паскале).

Строчка с тремя звездочками - это арифметический оператор условного перехода. Смысл такой: считается выражение в скобках (т.е. KK-24), и если оно отрицательное, то выполняется переход на первую метку (49), если равно нулю, то на вторую метку (тоже 49), а если положительно, то на третью (42). В итоге вся конструкция
Код

   40 DO 60 I=1,KP
      IF(KK-24)49,49,42  
   42 S(K,I)=25000./NP(I)
      GOTO 60
   49 DO 50 J=1,4
   50 MY(J)=C(KF(J),I)
      CALL PRM
      S(K,I)=F(KK)
   60 CONTINUE 

переписывается на современном Фортране в таком виде (метки я сохранил, чтобы было понятнее, что чему соответствует, в реальной программе их можно спокойно стереть):
Код

40   DO I=1,KP
      IF ((KK-24)>0) THEN 
   42  S(K,I)=25000./NP(I)
      ELSE
     49 DO J=1,4
           MY(J)=C(KF(J),I)
     50 END DO
      CALL PRM
      S(K,I)=F(KK)
      END IF
60  END DO


В "непонятном цикле" цикл действительно до метки 142 включительно. Слово CONTINUE не является обязательным, это просто пустой оператор, который можно снабдить меткой (оно нужно именно для того, чтобы границы циклов и т.п. были лучше видны).

1.E8 - это 1.0*(10^8). 

PM   Вверх
Cr@$h
Дата 2.2.2009, 02:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Исследователь
***


Профиль
Группа: Участник Клуба
Сообщений: 1693
Регистрация: 3.4.2005
Где: Санкт-Петербург, Россия

Репутация: 1
Всего: 41



Цитата(Фантом @  2.2.2009,  01:05 Найти цитируемый пост)
Строчка с двумя звездочками - это переход на метку в зависимости от значения переменной K. Когда K=1  - переход на первую метку из списка (10), когда K=2 - на вторую (12) и т.д. Вся эта конструкция:
на самом деле является реализацией переключателя (switch в C/C++ или case в Паскале).

smile Я бы на самом деле выражался так аккуратнее, а то будут потом говорить, что в Fortran нет конструкции-переключателя. Конечно, не будут и, конечно, она есть. Просто в F66-77 её ещё не было. Если код планируется использовать повторно, то лучше проводить небольшой рефакторинг по мере сил, желания и эстетических амбиций:
Код

    dimension S(10,10), KF(4)
    common /W3/ C(6,10), NP(10)
    common /W4/ L(4), MY(4), A(4)

    read(5,(9i3)) (L(I), i = 1, 4), (KF(J), j = 1, 4), kk
    write(6,(3x,9i6)) (L(I), i = 1, 4), (KF(J), j = 1, 4), kk
    do k = 1, 10
        select case(k)
            case(1)
                call D10(kp)
                d = 10
            case(2)
                call D12(kp)
                d = 12
            case(3)
                call D14(kp)
                d = 14
            case(4)
                call D16(kp)
                d = 16
            case(5)
                call D18(kp)
                d = 18
            case(6)
                call D20(kp)
                d = 20
            case(7)
                call D22(kp)
                d = 22
            case(8)
                call D25(kp)
                d = 25
            case(9)
                call D28(kp)
                d = 28
            case(10)
                call D32(kp)
                d = 32
        end select
        do i = 1, kp
            select case(kk - 24)
                case(:0)
                    S(k,i) = 25000. / NP(i)
                case(1:)
                    MY(1:4) = C(KF(1:4),i)
                    call Prm
                    S(k,i) = F(kk)
            end select
        end do
        write(6,(1x, f3.0, 10f6.0)) D, (S(k,i), i = 1, kp)
    end do
end

Код

! Если подпрограмма Prm чистая (хотя бы не меняет значения kk), то последний цикл лучше переписать,
! убрав переключатель из него.
select case(kk - 24)
    case(:0)
        S(k,1:kp) = 25000. / NP(1:kp)
    case(1:)
        do i = 1, kp
            MY(1:4) = C(KF(1:4),1:kp)
            call Prm
            S(k,i) = F(kk)
        end do
end select
! Если подпрограмма Prm ещё и не меняет значений массивов C, KF, F, то можно записать так:
select case(kk - 24)
    case(:0)
        S(k,1:kp) = 25000. / NP(1:kp)
    case(1:)
        MY(1:4) = C(KF(1:4),1:kp)
        call Prm
        S(k,1:kp) = F(kk)
end select
! Полезно подумать, чему я наложил именно такие условия для Prm в двух вариантах выше.
! Оба варианта будут работать быстрее, особенно второй из предложенных.

Если функция Ок чистая, то код:
Код

  140 DO 142 J=1,KP
      X(J)=OK(I(3)*H*100/(CK(J)/1.E8*I(2)*CP+1+CO))
      XX(K,J)=X(J)
      Y(J)=OK(NP(J)*1274/D/D)
  142 YY(K,J)=Y(J)

лучше переписать так:
Код

    140 continue
    X(1:kp) = Ok(I(3) * H * 100 / (CK(1:kp) / 1.E8 * I(2) * CP + 1 + CO))
    XX(k,1:kp) = X(1:kp)
    Y(1:kp) = Ok(NP(1:kp) * 1274 / D / D)
    YY(k,1:kp) = Y(1:kp)

Старайтесь записывать код кратко, если имеете возможность использовать компилятор, хотя бы поддерживающий F90. От меток можно избавиться. F09 позволяет эффективно записывать без меток вообще любой алгоритм. И добро пожаловать в мир элегантности и скорости современного Fortran.

Это сообщение отредактировал(а) Cr@$h - 2.2.2009, 02:21
PM MAIL ICQ   Вверх
artjomp
Дата 2.2.2009, 14:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 8
Регистрация: 1.2.2009

Репутация: нет
Всего: нет



Огромное вам человеческое СПАСИБО!!!
Вы просто спасли меня, а то я уже просто голову сломал именно в этих местах  smile 
PM MAIL   Вверх
FatalError
Дата 2.2.2009, 16:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 92
Регистрация: 11.4.2006

Репутация: нет
Всего: 1



Cr@$h, y человека же весь код написан в фиксированном формате, а Вы ему подсунули кусок в свободном, которым предполагается заменить имеющийся код. Соответственно, компилятор, дойдя до стыка форматов, начнет матюгаться совершенно не по-деццки. И будет абсолютно прав. Опять же не ясно, к какому компилятору есть доступ у artjomp, вдруг он на g77 сидит?
PM MAIL   Вверх
artjomp
Дата 2.2.2009, 16:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 8
Регистрация: 1.2.2009

Репутация: нет
Всего: нет



О версии ни малейшего понятия... Комп старый престарый, даже разъём монитора с двухрядным набором штырьков... Какой-то фотран под ДОС.
Но сейчас занимаюсь поиском компилятора какой-нибудь новой версии и попробую запустить эту прогу. Ну или в итоге буду "эту польку на родной язык перепёр" (с) на родной Паскаль или Си.
Т.е. лучше не изменять код, как указал Cr@$h? Может не заработать на новом?
PM MAIL   Вверх
Cr@$h
Дата 2.2.2009, 20:14 (ссылка) |   (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Исследователь
***


Профиль
Группа: Участник Клуба
Сообщений: 1693
Регистрация: 3.4.2005
Где: Санкт-Петербург, Россия

Репутация: 1
Всего: 41



Цитата(FatalError @  2.2.2009,  17:02 Найти цитируемый пост)
Cr@$h, y человека же весь код написан в фиксированном формате, а Вы ему подсунули кусок в свободном, которым предполагается заменить имеющийся код. Соответственно, компилятор, дойдя до стыка форматов, начнет матюгаться совершенно не по-деццки.

Понимаю всё собственной натурой . Но надежда есть  smile 
Цитата(artjomp @  2.2.2009,  17:19 Найти цитируемый пост)
сейчас занимаюсь поиском компилятора какой-нибудь новой версии и попробую запустить эту прогу

Попробуйте g95. Правда.
Цитата(artjomp @  2.2.2009,  17:19 Найти цитируемый пост)
Ну или в итоге буду "эту польку на родной язык перепёр" (с) на родной Паскаль или Си.

Ни в коем случаею Если можете эту прогу на Pascal и C писать, то лучше используйте более менее современный компилятор Fortran.
Цитата(artjomp @  2.2.2009,  17:19 Найти цитируемый пост)
Т.е. лучше не изменять код, как указал Cr@$h? Может не заработать на новом? 

В зависимости от того, какой у вас компилятор. Тот код выполнен в стандарте Fortran 90. Ничего стращного, но красиво, не правда ли? smile
PM MAIL ICQ   Вверх
Фантом
Дата 2.2.2009, 20:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Вы это прекратите!
***


Профиль
Группа: Участник Клуба
Сообщений: 1516
Регистрация: 23.3.2008

Репутация: 5
Всего: 49



Цитата(artjomp @  2.2.2009,  16:19 Найти цитируемый пост)
Т.е. лучше не изменять код, как указал Cr@$h? Может не заработать на новом? 


Наоборот, изменяйте. Сохранение старого кода сейчас имеет смысл только в том случае, если Вы собираетесь эту программу на той же машине под ДОС и гонять. А если она Вам нужна в нормальном виде, то лучше и код переделать. При этом, если эта задача для Вас не единичная, то стоит последовать совету  Cr@$h'а - пишите не на Паскале или C, а на современном Фортране.
PM   Вверх
artjomp
Дата 2.2.2009, 21:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 8
Регистрация: 1.2.2009

Репутация: нет
Всего: нет



Скачал компилятор http://progopedia.ru/implementation/gfortran/
Поборол кучу выдаваемых мелких ошибок.
А вот это побороть не могу :-(
G:\Program Files\gfortran\bin>gfortran.exe z.for
C:\DOCUME~1\APTEM\LOCALS~1\Temp/ccF9HcEa.o:z.for:(.text+0x16dd): undefined reference to `_ok_'
C:\DOCUME~1\APTEM\LOCALS~1\Temp/ccF9HcEa.o:z.for:(.text+0x1762): undefined reference to `_ok_'
C:\DOCUME~1\APTEM\LOCALS~1\Temp/ccF9HcEa.o:z.for:(.text+0x2754): undefined reference to `_ok_'
collect2: ld returned 1 exit status

И сразу вопрос ещё возник:
Код

      D(I)=(K(J)*K(J)*K(J)-K(I)*K(I)*K(I))?B(I)

Вопросительный знак - это опечатка? На самом деле
Код

      D(I)=(K(J)*K(J)*K(J)-K(I)*K(I)*K(I))/B(I)

Или в фортране есть такой оператор - вопросительный знак? Просто он ругался на эту строчку, пока я не поставил знак "/"
PM MAIL   Вверх
FatalError
Дата 2.2.2009, 21:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 92
Регистрация: 11.4.2006

Репутация: нет
Всего: 1



Вопросительного знака как оператора нет, это определенно опечатка.
Цитата

Комп старый престарый, даже разъём монитора с двухрядным набором штырьков... 

Похоже, что мониторчик еще EGA. Это очень плохо. Работать на таком - только зрение портить. Я абсолютно серьезно.
Цитата

undefined reference to `_ok_'

Это сочетание - `_ok_' - встречается в программе? Знаки подчеркивания на первой позиции должны встречаться только в служебных словах. Возможно, что компилятор по ходу дела сам где-то поставил этот символ, а потом его не распознал. Возможно, компилятор не совсем правильно настроен, или не совсем правильно задана компиляция (скажем, программа состоит из нескольких файлов, какой-то пропущен).
PM MAIL   Вверх
artjomp
Дата 2.2.2009, 22:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 8
Регистрация: 1.2.2009

Репутация: нет
Всего: нет



Комп этот уже выбросили.
Сочетания `_ok_'  нигде в программе не встречается. Компилятор я не настраивал вообще... Просто скачал, установил и запустил smile
Программа была из нескольких файлов. Процедуры и функции были по разным файлам раскиданы. Я их всех в один файл запихал посмотрел ещё раз. Нет ничего не забыл... Что может ещё быть или как настроить компилятор?
Может вообще взять какой-нибудь visual fortran там же наверное и оболочка есть, которую можно понастраивать с компилятором?
PM MAIL   Вверх
Фантом
Дата 2.2.2009, 22:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Вы это прекратите!
***


Профиль
Группа: Участник Клуба
Сообщений: 1516
Регистрация: 23.3.2008

Репутация: 5
Всего: 49



Цитата(artjomp @  2.2.2009,  22:20 Найти цитируемый пост)
Что может ещё быть или как настроить компилятор?


А Вы можете отправить сюда то, что скармливали компилятору? Оптимально - всю программу (в однофайловом варианте) и весь вывод компилятора.
PM   Вверх
Cr@$h
Дата 2.2.2009, 22:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Исследователь
***


Профиль
Группа: Участник Клуба
Сообщений: 1693
Регистрация: 3.4.2005
Где: Санкт-Петербург, Россия

Репутация: 1
Всего: 41



Цитата(artjomp @  2.2.2009,  23:20 Найти цитируемый пост)
Сочетания `_ok_'  нигде в программе не встречается

В исходны файлах должна быть определена такая фукция Ok.
PM MAIL ICQ   Вверх
artjomp
Дата 3.2.2009, 15:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 8
Регистрация: 1.2.2009

Репутация: нет
Всего: нет



Вот программа в файле. То, что выдаёт компилятор я писал выше smile это всё.
G:\Program Files\gfortran\bin>gfortran.exe z.for
C:\DOCUME~1\APTEM\LOCALS~1\Temp/ccF9HcEa.o:z.for:(.text+0x16dd): undefined reference to `_ok_'
C:\DOCUME~1\APTEM\LOCALS~1\Temp/ccF9HcEa.o:z.for:(.text+0x1762): undefined reference to `_ok_'
C:\DOCUME~1\APTEM\LOCALS~1\Temp/ccF9HcEa.o:z.for:(.text+0x2754): undefined reference to `_ok_'
collect2: ld returned 1 exit status

Cr@$h она определена само собой smile

Это сообщение отредактировал(а) artjomp - 4.2.2009, 12:34
PM MAIL   Вверх
Фантом
Дата 3.2.2009, 16:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Вы это прекратите!
***


Профиль
Группа: Участник Клуба
Сообщений: 1516
Регистрация: 23.3.2008

Репутация: 5
Всего: 49



Цитата(artjomp @  3.2.2009,  15:05 Найти цитируемый пост)
она определена само собой


Что-то я этого определения нигде не вижу.  smile Вы уверены, что никакой кусок программы при сращивании в файл не потеряли?
PM   Вверх
Ответ в темуСоздание новой темы Создание опроса
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Fortran | Следующая тема »


 




[ Время генерации скрипта: 0.0592 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.