Fortran :: Syntax error in OPEN statement at (1) - fortran

I was trying to test my cryptography algorithm by [diehard tests] (http://stat.fsu.edu/pub/diehard/), that I realized my input file must be an unformatted and direct access file.
So I tried to write a simple program in Fortran to read from a file and write it to another.
First of all, is it the only way to make an unformatted or direct access file ?
If it is so, I've got this Error
open(unit=2, file='unf.BIN',RECL=rl , form='UNFORMATTED', access='direct')
1
Error: Syntax error in OPEN statement at (1)
I use RECL because of some missing RECL parameter in Open statement errors.(Fortran 90, Compiling program: Error messages)
Here is my Fortran code:
program BinaryWriter
implicit none
integer :: i
integer :: p
open(unit=1,file='encout')
open(unit=2, file='unf.BIN',RECL=rl , form='UNFORMATTED', access='direct')
do i=1 ,256
read (8,'(i1)') p
write(*,*) p
end do
close(1)
close(2)
end program BinaryWriter

Two things:
1) Please stop using unit numbers less than 10. Virtually all modern Fortran compilers do now have the newunit identifier, which, instead of the old unit actually picks an unused value, so always use a variable there. But even if you want to use unit, set it to a value of 10 or more.
2) For direct access, the program needs the record length. So if you have access="direct", you also need an recl=<some integer value> to tell the compiler where a new record starts.
Now in your case, you have a RECL=rl entry in the open statement, but I can't see what rl is. It needs to be a positive integer.
Edit to add: As #IanH pointed out in a comment below your question, it is possible that you are using fixed form fortran. This might be caused by the file extension of your source code file being .f or .f77. In that case, you'd have to wrap your lines manually:
program dir
implicit none
integer :: rl
open(unit=20, file='delme.bin', recl=<the record length>,
& form='unformatted', access='direct')
close(20)
end program dir
Note that the & is in the 6th position of the line. Fortran 77 code usually uses a + there, but & is also compatible with newer Fortran versions, that's why I prefer it. F77 standard is just any character in that 6th spot.

Related

How to output "data1.dat" file using "iswap" subroutine using the following code?

subroutine iswap (file, b)
integer b
open(1,file = "file",status='unknown',form="unformatted")
write (1) b
close(1)
end
program callex
open(22, file = 'data1.dat')
call iswap(file,2)
close(22)
stop
end
Output: empty dat1.dat file
I'm completely new to Fortran. I'm trying to write the code that produces an output file "dat1.dat" containing the value of b, i.e 2, by using the "iswap" subroutine, but I'm getting an empty file. Could you please tell me the mistake I made in the code?
Thanks in advance.
By
open(1,file = "file",status='unknown',form="unformatted")
you are opening (creating if does not exiat) creating a file called "file"
and by
write (1) b
you write the value of b to this file.
The file "data1.dat" is opened under unit 22 so you have to write to that unit if you want to write to this file.
write (22) b
There is no reason to open and close another file called "file" in your subroutine.
It is also very important to use implicit none. Otherwise you have will be surprised by having undeclared stuff like the file variable you use in call iswap(file,2).
You can pass the unit number to your subroutine
subroutine iswap (unit, b)
implicit none
integer unit, b
write (unit) b
end
program callex
implicit none
open(22, file = 'data1.dat')
call iswap(22,2)
close(22)
end
There is no reason for the stop statement before the end. It is useless and may indoce some surprising messages like the signalling FPE exceptions.
Finally, you should to learn how to put your subroutines into a module as soon as possible. I strongly suggest to avoid external subroutines if at all possible. Also use some consistent indentation (spaces at the start of the lines) so that the structure is better visible.
module subs
implicit none
contains
subroutine iswap (unit, b)
integer, intent(in) :: unit, b
write(unit) b
end subroutine
end module
program callex
use subs
implicit none
open(22, file = 'data1.dat')
call iswap(22, 2)
close(22)
end program
It is also quite useless to use status="unknown". If you want to specify status, choose something specific "old", "new", "replace", otherwise just leave it out. There are many other specifiers in the open statement that are worth learning, like action (read/write) and others that control other modes for binary files. This is not a place to show them, they are explained in various manuals, tutorials and textbooks.

