Hi this is code given in Chapman's book Fortran 95-2003 for scientists and engineers(3ed) on page 195
WRITE (*,100) index, time, depth, amplitude, phase
100 FORMAT('1',t20,'results for the test number ',i3,///,&
1x,'time = ',f7.0/, &
1x,'depth = ',f7.1,' meters',/, &
1x,'amplitude = ',f8.2/ &,
1x,'phase = ',f7.1)
To run it, I completed rest of the statements
program test
implicit none
INTEGER :: index = 10
real:: time=300.0,depth=330.0,amplitude=850.65,phase=30.0
WRITE (*,100) index, time, depth, amplitude, phase
100 FORMAT('1',t20,'results for the test number ',i3,///,&
1x,'time = ',f7.0/, &
1x,'depth = ',f7.1,' meters',/, &
1x,'amplitude = ',f8.2/ &,
1x,'phase = ',f7.1)
end program test
When i compile it with gfortran, I get following errors..
test.f90:12.31:
1x,'amplitude = ',f8.2/ &,
1
Error: Unexpected element '&' in format string at (1)
test.f90:13.8:
1x,'phase = ',f7.1)
1
Error: Non-numeric character in statement label at (1)
test.f90:13.9:
1x,'phase = ',f7.1)
1
Error: Invalid character in name at (1)
test.f90:7.12:
WRITE (*,100) index, time, depth, amplitude, phase
1
Error: FORMAT label 100 at (1) not defined
whats happening here ? I have seen another thread here at stackoverflow, where the question was about the control characters in fortran. Chapman discusses it in his book without mentioning that the feature of control characters has been deleted in Fortran 2003. So I am wondering if this is similar old thing not recognized by gfortran ?
There is a comma after the ampersand on the line of the format specification that has the 'ampersand = ' literal. To act as a continuation character in a non-character context the ampersand must be the last non-blank, non-comment character on the line.
The comma should probably be before the ampersand.
(Because the ampersand is not treated as a continuation character, the compiler thinks it is part of the format specification - hence the first error. The next line is then taken to start a new statement - hence the subsequent errors.)
Related
I tried to write some data in Fortran:
program Problem
DIMENSION X(8), W(8)
DATA X /0.0950125098D0, 0.2816035507D0, 0.4580167776D0, 0.6178762444D0
+ , 0.7554044083D0, 0.8656312023D0, 0.9445750230D0, 0.9894009349D0/
DATA W /0.1894506104D0, 0.1826034150D0, 0.1691565193D0, 0.1495959888D0
+ , 0.1246289712D0, 0.0951585116D0, 0.0622535239D0, 0.0271524594D0/
D = 0.D0
DO NJ=1,8
D = D + X(NJ) + W(NJ)
ENDDO
write(*,*) D
end
But I always get the following error message: Unexpected attribute declaration statement at (1).
Does anybody know why?
As already stated by others you should use the new fortran standard. If you do that you can just remove the "+" you used to indicate a continuation line (should have been in column 6) and instead add an ampersand "&" at the end of the line that should be continued.
Then the program compiles and runs. But as X and W are single precision you use too many digits in your data statement. Use implicit none and declare all variables. And get a textbook.
Below you find a minor update to your code which allows it to compile:
program Problemless
dimension X(8), W(8)
data X /0.0950125098D0, 0.2816035507D0, 0.4580167776D0,
+ 0.6178762444D0, 0.7554044083D0, 0.8656312023D0,
+ 0.9445750230D0, 0.9894009349D0/
data W /0.1894506104D0, 0.1826034150D0, 0.1691565193D0,
+ 0.1495959888D0, 0.1246289712D0, 0.0951585116D0,
+ 0.0622535239D0, 0.0271524594D0/
D = 0.D0
do NJ=1,8
D = D + X(NJ) + W(NJ)
enddo
write(*,*) D
end
Your code is written in Fixed-source form (See Section 6.3.3 of the Fortran standard). This implies that you cannot have anything beyond column 72. All I've done is to correct this in the above.
If you are learning fortran, I would suggest to stop using the fixed format and start using the free format.
no upvotes required for this post
I am perplexed with the way my program is performing. I am looping the following process:
1) take the name of a course from an input file
2) output the length of the name of the course
The problem is that the first value is always one less than the actual value of the string.
My first string contains 13 characters (including the colon), but nameOfClass.length() returns 12. The next string, the character count is 16 and indeed, nameOfClass.length() returns 16.
Every value after that also returns the expected value, it is only the first that returns the expected value minus 1.
Here's the (reduced) code:
std::ifstream inf("courseNames.txt");
int numberOfClasses = 10;
string nameOfClass;
for (int i = 0; i < numberOfClasses; i++) {
std::getline(inf, nameOfClass,':');
std::cout << nameOfClass.length() << "\n";
}
The file looks like this (courseNames.txt):
Pre-Calculus:
Public-Speaking:
English I:
Calculus I:
...etc. (6 more classes)
This is what I get:
12
16
10
11
Can anyone explain this behavior of the .length() function?
You have a problem, but you have the wrong conclusion. std::getline reads but doesn't output the delimiter, and so the first result is indeed 12.
It also doesn't output the delimiter for any subsequent lines, so why is there always one more? Well, look what is after that :. That's right, a new line!
Pre-Calculus:
^ a new line
So your nameOfClass variable, except for the first string, always stores an extra newline before the other characters.
The fix is easy enough, just ignore the newline after reading the string.
inf.ignore(); // ignore one character
So, not the first result was wrong, it was the only one right :)
I'm attempting to write a program that utilizes the sobel filter to detect edges in images. So first off, I've written down some of the requirements in some basic code, such as the x and y direction filters as arrays and also an attempt to read in a pgm image:
program edges
implicit none
integer, dimension(:,:), allocatable :: inp, outim, GX, GY
integer, parameter :: dp = selected_real_kind(15,300)
integer :: ky, kx, x, y, out_unit = 10, M, N, sx, sy, i, j
real(kind=dp) :: G
M = 5
N = 5
allocate(inp(M,N))
allocate(outim(M-2,N-2))
allocate(GX(3,3))
allocate(GY(3,3))
open(file = 'clown.pgm',unit=out_unit,status= 'unknown') !opening file to write to inp
read (out_unit,11) 'P2' !pgm magic number
read (out_unit,12) 50,50 !width, height
read (out_unit,13) 1 !max gray value
do M=-25,25
do N=-25,25
read (out_unit,*) inp(M,N)
end do
end do
11 format(a2)
12 format(i3,1x,i3)
13 format(i5)
This is my first time working with image manipulation in FORTRAN, apart from once when I printed an image out as a pbm file. The code for reading the image in is a replicate of what I used to print one out before, except I changed write to read.
So my question is, how can I read in an image that's in pgm format into the "inp" array, so that I can apply the sobel filter? When I run my attempt, I get the following errors:
read (out_unit,11) 'P2' !pgm magic number
1
Error: Expected variable in READ statement at (1)
sobel.f90:41:18:
read (out_unit,12) 50,50 !width, height
1
Error: Expected variable in READ statement at (1)
sobel.f90:42:18:
read (out_unit,13) 1 !max gray value
1
Error: Expected variable in READ statement at (1)
Thank you
The first mistake is, as the compiler states quite clearly, in this line:
read (out_unit,11) 'P2'
The compiler expects, because that's the way that Fortran is defined, to be told to read a value from out_unit into a variable, but 'P2' is a character literal (or whatever the heck the standard calls them), it's a string, it's not a variable.
The same mistake occurs in the next lines too. The compiler expects something like
integer :: p2 ! pgm magic number
...
read (out_unit,11) p2
etc. After execution of this version of the read statement the variable p2 holds the magic number read from the pgm file.
While I'm writing, calling the unit to be read from out_unit is just perverse and will, eventually, confuse you.
I am currently writing a code to simulate particle collisions. I am trying to open as much files as there are particles (N) and then put the data for positions and velocities in each of these files for each step of the time integration (using Euler's method, but that is not relevant). For that, I tried using a do loop so it will open all the files I need - then I put all the data in them with a different do loop later - and then close them all.
I first tried just doing a do loop to open the files - but it gave errors of the type "file already open in another unit", so I did the following:
module parameters
implicit none
character :: posvel
integer :: i, j, N
real :: tmax
real, parameter :: tmin=0.0, pi=3.14159265, k=500.0*10E3, dt=10.0E-5, dx=10.0E-3, g=9.806, ro=1.5*10E3
real, dimension(:), allocatable :: xold, xnew, vold, vnew, m, F, r
end module parameters
PROGRAM Collision
use parameters
implicit none
write(*,*) 'Enter total number of particles (integer number):'
read(*,*) N
allocate(xold(N))
allocate(vold(N))
allocate(xnew(N))
allocate(vnew(N))
allocate(m(N))
allocate(F(N))
allocate(r(N))
xold(1) = 0.0
vold(1) = 0.0
m(1) = 6.283*10E-9
r(1) = 10E-4
xold(2) = 5.0
vold(2) = 0.0
m(2) = 6.283*10E-9
r(2) = 10E-4
write(*,*) 'Type total time elapsed for the simulation(real number):'
read(*,*) tmax
do i = 1, N
write(posvel,"(a,i3.3,a)") "posveldata",i,".txt"
open(unit=i,file=posvel, status="unknown")
end do
do i = 1, N
close(unit=i)
end do
END PROGRAM Collision
The last ten lines are the ones that regard to my problem.
That worked in codeblocks - it opened just the number of files I needed, but I'm actually using gfortran and it gives me and "end of record" error in the write statement.
How can I make it to execute properly and give me the N different files that I need?
P.S.: It is not a problem of compilation, but after I execute the program.
Your character string in the parameter module has only 1 character length, so it cannot contain the full file name. So please use a longer string, for example
character(100) :: posvel
Then you can open each file as
do i = 1, N
write(posvel,"(a,i0,a)") "posveldata",i,".txt"
open(unit=i,file=trim(posvel), status="unknown")
end do
Here, I have used the format i0 to automatically determine a proper width for integer, and trim() for removing unnecessary blanks in the file name (though they may not be necessary). The write statement can also be written more compactly as
write(posvel,"('posveldata',i0,'.txt')") i
by embedding character literals into the format specification.
The error message "End of record" comes from the above issue. This can be confirmed by the following code
character c
write(c,"(a)") "1"
print *, "c = ", c
write(c,"(a)") "23" !! line 8 in test.f90
print *, "c = ", c
for which gfortran gives
c = 1
At line 8 of file test.f90
Fortran runtime error: End of record
This means that while c is used as an internal file, this "file" does not have enough space to accommodate two characters (here "23"). For comparison, ifort14 gives
c = 1
forrtl: severe (66): output statement overflows record, unit -5, file Internal Formatted Write
while Oracle Fortran12 gives
c = 1
****** FORTRAN RUN-TIME SYSTEM ******
Error 1010: record too long
Location: the WRITE statement at line 8 of "test.f90"
Aborted
(It is interesting that Oracle Fortran reports the record to be "too long", which may refer to the input string.)
I am trying to read a file cs251_1.dat in Fortran and then trying to create a new file using the data from cs251_1.dat. The file cs251_1.dat was written by another Fortran program and the data inside this file is two spaces followed by a three digit number followed by two spaces with a total of four numbers on a line. However, I get the following error
C:\Users\Cornelius\Documents\~Source5.f:3:
open(5, File = 'C:cs251_1.dat')
1
C:\Users\Cornelius\Documents\~Source5.f:6: (continued):
Integer A
2
Statement at (2) invalid in context established by statement at (1)
This is the program:
open(5, File = 'C:cs251_1.dat')
open(6, File = 'C:cs251_2.out')
Integer A, B, C, D
total = 0.
E = 1
Integer Selection = 1
total = Selection + 1
Print *, 'Let''s do some math!!'
* 16 continue
Read(5, 65) A, B, C, D
65 Format(I4, I4, I4, I4)
write(6,66)
66 Format(4(2x, I4))
You can't have a declaration after an active statement. That is what your compiler means by "Statement at (2) invalid in context established by statement at (1)". So change the order of the statements.