300 do i=1,counter
open(1,file='Pcow_pd.txt')
write(1,*),Sw_pd(i), Pcow_pd(i)
open(2,file='Krw_pd.txt')
write(2,*),Sw_pd(i), Krw_pd(i)
open(3,file='Kro_pd.txt')
write(3,*),Sw_pd(i), Kro_pd(i)
print*, counter
end do
print *,"filled =",filled
When I compile the code I get an error message at write lines which I cannot fix
Compile error: error 573 - Missing expression
As has been commented, there should be no comma before the list of items for output. You should simply have
write(1,*) Sw_pd(i), Pcow_pd(i)
and so on.
The later line
print*, counter
where the comma before counter is absolutely necessary, may add a little confusion on writing. This is perhaps increased by how read is used: there are two forms:
read *, x
read (*,*) y
The first example without an explicit statement of unit implies the same unit as the * in the second and it requires a comma. The second must not have a comma.
A simple way to remember whether the output list has a comma first: if the format comes in isolation use the comma; if the unit is specified, don't.
Related
I have to read a file that contains numerical data (mostly reals) but there are also some missing data that are denoted by an asterisk(*). I don't know the positions of the asterisks in advance and I have to find the total valid (numerical) data and the total missing data (asterisks).
I tried doing this with a 'select case' nested in a do loop but failed because
I can't use real type for the selector
I don't think I can put the asterisks in a real matrix
The data file looks something like this
1 0.673070
2 0.750597
3 *
4 0.484100
Any suggestions?
Yes in the future, please provide some more information and post a [Minimal, Complete, and Verifiable example] (https://stackoverflow.com/help/mcve) of some code that tries to read it.
But, assuming you know every line has either a real number or an *, I would do something like this:
Character(len=8) :: LineRead
Real :: RealNumber
open(42,file='MyFile.txt')
do (whichever kind of loop you need to control the input)
read(42,'(a8)') LineRead
if (LineRead <> '* ')
read(LineRead,'(f8.6)') RealNumber
! Increment some sort of valid data counter
end if
end do
If you are not familiar with this technique, it is called reading from an internal file. Any character variable can be 'read' this way.
I need a help about implicit do loop in Fortran.
This is my simple code:
Program Simple
Implicit none
Integer::i,j
Integer,parameter::N=2,M=3
Real,dimension(N,M)::Pot
Open(1,File='First.txt',Status='old')
Read(1,'(M(f3.1,1x))') ((Pot(i,j),j=1,M),i=1,N)
Close(1)
Open(2,File='Second.txt',Status='Unknown')
Write(2,'(M(i0,1x,i0,1x,f3.1,1x))') ((i,j,Pot(i,j),j=1,M),i=1,N)
Close(2)
Stop
End program Simple
This is the file First.txt:
1.1 1.2 1.3
2.1 2.2 2.3
When I try to execute this program I got a this message:
Unexpected element 'N' in format string
Unexpected element 'M' in format string
I want to keep the name of integer variables N and M in write statement.
Is there any way to also keep their values from declaration part?
You are using M and N in the string (as characters), not as variables. In order to use the variables you need to write their values into the format string:
character(len=128) :: fmtString
!...
write(fmtString,*) M
fmtString = '('//trim(adjustl(fmtString))//'(f3.1,1x))'
Read(1,fmtString) ((Pot(i,j),j=1,M),i=1,N)
And similarly for the write statement.
However, you can probably use list-directed input (Read(1,*)) for the input, and let Fortran figure out the exact format.
Instead of this string manipulation you can use (*(f3.1,1x)) in modern compilers, or if you have an old one just specify a very large number, e.g. (99999(f3.1,1x)). In both cases, the correct number of values will be printed. However, this will result into writing all m*n values in one single line [thanks #agentp for pointing this out].
I've been given the challenge to port a Fortran 77 program into C#.
I've found out that read(5,*) read from the standard input, i.e. the keyboard.
Now I'm trying to understand how the following works:
1. When I run the program, I have to run it as cheeseCalc<blue.dat>output.txt
, which read a blue.dat file and produces a output.txt file. How does read work in this case?
In the same program, there is READ(5,* )IDUM and later it also has read(5,*)idum,idum,tinit. What is happening in this case?
The blue.dat file has the following lines:
HEAD make new cake
INPUT VARIABLES
MFED MASS-FEED 30 ;1001 1 100 PEOPLE TO FEED
TOVE TEMP-IN-OVEN 150.0 ;1001 20 100 TEMPERATURE OF OVEN, C
UPDATED: Just for context, the initial lines of code in the program are:
program cheeseCalc
CHARACTER*76 IDENT
CHARACTER*1 IDUM
READ(5,104)IDENT
104 FORMAT(4X,A)
READ(5,*)IDUM
c write start record
write(6,102)IDENT
102 format('**START',/,4X,A,/)
read(5,*)idum,idum,frate
110 format(f10.0)
frate2=frate/3.6
read(5,*)idum,idum,tempo
* Do calculation *
write(6,*)frate2,tempo
end
Any help will be appreciated!! Thanks!
The full detail of the general read statement is documented elsewhere, but there is an idiom here which is perhaps worth elaborating on.
The statement read(5,*) ... is list-directed input from the external unit number 5. Let's assume (it's not guaranteed, but it's likely and you seem happy with that for your setup) that this external unit is standard input.
The idiomatic part is the repeated use of a single variable in an input list such as
read(5,*) idum, idum, ...
This (and the fact that idum is an (awfully named) length-1 character variable) signifies that the user doesn't care about the input in the first two fields). The first string, delimited by blanks, is read then the first character is assigned to idum. Then idum is immediately set to the first character of the next string.
The purpose of this is to set the place in the record to the third field, which is read into the (real) variable frate (in the first case).
Equally
read(5,*) idum
is just skipping the second line (strictly, reading the first character, but that's not used anywhere before the next read into idum): the first blank-delimited field is read but the next read moves on to the next line rather than continuing with that one.
i'm totally new to Fortran, and i want to write a test program using a real*8 function called NeQuick, so i've written the following program :
program test
implicit real*8 (a-h,o-z)
aNe=NeQuick(400.0D0,45.0D0,15.0D0,10,1.929D2,15.0D0)
write(6,'(A,E12.5,A)')
& ' NeQuick electron density =',aNE,' m^-3'
call sleep(10)
end program
At the end when i compile it I have the following errors in each line of the little program : -Non-numeric character in statement label at 1 or
-Unclassifiable statement at 1
Can you guys please explain me what's wrong with my program ?
The way this code is written tells me that it was intended to be fixed-form source. This requires that all of the code start in column 7, except for the & in the second line of the WRITE statement which should be in column 6. Often when such code is pasted into an editor, the leading blanks are removed. If you do this, though, you will have to rename the source file to have a .f or .for file type so that the compiler knows it is fixed-form.
Another, perhaps easier solution is to put an & at the end of the first line of the WRITE - this will then make the source as you have it valid free-form.
For some perspective on this, please read Source Form Just Wants to be Free.
Suppose I have the following code
program fortran
open(900, FILE='SOMETHING')
write(900, *) '21'
end program fortran
The file form will be
21
that is, there is a space before the number. How to get rid of that space?
You can write it as a string:
PROGRAM fortran
OPEN(900,FILE='SOMETHING')
WRITE(900,'(a)') '21'
END PROGRAM FORTRAN
> cat SOMETHING
21
To respond to the comment:
The more explicit way of doing that would be to write the number into a string (you could also use list-directed I/O for this step), remove whitespaces from the string trim and finally output the left-adjusted adjustl:
program test
character(len=23) :: str
write(str,'(ES23.15 E3)') 1.23d0
write(*,'(a)') adjustl(trim(str))
write(str,'(ES14.7 E2)') 0.12e0
write(*,'(a)') adjustl(trim(str))
end program
> ./a.out
1.230000000000000E+000
1.2000000E-01
This solution is probably more complicated then necessary, but it is a very flexible approach that can be extended easily for arbitrary purposes and formats.
In list-directed format (the * in write(unit,*)) the compiler typically inserts a leading space. The first column used to be used to control line printers but that is now deleted from Fortran.
You can use any explicit format you want to get rid of the leading space. For example the general g0 one or the string specific a or the integer-specific i.