`Unexpected element ‘\’ in format string` in code written for MS Fortran [duplicate]

I have a project written in VS2010 with Intel Visual Fortran. I have a dump subroutine to write a 2D matrix into file:
subroutine Dump2D(Name,Nx,Ny,Res)
implicit none
integer i,j,Nx,Ny
real(8) :: Res(Nx,Ny)
character(len=30) name,Filename
logical alive
write(filename,*) trim(Name),".dat"
Write(*,*) "Saving ",trim(Name)," Please wait..."
open (10,file=filename)
do i=1,Ny
Write(10,FMt="(D21.13\)") (Res(j,i),j=1,Nx)
Write(10,*)
end do
close(10)
Write(*,*) "Save ",trim(Name),"Complete!"
return
end subroutine Dump2D
It is ok to compile and run. But when I compile in emacs using gfortran it gives me the error:
I think it's because the gfortran doesn't recognize \ in a format for a write command. How do I fix this problem?
Write(10,FMt="(D21.13\)") (Res(j,i),j=1,Nx)
1
Error: Unexpected element '\' in format string at (1)
The edit descriptor \ relates to backslash editing. This is a non-standard extension provided by the Intel compiler (and perhaps others). It is not supported by gfortran.
Such backslash editing is intended to affect carriage control. Much as in this answer such an effect can be handled with the (standard) non-advancing output.1
As you simply want to output each column of a matrix to a record/line you needn't bother with this effort.2 Instead (as you'll see in many other questions):
do i=1,Ny
write(10,fmt="(*(D21.13))") Res(:,i)
end do
There are also other approaches which a more general search will find.
1 The Intel compiler treats \ and $ in the same way.
2 There are subtle aspects of \, but I'll assume you don't care about those.
Another approach (although francescalus answer is better in your case) would be to build a format string that contains the number of elements to include in your row. One way of doing this is to use the following to build the format string (which uses an explicit space character to separate elements within a line in the file):
WRITE(fmtString, '(A,I0,A)') '(', Nx, '(D21.13,:,1X))' *
Then use the format string variable in your WRITE statement as so:
do i=1,Ny
Write(10,FMt=fmtString) (Res(j,i),j=1,Nx)
end do
This approach can also be very useful if you want to use something other than spaces to separate elements (e.g. commas or semicolons).
*As that's a little difficult to read, I will provide an example. For Nx = 3, this would be equivalent to:
fmtString = '(3(D21.13,:,1X))'
Which is 2 numbers formatted using D21.13, each followed by a space, and a final number formatted using D21.13, but without a space after it (as the ":" stops at the final item).
The backslash is not valid in Fortran 77 FORMAT statements. Gfortran will not compile it, unless you fix the code. There is no flag that will change that AFAIK (-fbackslash should not help here).
If I understand the intention correctly (and I may be wrong), the backslash does the same as the dollar sign in some other compilers and prevents terminating a record (line). In that case the advance="no" put in the write statement should help. It is Fortran 90, but you should not avoid it just for that reason.

write formatted UTF-8 text file fortran

