This question already has answers here:
Passing character strings of different lengths to functions in Fortran
(2 answers)
Closed 2 years ago.
I have a bunch of files, which contain numbers in rows. I need to write a function, that
reads from file for the first time to find amount of elements in file;
allocates an array and reads numbers from file into array;
returns an array
My function gets a string - name of the file - as an input.
So, the function that I wrote is:
function arrays_proc(name) result(arr)
character(len=128), intent(in) :: name
integer :: i, tmp, ios
character(len=30) :: line
double precision, dimension(:), allocatable :: arr
open(unit=09, file=name, status='old', iostat=ios)
if ( ios /= 0) stop "error opening file"
tmp = 0
do
read(09, '(A)', iostat=ios) line
if (ios /= 0) exit
tmp = tmp + 1
end do
allocate(arr(tmp))
rewind(09)
do i=1, tmp
read(09, '(A)') arr(i)
end do
close(09)
return
end function arrays_proc
Then, in the main program I write
...
real(8), dimension(:), allocatable :: points, potent
points = arrays_proc(trim('carbon_mesh.txt'))
potent = arrays_proc(trim('carbon_pot.txt'))
...
When I run my program, I get instant "error opening file".
I assume the problem is with names of files or how I put them in my function.
Anyway, I hope someone can help me
When compiling your code with a minimal program, GFortran prints the following warnings:
a.f90:4:25:
4 | points = arrays_proc(trim('carbon_mesh.txt'))
| 1
Warning: Character length of actual argument shorter than of dummy argument ‘name’ (15/128) at (1)
a.f90:5:25:
5 | potent = arrays_proc(trim('carbon_pot.txt'))
| 1
Warning: Character length of actual argument shorter than of dummy argument ‘name’ (14/128) at (1)
Trying to print the value of name inside arrays_proc shows that it is filled with garbage. So, guided by the warnings, you can try to change the length of the name parameter to *, which allows a string of any length to be used as input.
With that change, the function manages to open the files.
See also: Passing character strings of different lengths to functions in Fortran
I'm learning Fortran with the book Fortran 90 for scientists and engineers by Brian Hahn. In chapter 9 about arrays, pages 131/132, he gives the following code as an example of dynamic arrays
Program Chap_9_Allocatable_Array
Implicit none
! Variables
Real, dimension(:), Allocatable :: X, OldX
Real A
Integer IO, N, i
! Body of Chap_9_Allocatable_Array
Allocate( X(0) ) !Size zero to sart with?
N = 0
Open(1, File = 'Data.txt')
Do
Read(1, *, IOStat = IO) A
If (IO < 0) Exit
N = N + 1
Allocate( OldX( Size(X) ) )
OldX = X !Entire array can be assigned
Deallocate( X )
Allocate( X(N) )
X = OldX
X(N) = A
Deallocate( OldX )
End do
Print *, (X(i), i = 1, N)
End program Chap_9_Allocatable_Array
I have implemented this program in Visual Studio Community 2019 with the Intel Visual Fortran Compiler. The purpose of this program as he explains is
The following program extract shows how to use allocatable arrays, as these beasts are called, to read an unknown amount of data, which unfortunately must be supplied one item per line because of the way READ works.
I found an interesting error. The file data.txt consists of 100 random numbers, 1 per row. When I try to run it, it just seems to stall for a couple of seconds and then the console simply prints the
Press any key to continue.
prompt, without an error message. I have inserted some debug prints and determined that the program runs the do cycle between 3 to 8 times before stopping. I have not been able to determine the reason. If I then change the data.txt file to only be 3 numbers long, the program runs as intended. With the debug prints, I have pinned the error to being the
Deallocate( X )
line. If I debug the program in Visual Studio I just get the following message:
Chap_9_Allocatable_Array.exe has triggered a breakpoint.
There have been a few minor errors in the book. Just in this example, the author seems to have forgotten to declare i, which caused a compile error. However, as I'm only beggining to understand arrays, I don't know what else to try. Any ideas?
I am trying to code a program that allows me to count the number of columns in a file (in the example below datos.txt). However, gfortran tells me there is an error:
"Expected variable in read statement".
How can I solve this? In the example, I used 100 as the maximum number of columns possible. The real value is 5.
What I have tried is this:
program contarcolumnas
implicit double precision (a-h,o-z)
implicit integer*8 (i-n)
open (50, file="datos.txt")
m=1
dimension matrizfichero(1,100)
do i=1,1
read(50,*)(matrizfichero(i,j),j=1,m)
if (iostat /= 0) then
m=m+1
else
print*,m
end if
end do
close(50)
end program contarcolumnas
I am having trouble reading exponential from a text file using Fortran.
The entry in the text file looks like the following
0.02547163e+06-0.04601176e+01 0.02500000e+02 0.00000000e+00 0.00000000e+00 3
And the code that I am using looks like the following
read(iunit,'(ES20.8,ES20.8,ES20.8,ES20.8,ES20.8,I2)') dummy1, dummy2, Thermo_DB_Coeffs_LowT(iS,1:3),temp
The error I am getting is
Fortran runtime error: Bad value during floating point read
How can I read these values?
Well here is what I usually do when it is too painful to hand edit the file...
CHARACTER(LEN=256) :: Line
INTEGER, PARAMETER :: Start = 1
INTEGER :: Fin, Trailing_Int, I
DOUBLE, DIMENSION(6) :: Element
...
Ingest_All_Rows: DO WHILE(.TRUE.)
READ(...) Line ! Into a character-string
<if we get to the end of the file, then 'EXIT Ingest_All_Rows'>
Start =1
Single_Row_Ingest: DO I = 1, 6
Fin = SCAN(Line,'eE')+3 !or maybe it is 4?
IF(I ==6) Fin = LEN_TRIM(Line)
READ(Line(Start:Fin),*) Element(I) !fron the string(len-string) to the double.
Line = Line((Fin+1):)
IF(I ==6) Trailing_Int = Element(6)
ENDDO Single_Row_Ingest
<Here we shove the row's 5 elements into some array, and the trailing int somewhere>
ENDDO Ingest_All_Rows
You will have to fill in the blanks, but I find that SCAN and LEN_TRIM can be useful in these cases
I am trying to use the code below to read a formatted file and write it into another. However, on running it shows the following error
$ ./conv.sac.farm < i_conv.farm
# stn comp Delta Tr-time Start in record
At line 54 of file Main/conv.sac.farm.f (unit = 5, file = 'stdin')
Fortran runtime error: Bad real number in item 1 of list input
The source code is as follows
PARAMETER (nd0=100000,pi=3.1415926)
IMPLICIT COMPLEX*8 (Z)
CHARACTER name*6,comp*6,fname*60,event*20
- ,cmp(0:3)*5,fname0*60,charac*15,scode*60
REAL*8 GFACT(500),PP0(500),depth0
integer hr0,mnu0,yr,month,day,hr,mnu
REAL x(nd0),y(nd0)
DIMENSION Z(nd0),zpole(50),zero(50)
data np,cmp/8,'disp.','vel. ','acc. ','orig.'/
common /tbl/ip(110,14),is(110,14),secp(110,14),secs(110,14)
read(5,'(a)') event
read(5,*) alats,alons,depth,hr0,mnu0,sec0,id,delmin,delmax
depth0=depth
write(22,'(a,a5,3f7.2,2i3,f6.2)')
# event,cmp(id),alats,alons,depth,hr0,mnu0,sec0
* << J-B travel time table >>
OPEN(11,FILE='jb.ptime')
OPEN(12,FILE='jb.stime')
1000 read(11,*,end=1001) n,(ip(n,i),secp(n,i),i=1,14)
goto 1000
1001 read(12,*,end=1002) n,(is(n,i),secs(n,i),i=1,14)
goto 1001
1002 continue
close(11)
close(12)
* << Geometrical factor >>
OPEN(15,FILE='jb.table')
CALL GEOM(GFACT,PP0,depth0)
close(15)
nstn=0
print *,' # stn comp Delta Tr-time Start in record'
5 read(5,'(a)') fname
read(5,'(a)') scode
* ta=advance of start-time relative the standard P/S arrival
* du=duration
c
if(fname.eq.'dummy') goto 90
read(5,*) ta,du,dt,f1,f2,iph,nr,iuni
open(1,file=fname)
READ(1,'(g15.7)') dt0
read(1,'(/////5g15.7)') dum, alat, alon, elev
read(1,'(///////5i10)') yr, nday, hr,mnu, nsec
read(1,'(5i10)') nmsec,ndum,ndum,ndum,nd
read(1,'(/////)')
read(1,'(a6,2x,a13)') name,charac
read(1,'(////)')
And so on..
Line 54 is
read(5,*) ta,du,dt,f1,f2,iph,nr,iuni
I found a similar question following this link
Fortran runtime error: Bad real number
However, if I understand correctly, the corrections mentioned were pertaining to reading unformatted data. Despite this, I tried and failed as expected, given that the file I am trying to read is formatted.
here is a little trick if you can't readily find the offending line in the data file:
replace your read that throws the error with this:
read(5,'(a)')line
read(line,*,iostat=ios) ta,du,dt,f1,f2,iph,nr,iuni
if(ios>0)then
write(*,*)'error reading line:',line
stop
endif
with the declarations
integer ios
character*(200) line
Probably just do that for debugging then revert to the original once you fix the problem.