I have a fortran program with a lot of statements like this:
write(0,*) '*** ERROR *** something went wrong ',i
write(0,*) '*** ERROR *** something happend in line ',i
write(0,*) '*** ERROR *** something happend in line ',i,' of file ',filename
Is it possible to create a custom subroutine, e.g. log_error(msg) that allows the same arbitrary number and types of input as write?
Related
In a program I am improving, I noticed that Fortran does not detect file existing or not. This led to a logic error which has not been fixed. I highly appreciate if you could point out the problems or errors and give me your corrections.
open(unit=nhist,file=history,iostat=ierr)!This setting cannot exit program if file does not exist because ierr is always 0
if (ierr /=0) then
write(*,*)'!!! error#',ierr,'- Dump file not found'
stop
endif
!I used below statement, the program exits even though a file is existing
open(unit=nhist,file=history,err=700)
700 ierr=-1
if (ierr /=0) then
write(*,*)'!!! error#',ierr,'- Dump file not found'
stop
endif
There are two distinct problems here. Let's look at them separately.
First, consider
open(unit=nhist,file=history,iostat=ierr)
The comment suggests that ierr is always set to zero. Well, why shouldn't it be set to zero? ierr should be non-zero in the case the case of an error, but is the file not existing an error?
Not necessarily. In the absence of a status= specifier the default status='unknown' is taken. The compiler doesn't have to (and is unlikely to) treat opening in this case as an error if the file doesn't exist. It's likely to create it as needed on a write, or complain when trying to read.
Adding status='old' to the open statement is the usual way of saying "the file should exist".
Second, consider
open(unit=nhist,file=history,err=700)
700 ierr=-1
if (ierr /=0) then
...
If there's an error here, execution is transferred to the statement labelled 700. From this statement ierr is set to a non-zero value and off we go to the if construct to handle that error.
It's just that the statement labelled 700 also happens to be executed even without an error: it's simply the next statement after the open and there's no branch to miss it. [I could give an example of such branching, but I don't want to encourage use of err= in modern code. With the working iostat= things are far preferable.]
But if you just wish to test the existence of a file, consider inquire-by-file:
logical itexists
inquire (file=history, exist=itexists)
if (.not.itexists) error stop "No file :("
Some would argue this is even better than having status='old' in an open statement.
In a program I am improving, I noticed that Fortran does not detect file existing or not. This led to a logic error which has not been fixed. I highly appreciate if you could point out the problems or errors and give me your corrections.
open(unit=nhist,file=history,iostat=ierr)!This setting cannot exit program if file does not exist because ierr is always 0
if (ierr /=0) then
write(*,*)'!!! error#',ierr,'- Dump file not found'
stop
endif
!I used below statement, the program exits even though a file is existing
open(unit=nhist,file=history,err=700)
700 ierr=-1
if (ierr /=0) then
write(*,*)'!!! error#',ierr,'- Dump file not found'
stop
endif
There are two distinct problems here. Let's look at them separately.
First, consider
open(unit=nhist,file=history,iostat=ierr)
The comment suggests that ierr is always set to zero. Well, why shouldn't it be set to zero? ierr should be non-zero in the case the case of an error, but is the file not existing an error?
Not necessarily. In the absence of a status= specifier the default status='unknown' is taken. The compiler doesn't have to (and is unlikely to) treat opening in this case as an error if the file doesn't exist. It's likely to create it as needed on a write, or complain when trying to read.
Adding status='old' to the open statement is the usual way of saying "the file should exist".
Second, consider
open(unit=nhist,file=history,err=700)
700 ierr=-1
if (ierr /=0) then
...
If there's an error here, execution is transferred to the statement labelled 700. From this statement ierr is set to a non-zero value and off we go to the if construct to handle that error.
It's just that the statement labelled 700 also happens to be executed even without an error: it's simply the next statement after the open and there's no branch to miss it. [I could give an example of such branching, but I don't want to encourage use of err= in modern code. With the working iostat= things are far preferable.]
But if you just wish to test the existence of a file, consider inquire-by-file:
logical itexists
inquire (file=history, exist=itexists)
if (.not.itexists) error stop "No file :("
Some would argue this is even better than having status='old' in an open statement.
I am struggling to read from one input text file into a new text file using the Fortran compiler in Visual Studio 10. My input file is in gslib format (attached)
program main
! Unit numbers:
lisa = 4
lfke = 9
! Writing input data to file Lisa
open(unit=lisa,file='fake.dat',status='OLD',err=80)
open(unit=lfke,file='dlfke',status='NEW', err=80)
read(lisa,*,err=80)
read(lisa,*,err=80) line
write(9,*) line
close(unit=lisa)
close(unit=lfke)
80 stop 'ERROR in test file!'
end
This program is always going to produce the error message "ERROR in test file", whether or not there is an error. After executing line the close statements, it will next execute line 80 with the stop statement. You will probably find it easier, as your develop your program, to remove the err=80 tests in each IO statement. Then if there is an IO error, the program will automatically terminate and produce a specific message about the program. These err=branches are useful if you want to have your program handle the error, but with this implementation its hiding what the IO error was since all IO errors produce the same message.
I am getting the error message:
Error 90 File access and properties are incompatible
The piece of code that gives me the error is the following:
PARAMETER (NPT=250, NPR=9)
IMPLICIT REAL*8 (A-H,O-Z)
CHARACTER*255 ARQDAT
DIMENSION Z(NPT,NPT,NPR)
COMMON/CPROP/ TMIN,TMAX,DT,PMIN,PMAX,DP,VMIN,VMAX,DX,DX2,DY,DY2,Z
REAL*4 RGAS
!* Read matrix
OPEN(UNIT=10,FILE=ARQDAT,FORM='UNFORMATTED', ACCESS='DIRECT',RECL=1)
READ(10) Z !this is the statement giving error ARQDAT is a binary file
CLOSE(UNIT=10)
Why or what should I do?
You opened the file ACCESS='DIRECT' but are doing a sequential READ on it - this is not allowed. Often when people do ACCESS='DIRECT',RECL='1' they want to read a byte at a time, but you have to combine this with a REC= value in the READ statement. In modern Fortran there are other, better ways to do this (such as ACCESS='STREAM').
What compiler are you using and on what operating system?
I compile a fortran 77 code using gfortran and get the following error:
10 open (23,file=outfile,status='old',access='append',err=10)
1
Warning: Branch at (1) may result in an infinite loop
This happens several times.
One of the output files looks like the following:
^L6a10È <90> ) &<9b>LÓLÓLÕ<91><90> <90> <90> È <8e><9b>LÓLÓLÕ<93>2
!MERCURY ¢¤õ/!ô<8a><8a><90> ÿ<90> ÿ<90> ÿÌÖÏ©ü}M<91>
"VENUS «}>±{©±<8b><90> ÿ<90> ÿ<90> ÿʺ93¿<8d>d<91>
However, it should just look like a table of text.
Any ideas?
Your line of code
10 open (23,file=outfile,status='old',access='append',err=10)
specifies that the open statement should transfer control to itself (label 10) in case an error is encountered, so any error could trigger an infinite loop. It also suppresses the output of error messages. If you want to just check for an error status, I would suggest using the iostat and/or iomsg (Fortran 2003) arguments:
open (23, file=outfile, status='old', access='append', iostat=ios, iomsg=str)
Here ios is an integer that will be zero if no errors occur and nonzero otherwise, and str is a character variable that will record the corresponding error message.
The err= argument in your open statement specifies a statement label to branch to should the open fail for some reason. Your code specifies a branch to the line labelled 10 which happens to be the line containing the open statement. This is probably not a good idea; a better idea would be to branch to a line which deals gracefully with an error from the open statement.
The warning from gfortran is spot on.
As to the apparent garbage in your output file, without sight of the code you use to write the garbage (or what you think are pearls perhaps) it's very difficult to diagnose and fix that problem.