I'm trying to write in from fortran a text file.
I did this short test program but of course it does not work, because it does not create a text file that could be readable :
PROGRAM teste
INTEGER(4) REC2,RECL1
character(20) :: charI, wanted
RECL1=10
DO REC2=1,10
OPEN(1,FILE='teste.txt',ACCESS="direct",RECL=RECL1);
write (charI, "(A5,I4)") "hello", REC2
wanted=trim(charI)
write(1,REC=REC2) wanted
close(1)
END DO
END PROGRAM teste
I read lot of different thing but it's still really unclear how it should be written.
Do I need to convert to string before writing ? if yes why ?
Try this
PROGRAM test
IMPLICIT NONE
INTEGER, PARAMETER :: ascii = selected_char_KIND ("ascii")
INTEGER, PARAMETER :: ucs4 = selected_char_KIND ('ISO_10646')
INTEGER :: ix
CHARACTER(len=5,kind=ucs4) :: greeting = ucs4_"hello"
OPEN(10,FILE='test.txt')
DO ix=1,10
WRITE (10,'(A5,I4)') greeting, ix
END DO
CLOSE(10)
END PROGRAM test
... a commentary ...
PROGRAM test
IMPLICIT NONE
All good Fortran programs include the line implicit none; the reason for this is explained in 101 Qs and As here on Stack Overflow and I won't repeat them here.
INTEGER, PARAMETER :: ascii = selected_char_KIND ("ascii")
INTEGER, PARAMETER :: ucs4 = selected_char_KIND ('ISO_10646')
The latest Fortran standard requires that compilers provide these two kinds of character. I'm honestly not sure if iso_10646 is the same as UTF-8 but if it isn't you're probably out of luck. Here, I'm defining two parameters for identifying the character kinds to use later in the program. For your purposes the first of these parameters is unnecessary but you ought to know about it too.
I suppose your compiler might support other character kinds, read the documentation.
(Aside: technically, there is a third character kind name, default. This is likely to set the character kind to either ascii or iso_10646, most likely the former, but if this is important to you check your compiler's documentation.)
INTEGER :: ix
CHARACTER(len=5,kind=ucs4) :: greeting = ucs4_"hello"
In the second of these lines I've defined a character variable with the text hello and of kind ucs4 (which, as you see above, is a local code for iso_10646). Without the prefix ucs4_ the string hello will be interpreted as being of kind default and then converted to ucs4 when stored into the variable greeting. In this case, where there is a 1:1 mapping between the (representation of) the characters in ascii and in ucs4 the prefix is strictly unnecessary but there will be other cases where it won't be.
OPEN(10,FILE='test.txt')
DO ix=1,10
WRITE (10,'(A5,I4)') greeting, ix
END DO
CLOSE(10)
I've removed all the guff about direct access and writing at particular records in a file. It's all unnecessary for what seems to be your immediate need. So this loop will write greeting (ie the ucs4 string hello) and a row index into the file test.txt 10 times.
END PROGRAM test
In your open statement you are opening a file for unformatted input/output. Because you have specified ACCESS="direct" the default is for unformatted, compared with the default as formatted when connected for sequential access.
To make the file "readable" you need to actively open for formatted access, and provide a format for the writing:
open(1,FILE='teste.txt',ACCESS="direct",RECL=RECL1, FORM='formatted')
...
write(1,fmt=...,REC=REC2) ...

gfortran error: unexpected element '\' in format string at (1)

I have a project written in VS2010 with Intel Visual Fortran. I have a dump subroutine to write a 2D matrix into file:
subroutine Dump2D(Name,Nx,Ny,Res)
implicit none
integer i,j,Nx,Ny
real(8) :: Res(Nx,Ny)
character(len=30) name,Filename
logical alive
write(filename,*) trim(Name),".dat"
Write(*,*) "Saving ",trim(Name)," Please wait..."
open (10,file=filename)
do i=1,Ny
Write(10,FMt="(D21.13\)") (Res(j,i),j=1,Nx)
Write(10,*)
end do
close(10)
Write(*,*) "Save ",trim(Name),"Complete!"
return
end subroutine Dump2D
It is ok to compile and run. But when I compile in emacs using gfortran it gives me the error:
I think it's because the gfortran doesn't recognize \ in a format for a write command. How do I fix this problem?
Write(10,FMt="(D21.13\)") (Res(j,i),j=1,Nx)
1
Error: Unexpected element '\' in format string at (1)
The edit descriptor \ relates to backslash editing. This is a non-standard extension provided by the Intel compiler (and perhaps others). It is not supported by gfortran.
Such backslash editing is intended to affect carriage control. Much as in this answer such an effect can be handled with the (standard) non-advancing output.1
As you simply want to output each column of a matrix to a record/line you needn't bother with this effort.2 Instead (as you'll see in many other questions):
do i=1,Ny
write(10,fmt="(*(D21.13))") Res(:,i)
end do
There are also other approaches which a more general search will find.
1 The Intel compiler treats \ and $ in the same way.
2 There are subtle aspects of \, but I'll assume you don't care about those.
Another approach (although francescalus answer is better in your case) would be to build a format string that contains the number of elements to include in your row. One way of doing this is to use the following to build the format string (which uses an explicit space character to separate elements within a line in the file):
WRITE(fmtString, '(A,I0,A)') '(', Nx, '(D21.13,:,1X))' *
Then use the format string variable in your WRITE statement as so:
do i=1,Ny
Write(10,FMt=fmtString) (Res(j,i),j=1,Nx)
end do
This approach can also be very useful if you want to use something other than spaces to separate elements (e.g. commas or semicolons).
*As that's a little difficult to read, I will provide an example. For Nx = 3, this would be equivalent to:
fmtString = '(3(D21.13,:,1X))'
Which is 2 numbers formatted using D21.13, each followed by a space, and a final number formatted using D21.13, but without a space after it (as the ":" stops at the final item).
The backslash is not valid in Fortran 77 FORMAT statements. Gfortran will not compile it, unless you fix the code. There is no flag that will change that AFAIK (-fbackslash should not help here).
If I understand the intention correctly (and I may be wrong), the backslash does the same as the dollar sign in some other compilers and prevents terminating a record (line). In that case the advance="no" put in the write statement should help. It is Fortran 90, but you should not avoid it just for that reason.

