There is a conventional way to read each line one by one and check iostat
hits nonzero or negative value at every reading. However, I would like to call system(command)
routine and
use wc -l
command to count the number of and then want to allocate the dimension of the array where I want to put the data. For the example, I am printing the number of lines in both ways:
Program Test_reading_lines
integer:: count,ios, whatever
character(LEN=100):: command
Print*,'Reading number of lines in a standard way'
count=0
open (10, file='DATA_FILE')
Do
read (10,*,iostat=ios) whatever
if (ios/=0) exit
count=count+1
End Do
close(10)
Print*,'Number of lines =', count
Print*,'Reading number of lines using shell command'
command='cat DATA_FILE | wc -l'
call system(command)
Print*,'Number of lines =','< ? >'
End Program Test_reading_lines
Unfortunately, in the latter case, can I assign a variable like count
as in the standard case? That is, I want to print a variable instead of '< ? >'
in the last print command.
This is not possible in a straightforward way. You could redirect the output of the command to a file, then open it and read it http://compgroups.net/comp.lang.fortran/how-to-get-the-output-of-call-system-in-a-v/216294
Or use some even more sophisticated features of the Unix functions and call its C API (see the first answer in that thread).
The EXECUTE_COMMAND_LINE() also does not have any feature to read the output of the command directly.
If you want to use the Unix command $ wc -l
, you could call the Fortran subroutine execute_command_line
which is common to many Fortran compilers, gfortran
included.
Here is a working example which computes the number of lines, nlines
, of a file called style.gnuplot
and then uses nlines
to append some rows to style.gnuplot
by overwriting the last one.
PROGRAM numLines
IMPLICIT NONE
integer, parameter :: n = 100
integer :: i, nLines
real, parameter :: x0 = -3.14, xEnd = 3.14
real :: dx
real, dimension (:), allocatable :: x, fun
allocate(x(0:n)) ! Allocate the x array
allocate(fun(0:n)) ! Allocate the fun array
dx = abs(xEnd-x0)/n
x(0:n) = [(x0+i*dx, i = 0,n)] ! Create the x array
fun(0:n) = [(sin(x0+i*dx), i = 0,n)] ! Create the fun array
open(unit=1,file="plotFunction.dat")
DO i=0,size(x)-1
write(1,*) x(i), ' ', fun(i) ! Save the function to a file to plot
END DO
close(unit=1)
deallocate(x) ! Deallocate the x array
deallocate(fun) ! Deallocate the fun array
open(unit=7, file="style.gnuplot")
write(7,*) "set title 'y = sin(x)' font 'times, 24'"
write(7,*) "set tics font 'times, 20'"
write(7,*) "set key font 'times,20'"
write(7,*) "set grid"
write(7,*) "set key spacing 1.5"
write(7,*) "plot '<cat' u 1:2 w l lw 2 linecolor rgb 'orange' notitle "
close(unit=7)
CALL execute_command_line("wc -l style.gnuplot | cut -f1 -d' ' > nlines.file") ! COunt the lines
open(unit=1,file='nlines.file')
read(1,*) nlines ! Here the number of lines is saved to a variable
close(unit=1)
CALL execute_command_line("rm nlines.file") ! Remove nlines.file
CALL execute_command_line("cat plotFunction.dat | gnuplot -p style.gnuplot") ! Show the plot within the executable
open(unit=7,file="style.gnuplot")
DO i = 1,nLines-1
read(7,*) ! Read the file untile the penultimate row,
END DO ! then append the other rows
write(7,*) "set object rectangle at -3.14,0 size char 1, char 1", &
" fillcolor rgb 'blue' fillstyle solid border lt 2 lw 1.5"
write(7,*) "set object rectangle at 0,0 size char 1, char 1", &
" fillcolor rgb 'blue' fillstyle solid border lt 2 lw 1.5"
write(7,*) "set object rectangle at 3.14,0 size char 1, char 1", &
" fillcolor rgb 'blue' fillstyle solid border lt 2 lw 1.5"
write(7,*) "plot 'plotFunction.dat' u 1:2 w l lw 2 linecolor rgb 'orange' notitle"
close(unit=7)
CALL execute_command_line("gnuplot -p 'style.gnuplot'") ! Load again style.gnulot with the appended lines
END PROGRAM numLines
My code might not be elegant, but it seems to work!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With