• 締切済み

フォートランの動作に関する質問

以下のような短いフォートランプログラムがあります。OS:Windows10 module com integer,parameter ::nd=10 end module program main use com print *, nd call sub stop end subroutine sub use com print *, nd return end 内容はモジュールで宣言したパラメータを確認してみるということです。 このプログラムがgfortranで動作せず、intel fortranでは全く問題ありません。 gfortranの結果は以下のようです。 f951.exe: Fatal Error: Reading module 'com' at line 1 column 1: Unexpected EOF GNU Fortran (Rev1, Built by MSYS2 project) 9.3.0 Copyright (C) 2019 Free Software Foundation, Inc. gfortranのこのバージョンに何か問題があるのでしょうか。前からすこしおかしいことには気づいていたのですが。私のコードに問題があるでしょうか。 ※Cが一番近いと思いましてこちらに上げました。

みんなの回答

  • asciiz
  • ベストアンサー率70% (6630/9393)
回答No.5

回答no.1に少し間違いがありました 「特殊ファイル名」として挙げたリストのうち、「COM0」「LPT0」は特殊ファイル名ではありませんでした。 >(※1)実際には、特殊ファイル名をベースネームとするファイルは作成できないはずです。 この回答No.4の一文を書いた後に実験したんですが、実際に "com0.txt" も "com.txt" も作成できます。 でも "com1.txt" は作成できません。 「COM1」は確かに特殊ファイル名です。 だとすると、ここから想像になりますが、 ・GNU Fortranにおいて「module abc」というような記述をしたとき、「ABCx(xは1以上の数値).拡張子」というようなファイルが作成される ・それがたまたま「module com」により「COM1.拡張子」というファイル名を作成することになってしまった。 ・それをコンパイル別段階で読み込もうとして、シリアルポート入力になってしまった。 こういうことであったかも…? でもやはりこの「特殊ファイル名」がまずいんでしょうから、command.com の内部コマンド名(例:「copy」「type」等)や、外部コマンドの名前(format(.exe)やconvert(.exe)等)などをモジュール名に使っても、何も問題ないでしょう。

skmsk1941093
質問者

お礼

回答ありがとうございます。 module comm integer :: x end module などとすると、gfortranではcomm.mdというバイナリファイルが出力されます。module comだったらcom.mdです。 プログラミングについては今回の例のようにシステムとかOSとかに気を使いつつプログラムの内部を編集していくのがプロだと思いますが、私のごときはプログラムだけに集中したいものだと思っています。絶対(に近い)信頼を確信するからこそプログラムの中身だけに入っていけるわけですね。変数名の付け方でアウトになる可能性があり、そのことに気を使わなければならないというのは本職の方に集中できないなあという気持ちはあります。

  • asciiz
  • ベストアンサー率70% (6630/9393)
回答No.4

>モジュール名は固有名なので常識の範囲で何でもアリだと思っていました。 基本的に何でもアリだと思うんですが、コンパイルしたときに「モジュールファイル」みたいなものができていないでしょうか? 例えば、「module abc」と書いたなら、コンパイルの過程で「abc.module」みたいなファイルができているとか。 (一時的に作成されて、最終プログラム完成時点では残ってない、とかだと見えないですけど…) 仮にそうだったとして、「module com」という記述から、「C:\Fortran\COM.module」みたいなファイルが出来ていたとすると、(※1) 回答No.1に書いたMS-DOS特殊ファイル名は、どのようなフォルダにあっても・どのような拡張子がついていても、特殊ファイル(デバイスファイル)として動作してしまいます。 そしてコンパイルの別段階で「COM.module」ファイルを読み取ろうとしても、そこではシリアルから読み取ろうとしてしまい、ご質問のエラーが出てしまった、ということあるかもしれません (だとすると回答No.1の指摘も微妙に間違ってるかも…)。 (※1)実際には、特殊ファイル名をベースネームとするファイルは作成できないはずです。 ---- まあ実際リネームで直ったっということですので、「com」というモジュール名が使えないのは、『コンパイラの実装方式』と『OSの都合』という【言語仕様外の話】で、ホントにたまたま都合の悪いモジュール名を使ってしまった、ということになりますかね…。 unix系のOSであれば、デバイスファイルは必ず /dev/console とか /dev/ttyS0 みたいに /dev/ 特殊フォルダからの指定が必須になるので、普通にcon.txt でも com.module でもファイル作成できます。 汎用コンピュータ上のFortranでも COM とか指定しても何の問題もないでしょうね。(使ったことありませんが!)

  • sat000
  • ベストアンサー率40% (324/808)