End of Record error when saving a variable

I'm having a runtime error when I run a code that works without problems using a different computer.
I'm wondering if the problem is the Fortran compiler of this machine (GCC 4.9.2) since the former computer used a previous version.
The issue comes when defining a variable like this:
In a module I define
character(30),allocatable,save :: sceneclass(:)
Then in the subroutine sceneclass is defined according to
character(30) surf, frac, scene
allocate(sceneclass(10))
do i=1,10
write(sceneclass(i),*) trim(scene)//trim(surf)//'_'//trim(frac)
enddo
In the first iteration I get the "End of record". But I don't know where is the problem. It seems to work fine in other computers.
You are probably writing a string to sceneclass(i) that is longer then the 30 chars you specified.
I can reproduce this with
program test
implicit none
character(10),allocatable :: sceneclass(:)
integer :: i
allocate( sceneclass(10) )
do i=1,10
write(sceneclass(i),*) 10**i
enddo
print *, ( trim(sceneclass(i)), i=1,10 )
end program
gfortran fails with
Fortran runtime error: End of record
while ifort reports the error correctly:
output statement overflows record, unit -5, file Internal List-Directed Write
Increasing the string length to 12 solves the issue in this case. You can (and should) use iostat within the write statement to capture this.
One thing to be aware of, when you specify a list directed * write of a character string, the compiler always(?) adds an extra lead blank, so the effective length of the string you can write is one less than you might expect.
To remedy that (and of course assuming you don't want the lead blank anyway ) use a string edit descriptor:
write(sceneclass(i),'(a)')...
Interestingly ifort (linux 11.1) actually allows you to overrun by one character:
character*5 c
write(c,*)'12345' ! result: " 1234"
which I would consider a bug. It seems they forgot to count the blank too.. ( gfortran throws the above error on this, and ifort balks if you add one more character )
see here if you wonder why the blank.. Are Fortran control characters (carriage control) still implemented in compilers?
and now I'm curious if some compiler somewhere didn't do that for an internal list write, or maybe your code was previously compiled with a flag to disable the "printer control" code