IF-block syntax - if-statement
I'm trying to compare a month array to check whether each number is a odd month or even month so that I can make files labelled as the month//date//year.txt and upload lines matching the date from another files into the respective .txt file.
My output should be 90 .txt files, each containing the lines matching the particular date from APM_FORMATTED.txt.
PROGRAM APM_TEST
IMPLICIT NONE
INTEGER :: READSTATUS, YEAR_MIN, MONTH_MIN, DAY_MIN, YEAR_MAX, MONTH_MAX, DAY_MAX, I, IND, IND1, D, D1, D2
CHARACTER(13) :: DATE_INPUT
CHARACTER(2) :: FILE_DAY, FILE_MONTH, FILE_YEAR, CURRENT_DAY, CURRENT_MONTH
CHARACTER(632) :: ROW1
INTEGER, DIMENSION(1,6) :: M
INTEGER, DIMENSION(1,6) :: N
INTEGER, DIMENSION(1,3) :: MON
WRITE(*,'(" ENTER DATE RANGE OF FILE (E.G. 010413-010713):")', ADVANCE = "NO")
READINT : DO
READ (*,*,IOSTAT=READSTATUS) DATE_INPUT
IF (READSTATUS==0) THEN
EXIT READINT
ELSE
WRITE(*,'(/"READ ERROR. PLEASE RE-INPUT:")')
ENDIF
ENDDO READINT
READ(DATE_INPUT(5:6), '(I2)') YEAR_MIN
READ(DATE_INPUT(3:4), '(I2)') MONTH_MIN
READ(DATE_INPUT(1:2), '(I2)') DAY_MIN
READ(DATE_INPUT(12:13), '(I2)') YEAR_MAX
READ(DATE_INPUT(10:11), '(I2)') MONTH_MAX
READ(DATE_INPUT(8:9), '(I2)') DAY_MAX
IND=1
IND1=1
M=(/1,3,5,7,9,11/)
N=(/4,6,8,10,12/)
36 DO MON=MONTH_MIN, MONTH_MAX
IF (ANY(M.EQ.MON(IND))) THEN
DO D=DAY_MIN,31
FILE_DAY=DATE_INPUT(1:2)
FILE_MONTH=DATE_INPUT(3:4)
FILE_YEAR=DATE_INPUT(5:6)
OPEN(UNIT=201, FILE="APM_FORMATTED.TXT")
OPEN(IND1, FILE=(FILE_MONTH//FILE_DAY//FILE_YEAR//".TXT"), ACTION="WRITE", STATUS="NEW")
45 DO I=1,200000
READ(201,'(A632)') ROW1
IF (ROW1(1:3).EQ.'APM') THEN
READ(ROW1(41:42), '(I2)') CURRENT_DAY
READ(ROW1(43:44), '(I2)') CURRENT_MONTH
IF (CURRENT_MONTH.EQ.MON .AND. CURRENT_DAY.EQ.D) THEN
WRITE(IND1,*) ROW1
ELSE
GOTO 45
ENDIF
ELSE
ENDIF
ENDDO
IND1=IND1+1
CLOSE(IND1)
CLOSE(201)
ENDDO
ELSEIF (ANY(N.EQ.MON)) THEN
DO D1=DAY_MIN,30
FILE_DAY=DATE_INPUT(1:2)
FILE_MONTH=DATE_INPUT(3:4)
FILE_YEAR=DATE_INPUT(5:6)
OPEN(UNIT=201, FILE="APM_FORMATTED.TXT")
OPEN(IND1, FILE=(FILE_MONTH//FILE_DAY//FILE_YEAR//".TXT"), ACTION="WRITE", STATUS="NEW")
73 DO I=1,200000
READ(201,'(A632)') ROW1
IF (ROW1(1:3).EQ.'APM') THEN
READ(ROW1(41:42), '(I2)') CURRENT_DAY
READ(ROW1(43:44), '(I2)') CURRENT_MONTH
IF (CURRENT_MONTH.EQ.MON .AND. CURRENT_DAY.EQ.D1) THEN
WRITE(IND1,*) ROW1
ELSE
GOTO 73
ENDIF
ELSE
ENDIF
ENDDO
IND1=IND1+1
CLOSE(IND1)
CLOSE(201)
ENDDO
ELSEIF (ANY(M.EQ.4)) THEN
DO D2=DAY_MIN,28
FILE_DAY=DATE_INPUT(1:2)
FILE_MONTH=DATE_INPUT(3:4)
FILE_YEAR=DATE_INPUT(5:6)
OPEN(UNIT=201, FILE="APM_FORMATTED.TXT")
OPEN(IND1, FILE=(FILE_MONTH//FILE_DAY//FILE_YEAR//".TXT"), ACTION="WRITE", STATUS="NEW")
101 DO I=1,200000
READ(201,'(A632)') ROW1
IF (ROW1(1:3).EQ.'APM') THEN
READ(ROW1(41:42), '(I2)') CURRENT_DAY
READ(ROW1(43:44), '(I2)') CURRENT_MONTH
IF (CURRENT_MONTH.EQ.MON .AND. CURRENT_DAY.EQ.D2) THEN
WRITE(IND1,*) ROW1
ELSE
GOTO 101
ENDIF
ELSE
ENDIF
ENDDO
IND1=IND1+1
CLOSE(IND1)
CLOSE(201)
ENDDO
ELSE
GOTO 36
ENDIF
IND=IND+1
DAY_MIN=1
ENDDO
END PROGRAM APM_TEST
Errors:
error FOR2614: assignment between arrays of differing rank
error FOR2614: assignment between arrays of differing rank
error FOR2799: DO control variable MON is not scalar
error FOR2979: expected 2 subscripts but found 1 for array MON
error FOR3041: operands to relational operator .EQ. are of incompatible data type
error FOR3041: operands to relational operator .EQ. are of incompatible data type
error FOR3048: illegal data type to binary logical operator .AND.
error FOR3156: array shapes differ in dimension 2 (extent 6 and 3)
error FOR3041: operands to relational operator .EQ. are of incompatible data type
error FOR3041: operands to relational operator .EQ. are of incompatible data type
error FOR3048: illegal data type to binary logical operator .AND.
error FOR3041: operands to relational operator .EQ. are of incompatible data type
error FOR3041: operands to relational operator .EQ. are of incompatible data type
error FOR3048: illegal data type to binary logical operator .AND.
You have syntax errors on lines 38 and 45 (and very likely other lines as well). Look into your favorite book or online tutorial about correct IF block and statement syntax. The basic IF-block syntax in Fortran is in the form:
IF(scalar-logical-expr)THEN
...
ELSEIF(scalar-logical-expr)THEN
...
ELSE
...
ENDIF
Related
Error: Unclassifiable statement at (1) in Fortran for calculations [duplicate]
This program: C This program calculates cos(x**2) PROGRAM COSX_SQUARE IMPLICIT NONE INTEGER a REAL y, r PRINT*, 'INPUT THE DEGREE' PRINT*, 'BETWEEN 0 AND 360' READ*, a a*(3.141592/180) = y C This part determines minus sign and calculates the function IF (a .GT. 90) THEN r = -(1-(y**4)/2+(y**8)/24-(y**12)/720+(y**16)/40320) ELSEIF (a .GE. 270) THEN r = 1-(y**4)/2+(y**8)/24-(y**12)/720+(y**16)/40320 ELSEIF (a .GT. 360) THEN PRINT*, 'INVALID DEGREE' PRINT*, 'DEGREE MUST BE BETWEEN 0 AND 360' ELSEIF (a .LT. 0) THEN PRINT*, 'INVALID DEGREE' PRINT*, 'DEGREE MUST BE BETWEEN 0 AND 360' END IF PRINT*, 'THE RESULT OF COS', a, 'SQUARE IS = ', r STOP END Gives this error: a*(3.141592/180)=y 1 Error: Unclassifiable statement at (1) I already defined a as INTEGER. Why this error keeps coming?
Yep. It is an expression which begins a statement. Maybe change it to y = a*(3.141592/180) if that is what you really meant.
An error combining DO and IF in Fortran
This is a part of code that I am writing in Visual FORTRAN 6.6A: . . . DO 24 I=1,80 24 IF ((NODNUM(1) .EQ. I) .AND. (CAUCHY(3,2) .LT. CTI(I+12))) THEN ARRAY(1)=C1*0.99 END IF . . . and this error occurs when I compile it: *--------------------Configuration: ovl30u_moon1 - Win32 Debug-------------------- Compiling Fortran... C:\Documents and Settings\XPMUser\Desktop\ovl30u_moon1.f C:\Documents and Settings\XPMUser\Desktop\ovl30u_moon1.f(567) : Error: This is not a valid termination statement for a DO construct. 24 IF ((NODNUM(1) .EQ. I) .AND. (CAUCHY(3,2) .LT. CTI(I+12))) THEN ---^ C:\Documents and Settings\XPMUser\Desktop\ovl30u_moon1.f(569) : Error: An ENDIF occurred without a corresponding IF THEN or ELSE statement. END IF -----------^ Error executing df.exe. ovl30u_moon1.obj - 2 error(s), 0 warning(s)* I also tried this but error exists yet: DO 24 I=1,80 24 IF ((NODNUM(1) .EQ. I) .AND. (CAUCHY(3,2) .LT. CTI(I+12))) THEN ARRAY(1)=C1*0.99 END IF END DO Any advice appreciated.
The termination of a do loop using a label is not valid the way you specify it. For FORTRAN 77 use: DO 24 I=1,80 IF ((NODNUM(1) .EQ. I) .AND. (CAUCHY(3,2) .LT. CTI(I+12))) THEN ARRAY(1)=C1*0.99 END IF 24 CONTINUE In Fortran 90+ you could simply leave out the label: DO I=1,80 IF ((NODNUM(1) .EQ. I) .AND. (CAUCHY(3,2) .LT. CTI(I+12))) THEN ARRAY(1)=C1*0.99 END IF END DO Or, if you depend on the label, you could use label: DO I=1,80 IF ((NODNUM(1) .EQ. I) .AND. (CAUCHY(3,2) .LT. CTI(I+12))) THEN ARRAY(1)=C1*0.99 END IF END DO label
To add to Alexander Vogt's answer there is another way to restate your particular case. While it is not allowed to use an if construct as the termination of the non-block (labelled) do it is possible to use an if statement: DO 24 I=1,80 24 IF ((NODNUM(1) .EQ. I) .AND. (CAUCHY(3,2) .LT. CTI(I+12))) ARRAY(1)=C1*0.99 You can, but you really shouldn't: use the block construct as in the other anwer. For more detail, see Fortran 2008 8.1.6.3 and R214.
FORTRAN 77 "Error: Unclassifiable statement at (1)"
This program: C This program calculates cos(x**2) PROGRAM COSX_SQUARE IMPLICIT NONE INTEGER a REAL y, r PRINT*, 'INPUT THE DEGREE' PRINT*, 'BETWEEN 0 AND 360' READ*, a a*(3.141592/180) = y C This part determines minus sign and calculates the function IF (a .GT. 90) THEN r = -(1-(y**4)/2+(y**8)/24-(y**12)/720+(y**16)/40320) ELSEIF (a .GE. 270) THEN r = 1-(y**4)/2+(y**8)/24-(y**12)/720+(y**16)/40320 ELSEIF (a .GT. 360) THEN PRINT*, 'INVALID DEGREE' PRINT*, 'DEGREE MUST BE BETWEEN 0 AND 360' ELSEIF (a .LT. 0) THEN PRINT*, 'INVALID DEGREE' PRINT*, 'DEGREE MUST BE BETWEEN 0 AND 360' END IF PRINT*, 'THE RESULT OF COS', a, 'SQUARE IS = ', r STOP END Gives this error: a*(3.141592/180)=y 1 Error: Unclassifiable statement at (1) I already defined a as INTEGER. Why this error keeps coming?
Yep. It is an expression which begins a statement. Maybe change it to y = a*(3.141592/180) if that is what you really meant.
Fortran 90: Assigning a character to a real kind in Fortran
Apologies for inconvenience , I have resubmitted the code now. Problem: I am trying to write a program that reads the precipitation from a binary (.DAT) file. It calculates the value of precipitation at each grid and for every grid the maximum value month is returned as output. For example if there was a value of 25 highest in the month of June then our output value should be "Jun". implicit none integer,parameter :: ix=44,iy=27,nyr=12 integer :: ntot real :: v_obs(ix,iy,nyr),TestVal,b(ix,iy,nyr),wet(ix,iy) real:: Mon(12),Y(12),missing_obs,missing_mod,missing integer :: ii,jj,i,j,k,ik,jk,irec,m,n character (130) dir,jan,feb,mar,apr,may,jun,jul,aug,sep,oct,nov,dec data missing_obs/-999000000/ data missing/-999./ open(21,file='C:/Fortran/test-dat.dat',access='direct',recl=ix*iy*nyr,form='unformatted') open(23,file='C:/wet-month.dat',access='direct',recl=ix*iy*nyr,form='unformatted') irec=1 Do j=1,nyr read(21,rec=irec) ((v_obs(ii,jj,j),ii=1,ix),jj=1,iy) ntot=0 do ik=1,nyr ntot=ntot+1 Y(ik)=v_obs(ii,jj,ik) enddo if (Y(ik) .eq. missing_obs)then wet=-999 go to 199 endif enddo Mon(1)=v_obs(ii,jj,1) Mon(2)=v_obs(ii,jj,2) Mon(3)=v_obs(ii,jj,3) Mon(4)=v_obs(ii,jj,4) Mon(5)=v_obs(ii,jj,5) Mon(6)=v_obs(ii,jj,6) Mon(7)=v_obs(ii,jj,7) Mon(8)=v_obs(ii,jj,8) Mon(9)=v_obs(ii,jj,9) Mon(10)=v_obs(ii,jj,10) Mon(11)=v_obs(ii,jj,11) Mon(12)=v_obs(ii,jj,12) TestVal=MAXVAL(Mon) If (TestVal .eq. Mon(1)) then wet=jan else if (TestVal .eq. Mon(2)) Then wet=feb else if (TestVal .eq. Mon(3)) Then wet=mar else if (TestVal .eq. Mon(4)) Then wet=apr else if (TestVal .eq. Mon(5)) Then wet=may else if (TestVal .eq. Mon(6)) Then wet=jun else if (TestVal .eq. Mon(7)) Then wet=jul else if (TestVal .eq. Mon(8)) Then wet=aug else if (TestVal .eq. Mon(9)) Then wet=sep else if (TestVal .eq. Mon(10)) Then wet=oct else if (TestVal .eq. Mon(11)) Then wet=nov else if (TestVal .eq. Mon(12)) Then wet=dec endif 199 continue irec=1 do k=1,nyr write(23,rec=irec)((wet(ii,jj),ii=1,ix),jj=1,iy) irec=irec+1 enddo close(21) close(22) end The compliation error says You cannot assign an expression of type CHARACTER(LEN=130) to a variable of type REAL(KIND=1)" i.e: "wet=jan". But I want to save data as character for each grid point.Please help to resolve this error.
The problem is all those lines wet=jan, wet=feb, etc. As I read from your code wet is real,dimension(44,27). jan and feb are of type character(130). Those are incompatible (as the compiler says).
Syntax error, found .and. and .or.
I just wanted to modify a small part of a very old program and I can't for the life of me figure out what I've done to anger the Fortran gods. The original code has the following line: if (r.gt.rstep) xappad = xappad*fakm which I have modified to: if (r.gt.0.58*rstep .and. r.lt.1.42*rstep) .or. (r.gt.2.08*rstep : .and. r.lt.2.92*rstep) xappad = xappad*fakm Which gives me the errors: sp-co-2-MODIFIED.for(785): error #5082: Syntax error, found '.OR.' when expecting one of: BLOCK BLOCKDATA PROGRAM MODULE TYPE COMPLEX BYTE CHARACTER DOUBLE DOUBLECOMPLEX ... if (r.gt.0.58*rstep .and. r.lt.1.42*rstep) .or. (r.gt.2.08*rstep -------------------------------------------------------------------------^ sp-co-2-MODIFIED.for(786): error #6090: An array-valued operand is required in this context. : .and. r.lt.2.92*rstep) xappad = xappad*fakm ------^ sp-co-2-MODIFIED.for(786): error #6087: An array assignment statement is required in this context. : .and. r.lt.2.92*rstep) xappad = xappad*fakm -------------------------------------------^
I really don't know much FORTRAN, but it looks to me like you're missing a pair of parentheses around the conditional: if ((r.gt.0.58*rstep .and. r.lt.1.42*rstep) .or. (r.gt.2.08*rstep .and. r.lt.2.92*rstep)) xappad = xappad*fakm