回答No.3

1行目の1カラムに問題ありということを示しています。 ひょっとして7カラムからでなく、1カラムから書いてますか? 1カラムから書く場合は自由形式でないといけません。 GNU Fortran の場合は拡張子で判断するので、拡張子をf90やf95などとする必要があります。固定形式の場合はfやforにします。 あと今回のエラーとは関係ありませんが、end module -> end module comと書かないとコンパイルエラーになるかもしれません。 あと、mainのend -> end program main、subのところもend subroutine subですね。 それから、stopは不要になりました。あってもエラーにはなりませんが。

skmsk1941093
質問者

お礼

回答ありがとうございます。これは自由形式で書いています。fortran95の仕様です。以前のfortran77の形式に慣れていましたが、95の形式に移行しています。拡張子はf95です。 モジュール、メイン、サブルーチンの閉じ方についてはやり方に幅があるようです。 また、いけるコンパイラといけないコンパイラがある、というところで戸惑っています。intel はいけています。ただし、やや古いので拡張子はf95でなく、f90にしています。拡張子だけが違うものです。

  • dragon-man
  • ベストアンサー率19% (2700/13647)
回答No.2

昔のプログラマですが、今のフォートラン(Fortran)は我々の頃とまったく違うのですね。Fortranは”formula translation”の略称で数式の機械語への変換を行うコンパイラでした。お示しのプログラム例はそれとまったく異なる記述様式です。驚きました。単なる感想で、回答にならなくて済みません。

skmsk1941093
質問者

お礼

コメントありがとうございます。自由形式になるとか、構造体やポインタがあるとか、C言語みたいです。 Cよりfortranがいいのはあんまり方言がないこととかバージョンアップして仕様が変わるとかが少なく、上位互換って言うんでしょうか、仕様が変わっても古いものが見捨てられないというのがありますね。F77の古いコードがF95のコンパイラで動作していました。今回の質問はコンパイラが変わっていける・いけないの差が出てきたということでフォートランの利点が損なわれたように思えたからなのですが。

  • asciiz
  • ベストアンサー率70% (6630/9393)
回答No.1

「COM」という名前を使う必要はありますか? common とか command とかの省略のつもりだったでしょうか? と言うのも、Windowsでは、デバイスを表す特殊ファイル名というのが存在します。MS-DOS時代(以前)からの遺産です。 コンソール(キーボード)入力を示す CON だとか、プリンタ出力を表す PRNなど。 そういう予約ファイル名の中に、COM0~COM9 と言う物が存在します。 厳密に言えば COM は COM0 ではないので、intel Fortran ではきちんと通るのかもしれません。 しかしgFortranの方では、COM=COM0のことだ、と解釈して、モジュールの com ではなく シリアルポートの COM0 からの読み込みを行おうとしてしまい、EOFに到達した(何も読めなかった)、と言うエラーが出てしまっているのかもしれません。 モジュール名を com 以外の物にしてみるとどうでしょう。 もちろん、次のような予約ファイル名と一致してはいけません。 予約ファイル名: CON, PRN, AUX, NUL, CLOCK$, COM0, COM1, COM2, COM3, COM4, COM5, COM6, COM7, COM8, COM9, LPT0, LPT1, LPT2, LPT3, LPT4, LPT5, LPT6, LPT7, LPT8, LPT9

skmsk1941093
質問者

お礼

回答ありがとうございます。それが正解でした。リネームで通りました。シリアルポートのあのCOMと解釈していたようです。モジュール名は固有名なので常識の範囲で何でもアリだと思っていました。ファイル名として使えないのはコマンド名とか組み込み関数名とかでしょうか。 また、intel fortranは通るというのはどうしたわけだろうと思いますが。また予約語であってもコンパイラがよきに取り計らうということはないのでしょうか。JavaとかC++ などは使い方(でてくる場面)に依存して解釈してくれるようですが。オーバー〇〇とかですかね。ロードとかライドとか。

関連するQ&A

  • 最新のgfortranでのコンパイルエラー

    GNU Fortran (Rev1, Built by MSYS2 project) 9.3.0ですが、現時点での最新バージョンと思われます。以下のソースファイルをコンパイルしてみました。 module abc real x,y end module abc program test use abc x=3.14 y=5.55 print *, x,y call xxx print *, x,y end program test subroutine xxx use abc x=5.55 y=3.14 end subroutine xxx その結果、 f951.exe: Fatal Error: Reading module 'abc' at line 1 column 46: Unexpected EOF というエラーになります。 10年以上前のintel fortranだと問題なくコンパイルでき結果もOKです。 できれば新しいコンパイラを使いたいのですが、ソースをどのように改変していけばいいでしょうか。また、最新版のコンパイラをやめた方がいいのでしょうか。コンパイラを新しくして他にもトラブルが出ているのですが。 Cのカテゴリですみません。ここしか思い当たらないので。

  • フォートランのサブルーチンの内部変数

    すみません。科学技術系の人間でして、フォートランが現役なのです。 あるプログラムのことですが、サブルーチンの内部の変数についてサブルーチンを呼び出すごとに加算していくようなことを行っています。 do i=1,100 call abc(i)   ← サブルーチンabcを100回呼び出す enddo end subroutine abc(i) n=n+1        ←呼び出されるたびに和をとる。 write(*,*) n return end このようなシンプルなプログラムは問題ないのですが、少し複雑になるとどういうわけか、呼び出される度にnが初期化され、writeさせた結果常に1が表示されるという現象に会いました。 昔のコンパックフォートラン(MS-Fortran, DEC Fortranを継承)と、最近のIntel Fortran(最新版)で動作が異なります。前者では和を取ってくれますが、後者では初期化されて常に1が出力されます。(上記のプログラムは問題なしです。もう少し長いプログラムでの問題です。) 言語仕様の問題(すなわちフォートランのバージョン)なのか、コンパイラ仕様の問題なのか、C言語のように宣言の仕方で変ったりするようになったというようなことはないでしょうか。 以下に示すように和をとる変数をメインプログラム側に一旦見えるようにすると、インテル版でも思ったとおりの動作をします。 call abc(i,n) suboroutine abc(i,n) としてnをメイン側に露出する。 よろしくお願いします。

  • Fortranについて教えてください

    Fortran90で書かれた、又はこれから書く、プログラム実行したく GCCのgfortranをインストールしました。OSは、Windows XPです。 ところが、コンパイルのところで、つまずいてなかなか進みません。 (gfortranは動いてますので、インストールに問題はないと思います。) そこで、gfortranについて(オプション等)、解説しているサイトや文献を教えて頂きたいと思います。 英語力があまり無いので、日本語のものを紹介いただけると助かります。 また、十数年ぶりのフォートランですので(現在はVBAしか触っていません)、初学者向けだと、なお助かります。 どうか、よろしくお願いします。

  • 64ビットPCでのフォートランコンパイラ

    仕事柄いまだにフォートランのプログラムソースを書いています。物理シミュレーションを行っており、計算機の高速化に期待しているところです。地球シミュレータなどのメインフレーム?ではなく、高速のパソコンでも仕事ができるような程度のものです。 さて、質問ですが、最近、64ビットPC機、64ビット対応OSが手ごろな価格でも出ています。ノートPCでさえ8メガのメモリを積んでいるようです。この場合、フォートランコンパイラについても64ビット対応である必要があるのでしょうか。インテル、Visual Fortran, FTN95, G95, Gfortranなど有償・無償いろいろあると思います。64ビットOS用のコンパイラがあるのでしょうか。それとも従来の32ビット版でも十分な計算速度が出るでしょうか。よろしくお願いします。

  • モジュールとなったライブラリ集の利用法

    以下、長文ですみません。 サブルーチンとか関数に関するプログラム集というものがあり、自分でメインを適当に作ってそれらを呼び出して使うというライブラリ集のようなものがあります。昔からあるもので各言語に応じた本なども多数出版されています。 Fortranなのですが、F77の頃は以下のパターンが1つのファイルで延々と1万行ぐらい続くものです。ファイル名:A.f ---------------- 以下の形式のサブルーチン群の羅列 subroutine abc() いろいろ return end ---------------- このようなものは、例えば、 gfortran -c A.f としてリンクなしでコンパイルし、オブジェクトA.oが出力され、 メインプログラム(B.f)から呼び出す場合、 gfortran B.f -o A.o とすると、実行形式が出力されます(ここまで前置きが長くてすみません)。 さて、Fortran95だと状況が一変します。 A.f95だと以下のように変更されています(A.fの後継としてのA.f95)。 ------------- module A interface.... public... private... そしてサブルーチン群 subroutine abc() いろいろ return end subroutine abc end module A ------------ これを gfortran -c A.f95 とリンクなしでコンパイルすると、A.mod, A.oという2つのファイルが出力されます。 その後、メイン(B.f95)の作成ですが、モジュールA.modを読み込むため、 USE A を先頭にし,中身をF95のフォーマットにしています。その後、 gfortran B.f95 -o A.o あるいは gfortran B.f95 とするのですが、B.f95からcallしているA.f95の中のサブルーチンが発見できないというエラーになります。これら(A.f95, B.f95, A.o, A.mod)はすべて同一フォルダ内部のファイルです。 ここで万事休すなのですが、何かFortran95の処理で間違っているところがあるでしょうか。私がFortran95の処方を間違っているからではないかと思いますが、対処方法についてもしご存じでしたら、よろしくお願いします。 ※カテゴリ違いかもですが、ここしか聞く当てがないと思っています。

  • 隔絶されているサブルーチン間の通信の方法

    以下のようなFortranのサブルーチンとモジュールがあります。これを見ると、サブルーチンA,Bはモジュールa,bが別なのでデータ的に隔絶されていることになります。もし、このような場合、サブルーチンA,Bの間で何らかの変数を共有するようなことをしたい場合、どのような方法があるでしょうか。サブルーチンの引数を使うのは混乱の原因になりそうなので、できればmoduleの方で処理できないかと思うのですが。 混乱しそうなところなので、やり方をいろいろ比較して見てみたいと思います。Cではグローバル変数のように全体で共有する変数を用意するのかなと思いますが。 module a end module module b end module subroutine A use a end subroutin B use b end Fortranについてはここでは特設会議室はありませんが、どこかいいところがあるでしょうか。Cの専門家はいろんなことに通じていると思うのでここにお尋ねしました。よろしくお願いします。

  • visual studioについて

    visual studio express 2013の新規コンソールアプリの始めに出てくる Module Module1 Sub Main() End Sub End Module は何なのですか?消してもいいのですか? プログラムを書くときはこの下から書けば良いのですか? 教えてください。

  • メインルーチンの変数をモジュールに渡す

    Perlの勉強をし始めの者なんで、恥ずかしい質問ですけど・・・ モジュールの使い方です。 以下のプログラムではTest_module.pmで定義した変数$testをメインルーチンでprintしています。 ***** メインルーチン *****  #perl /usr/bin/perl  use Test_module;  our $test=10;  print $Test_module::test; ***** Test_module.pm *****  package Test_module;  our $test=10;  1; これはちゃんと動いています。 ところが逆にメインルーチンで定義した変数$testをTest_module.pmに渡そうとすると、うまくいきません。 以下のプログラムをどう直せばいいのでしょうか。 ***** メインルーチン *****  #perl /usr/bin/perl  use Test_module;  our $test=10;  &Test_module::print_test(); ***** Test_module.pm *****  package Test_module;  sub print_test {  print $Main::test;  }  1;

    • ベストアンサー
    • Perl
  • VBAでオブジェクト名に関する質問

    Excel2003を使っています。 例えば、 Sub Module1() ActiveWorkbook.Charts.PrintOut Copies:=1, Collate:=True End Sub というプログラムをVBAで作成します。このときオブジェクト名をModuleとして設定します。 すると、ツール⇒マクロで見られるマクロ名は xxxx.XLS!Module1 のようになります。 一方で、オブジェクト名をプログラム名と同じModule1にすると ツール⇒マクロで見られるマクロ名は xxxx.XLS!Module1.Module1 のようになります。 これって一体なぜなのでしょうか? 他のプログラムから他のプログラムを呼び出したいときに、 Module1と設定してしまうと xxxx.XLS!Module1.Module1のプログラムを呼び出すことは出来ません。 一体どういう利点があってこういう仕様になっているのでしょうか? また、オブジェクト名をプログラム名は別の名前にすべきなのでしょうか?

  • 副プログラムの変数について

    Fortranなのですが、以下のようなプログラムがあります。 call sub1 call sub1 end subroutine sub1 !save a write(*,*) a a=1.0 return end sub1というサブルーチンをメインから2回呼び出すだけです。そのサブルーチンの中の変数aですが、2回目に呼び出されたときに1回目に設定したa=1が保持されているようです。2回目の呼び出しで1回目に設定したa=1に対応した出力になっています。 Fortranはこのような動作をするのでしょうか。save aをコメントアウトしているのです。save aを指定したときだけそうなると思っていたのですが。cなどは細々とした設定ができるだろうと思います。このサンプルコードは実際にそうなっているという実験なのですが、どういう風に解釈したらいいでしょうか。〇〇保存属性とかです。昔からこうだったのでしょうか。使用したのはgfortran ver.9.3ですが。 

専門家に質問してみよう